根据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)运行?
答案 0 :(得分:1)
是的,你的第二个伪代码是正确的。插入排序的通常分析是外循环依次插入每个元素(O(n)迭代),内循环将该元素移动到正确的位置(O(n)迭代),总共O(n) ^ 2)。但是,由于您的第二个quicksort
会留下一个数组,可以通过置换最大threshold
块内的元素进行排序,因此每个元素最多移动threshold
个位置,新分析为{ {1}},相当于分别在每个块上运行插入排序。
Bentley在1999年版的编程珍珠中描述,这个想法(每个维基百科)避免了多次启动和停止插入排序循环的开销(实质上,我们已经在插入循环中有一个自然的标记值。数组)。恕我直言,这是一个可爱的想法,但鉴于现在商品硬件的性能特征有多么不同,显然还不是很好(具体来说,最终的插入类型需要另外通过数据,这已经相对更昂贵,并且启动循环的成本(在寄存器中移动一些值)已经相对便宜了。)