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

Algorithm 在快速排序中使用插入排序一次,algorithm,sorting,pseudocode,Algorithm,Sorting,Pseudocode,据 使用插入排序…进行小数组上的调用(即 长度小于阈值k(通过实验确定)。这 可以通过在小于k时停止递归来实现 元素保留,使整个数组按k排序:每个元素 离最终位置最多有k个位置。然后,一个 单次插入排序过程在O(k×n)时间内完成排序 我不确定我是否理解正确。一种涉及多次调用插入排序的方法是 quicksort(A, i, k): if i+threshold < k: p := partition(A, i, k) quicksort(A, i, p - 1)

使用插入排序…进行小数组上的调用(即 长度小于阈值k(通过实验确定)。这 可以通过在小于k时停止递归来实现 元素保留,使整个数组按k排序:每个元素 离最终位置最多有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)

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

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


Bentley在1999年版的Programming Pearls中描述了这个想法(根据Wikipedia),它避免了多次启动和停止插入排序循环的开销(本质上,数组中已经有了插入循环的自然哨兵值)。IMHO,这是一个很好的想法,但考虑到目前商品硬件的性能特征有多大的不同(特别是,最终插入排序需要对数据进行另一次传递,这会变得相对昂贵,并且启动循环的成本(移动寄存器中的一些值),这显然不是一个好主意)成本相对较低)。

是否要详细介绍您所指的性能特征?当然,对缓存中碰巧存在的元素进行插入排序更有意义,因为它们刚刚被分区,但您是否还想到了其他事情?@rici,与内存引用相比,在寄存器中乱序几个值的成本相对较低。另一方面,错过分支预测的成本变得昂贵得多。插入测试中的循环结束测试很可能在每次循环结束时预测错误;在single insertionsort版本中,这种情况只发生一次。当然,没有基准,一切都只是空泛的猜测。@rici是的,谁知道呢?因为这个原因,我的批评措辞非常温和。@DavidEisenstat你刚才抄袭了我的问题。你的伪代码和我的有什么不同?你所谓的快速排序,我称之为排序。
sort(A)
 quicksort(A, 0, A.length-1)
 insertionsort(A, 0, A.length-1)