二分法插入排序沿用了插入排序的思路,而且由于[R0,Ri-1]是有序序列,在寻找Ri的插入位置时,可以采用二分查找法搜索有序区间中比第一个Ri小的元素,这样就减少了比较次数,提高了插入排序算法的性能。\n\n以长度为6的序列 {6,3,5,4,1,2} 的二分法插入排序过程做示范:\n第一趟排序:[3 6] 5 4 1 2 (3插入6之前)\n第二趟排序:[3 5 6] 4 1 2 (5插入6之前)\n第三趟排序:[3 4 5 6] 1 2 (4插入5之前)\n第四趟排序:[1 3 4 5 6] 2 (1插入3之前)\n第五趟排序:[1 2 3 4 5 6] (2插入3之前)\n(注:用中括号括起来的是有序区间,之后的元素序列为待排区间)\n\n可以看见二分法插入的排序过程和插入排序的过程是一摸一样的,但是其中寻找插入位置的过程是不一样的。\n\n用第5趟排序过程作详细介绍第5趟排序过程需要寻找R5,即2的插入位置:\n 第五趟排序前的序列:[1 3 4 5 6] 2\n 首先,定义右边界right为R4,值为6,左边界为R0,值为1。[R0,R4]的中间元素为R(4+0)/2 = R2,值为4,2比中间元素小,因此元素2的插入位置一定在[R0,R2]之间,这时右边界置为中间元素的前一位,R1。\n [R0,R1]的中间元素为R(1+0)/2 = R0,值为1,2比1大,因此元素2的插入位置应该在R0之后,这时将左边界置位中间元素的后一位,即R1。\n 此时搜寻的区间变为[R1,R1],中间元素也为R1,值为3,2小于R1,置右边届为中间元素前一位,即R0,左边界的位置大于了右边届,比较结束。此时的左边界R1即为2的插入位置。\n 将2插入序号1的位置上,序列由:[1 3 4 5 6] 2 变为:[1 2 3 4 5 6]。\n 使用二分查找法后,一共经过了3次比较找到插入位置。直接插入算法则需要5次比较(分别与6,5,4,3,1比较),可见二分查找法减少了插入发排序过程中比较的次数。
void swap(int *a, int *b)
{
int temp = *a;
*a = *b;
*b = temp;
}
void binarySort(int *arr, int length)
{
if (arr == NULL || length <= 0)return;
int left, right;
for (int i = 1; i < length; ++i)
{
left = 0;
right = i - 1;
int temp = arr[i];
while (left <= right)
{
int mid = (left + right) / 2;
if (arr[mid]>arr[i])right = mid - 1;
else left = mid + 1;
}
for (int j = i - 1; j >= left; --j)
{
arr[j + 1] = arr[j];
}
arr[left] = temp;
}
}