使用二进制搜索改善插入排序的最坏情况运行时间

时间:2012-02-27 15:37:55

标签: algorithm binary-search insertion-sort

while循环使用线性搜索向后扫描。但是,我们知道while循环中的数组已经排序。因此,我们可以用二进制搜索替换线性搜索,以便O(n)将变为O(lg n)。但是,我对此的看法是它不会有助于减少总体时间,因为我们仍然需要将元素向前移动一个索引,这将始终采用(向后步骤数(n))次。总的来说,运行时间保持为O(n ^ 2),并且在这种情况下无法实现O(n lg n)。如果我以错误的方式接近这个,请告诉我。

INSERTION-SORT(A)

 for j = 2 to length[A]
  do key = A[j]
     i = j - 1

  while i > 0 and A[i] > key
    A[i+1] = A[i]
    i = i - 1

  A[i+1] = key

4 个答案:

答案 0 :(得分:5)

插入排序会推送数组的元素,以便将空格释放到行中的下一个元素。
因此,如果您使用二进制搜索找到输入新元素的位置,您仍需要将该索引之后的所有元素向前推进一步(向右)。
所以给定一个向后排序的数组:10,9,8,7,6,5,4,3,2,1
你需要向右推i-1才能插入第i个元素(即使你使用二分搜索) - 最坏情况时间:O(n ^ 2)
如果你可以逐个插入元素到一个列表,你不必推送元素,但你必须“支付”搜索列表中的正确位置(所以在这个实现中WCT是O (N ^ 2))。

这个问题的解决方案将是列表和数组之间的某种协同作用,这样你就可以在O(1)时间内(如在数组中)到达第i个元素,并且可以将新元素推送到给定位置(在O(1)时间之后(如列表中所述)在指数j)之后说 - 如果你成功了,我相信你将赢得永恒的荣耀!

答案 1 :(得分:0)

基本上,插入排序所需的时间由三个因素组成。

  1. 遍历SOURCE数组中的每个元素
  2. 找到将其插入DESTINATION数组的正确位置
  3. 执行插入。
  4. 你在谈论的是关注步骤2.一个天真的方法是通过完整的DESTINATION数组来找到插入位置,这需要O(n)。但是,您可以进行二进制搜索,只需要O(log(n))

    您仍需要执行插入操作,但其成本取决于数据结构。如果您使用链接列表,它将始终花费您不间断的时间。如果你使用一个简单的数组,你可以做一个memcpy(),它应该同样可以扩展。您在伪代码中使用的方法是一种非常天真的方法,在实际实现中永远不会有效。有关INSERT for Arrays的实际示例,请参阅http://www.docjar.com/html/api/java/util/ArrayList.java.html#421System.arraycopy()O(1)

答案 2 :(得分:0)

二进制搜索插入点可以提供轻微改进,主要是通过从向上移动元素的循环中删除键比较。在对大量数据进行排序之前,差异不会很大。当然,如果你有一个大型数据集,你应该使用更好的排序算法......

答案 3 :(得分:-1)

我认为运行时间是O(nlgn)..二进制搜索需要lgn时间..并且在最坏的情况下移动元素需要O(n / 2),这是“渐近相同” as O(n)[我找不到'属于'符号..:D]

我不认为你提供的伪代码是二进制搜索的插入排序。