显然,对于已经排序好的数组而言,二分法比直接遍历的方法要省去很多不必要的比较过程,显著性的节约了查找或排序所需要的时间。
二分法排序的主要思想为:
1.对数组取左端(left)和右端(right),在对已经用循环法排序后的数组取左(L)和右(R)。
并且用tmp保存当前arr[i]的元素,避免后续被覆盖。
注意:当排序到第i个元素时,R=i-1,而不是right。
2.然后,对用arr[i](tmp)和最中间的位置(mid=(L+R)/2)进行循环比较。
若小于arr[mid],则将R迁移到mid-1;
若大于或等于arr[mid],则将L迁移到mid+1。
3.通过退出循环while(L<=R)后,L即为要插入的位置。
4.将L后面的所有元素后移,在L的位置进行插入即可完成。
二分法插入函数:
void BinInsertSort(int arr[], int left, int right)
{
for (int i = left + 1; i < right; i++)
{
int L = left;
int R = i - 1;
int tmp = arr[i];
while (L <= R)//此处,是要加等号的,在tmp位于在L=R右边时,将L后移一位才是真正要插入的位置
{
int mid = (L + R) / 2;
if (tmp >= arr[mid])//此处的等号是为了保证排序的稳定性,使其排在L的后面
L = mid + 1;
else if (tmp < arr[mid])
R = mid - 1;
}
//上述L的位置即为所要插入的位置
for (int j = i; j > L; j--)
{
arr[j - 1] = arr[j];
}
arr[L] = tmp;
}
}
打印函数:
void PrintArray(int arr[], int left, int right)
{
for (int i = left; i < right; i++)
{
printf("%d ", arr[i]);
}
printf("\n");
}
测试:
void main()
{
int arr[] = { 49,38,65,97,76,13,27,49 };
int n = sizeof(arr) / sizeof(arr[0]);
PrintArray(arr, 0, n);
BinInsertSort(arr, 0, n);
PrintArray(arr, 0, n);
}