2013-03-03 105 views
0

你好我被要求通过使用二分搜索而不是线性提高插入排序。现在的问题是,由于数据比较,现在最好的情况是O(n log n),而不是O(n),这使得程序在某些情况下如果不是较慢,就等于。这里是我的二进制插入排序代码:直接和二进制插入排序

void InsertionSort(int data[], int size) 
{ 
    int index = -1; 
    for(int i = 1,temp,j;i<size;i++) 
    { 
     temp = data[i];//DM O(N) 
     int high = i,low = 0,mid;//DM O(N) 
     while(low <= high)//DC O(nlogn) 
     { 
      mid = (low + high) /2; 
      if(temp < data[mid]) 
      { 
       high = mid - 1; 
       index = mid; 
      } 

      else if (temp > data[mid]) 
      { 
       low = mid + 1;  
      } 

      else if(data[mid] == temp) 
      { 
       index = mid; 
       break; 
      } 

     } 
     for(j = i;j > index;j--) 
     { 
      data[j] = data[j-1];//DC Worst Case O(n*n) but the exact is summation of n(n+1)/2 nad best case o(1) 
     } 
     data[j] = temp;//DM O(n) 
    } 
} 
+0

但它是改善最坏的情况下,对吧? – 2013-03-03 11:12:13

+0

@OliCharlesworth不,它仍然是O(n * n),因为它会产生n(n + 1)/ 2个移位 – user1948105 2013-03-03 11:13:08

+0

事实上,这不会影响渐近复杂性,但它可能会改善实践中的运行时间。 – 2013-03-03 11:15:20

回答

0

你可以开始你的二进制搜索与有利于最好的情况下的偏见阶段。而不是直接去(low+high)/2的,开始在位置i-1,然后i-2,然后i-4i-8i-16i-32 ......直到找到一个更小的元素,或者直到i-whatever变得比low低。然后继续进行普通的二分查找。

请注意,此优化需要付出代价。最好的情况---排序或几乎排序的数据---需要O(N)个时间,但是对于简单的二进制搜索版本,平均情况和最坏情况会稍微慢一些。

void InsertionSort (int data[], int size) 
{ 
    int i, j, high, low, mid, hop; 
    int temp; 

    for (i=1; i<size; i++) 
    { 
     temp = data[i]; 

     high = i; 
     low = 0; 
     hop = 1; 

     do 
     { 
      mid = high - hop; 
      hop <<= 1; 

      if (temp < data[mid]) 
       high = mid; 
      else 
       low = mid + 1; 
     } 
     while (low+hop <= high); 

     while (low != high) 
     { 
      mid = (low + high)/2; 

      if (temp < data[mid]) 
       high = mid; 
      else 
       low = mid + 1; 
     } 

     for(j=i; j>low; j--) 
      data[j] = data[j-1]; 

     data[j] = temp; 
    } 
} 

还要注意high分配mid而不是mid+1。其中temp==data[mid]的处理与temp>data[mid]的情况完全相同。这是为了保持插入排序的良好属性:它是一个stable sort。但是,排序纯整数时没有区别。

+0

我不明白这部分做 { mid = high-hop; hop + = 1; if(temp user1948105 2013-03-06 13:54:57

+0

@ user1948105:它不是hop + = 1,而是hop << = 1,它与hop * = 2或hop = hop * 2相同。跳从1开始,每次乘以2。因此,中期从高点开始,然后以更高的速度进一步增加:高2,高4,高8 ... – comocomocomocomo 2013-03-21 06:10:46

-1

你也可以更换其他最后:用简单的else 因为很明显这是为真else if(data[mid] == temp)如果前两者是不正确的......

+0

它会没有区别 – user1948105 2013-03-04 09:09:18