在快速排序中使用插入排序一次

时间:2014-08-27 23:22:29

标签: algorithm sorting pseudocode

根据here

  

使用插入排序...对小阵列进行调用(即在哪里   长度小于实验确定的阈值k)。这个   可以通过在小于k时简单地停止递归来实现   剩下的元素,留下整个数组k-sorted:每个元素   将离最终位置最多k个位置。然后,一个   单个插入排序传递在O(k×n)时间内完成排序。

我不确定我是否理解正确。一种方法,包括多次调用插入排序是

quicksort(A, i, k):
  if i+threshold < k:
    p := partition(A, i, k)
    quicksort(A, i, p - 1)
    quicksort(A, p + 1, k)
  else
    insertionsort(A, i, k)

但是这会为每个子数组调用insertionsort()。这听起来像插入排序只能调用一次,但我有点不理解这一点,因为调用插入排序的次数并不重要,它通常比快速排序慢。

这个想法是这样的吗?

sort(A)
 quicksort(A, 0, A.length-1)
 insertionsort(A, 0, A.length-1)

所以基本上在最后调用插入排序一次?你怎么知道它只需要一次通过而不是在O(n)运行?

1 个答案:

答案 0 :(得分:1)

是的,你的第二个伪代码是正确的。插入排序的通常分析是外循环依次插入每个元素(O(n)迭代),内循环将该元素移动到正确的位置(O(n)迭代),总共O(n) ^ 2)。但是,由于您的第二个quicksort会留下一个数组,可以通过置换最大threshold块内的元素进行排序,因此每个元素最多移动threshold个位置,新分析为{ {1}},相当于分别在每个块上运行插入排序。

Bentley在1999年版的编程珍珠中描述,这个想法(每个维基百科)避免了多次启动和停止插入排序循环的开销(实质上,我们已经在插入循环中有一个自然的标记值。数组)。恕我直言,这是一个可爱的想法,但鉴于现在商品硬件的性能特征有多么不同,显然还不是很好(具体来说,最终的插入类型需要另外通过数据,这已经相对更昂贵,并且启动循环的成本(在寄存器中移动一些值)已经相对便宜了。)