折半插入排序
一、基本概念
当直接插入排序进行到某一趟时,对于 r[i].key 来讲,前边 i-1 个记录已经按关键字有序。此时不用直接插入排序的方法,而改为折半查找,找出 r[i].key 应插的位置,然后插入。这种方法就是折半插入排序( Binary insertion sort )。
二、具体操作
在将一个新元素插入已排好序的数组的过程中,寻找插入点时,将待插入区域的首元素设置为a[low],末元素设置为a[high],则轮比较时将待插入元素与a[m],其中m=(low+high)/2相比较,如果比参考元素大,则选择a[low]到a[m-1]为新的插入区域(即high=m-1),否则选择a[m+1]到a[high]为新的插入区域(即low=m+1),如此直至low<=high不成立,即将此位置之后所有元素后移一位,并将新元素插入a[high+1]。
三、稳定性及复杂度
折半插入排序算法是一种稳定的排序算法,比直接插入算法明显减少了关键字之间比较的次数,因此速度比直接插入排序算法快,关键字的比较次数由于采用了折半查找而减少,数量级为O(nlog 2n) ,但记录移动的次数没有变,所以折半插入排序算法的时间复杂度仍然为O(n^2),与直接插入排序算法相同。附加空间O(1)。
四、示例代码:
public class ZhebanCharuPaixu { public static void main(String[] args) { // 待排序的数组 int[] array = { 1, 0, 5, 3, 9, 10, 6, 7 }; binaryInsertSort(array); // 显示排序后的结果 System.out.print("排序后: "); for (int i = 0; i < array.length; i++) { System.out.print(array[i] + "->"); } } private static void binaryInsertSort(int[] array) { if(array.length == 0){ return; } for (int i = 1; i < array.length; i++) { int temp = array[i]; int low = 0; int high = i - 1; while (low <= high) { // int mid = (high - low) / 2 + low; // 下面这样可能会有整型溢出的问题 int mid = (low + high) / 2; if (temp < array[mid]) { high = mid - 1; } else { low = mid + 1; } } // 下面的for循环中,有人用 j > mid; 还有人用 j >= high + 1,这个还需要再看看 for (int j = i; j >= low + 1; j--) { array[j] = array[j - 1]; } array[low] = temp; // 此处用 array[high+1] = temp; 也可 } } }