折半插入排序需要注意的是:
- 折半插入的顺序表必须有序
- 比较次数是运用折半查找减少了比较次数,故涉及到手撸折半查找的代码
- 后移次数仍然没有优化
#include<stdio.h>
//后面为了测试写的输出,输出每一次排序后的信息。
void print(int a[], int n ,int i){
printf("%d:",i);
for(int j=0; j<n; j++){
printf("%d",a[j]);
}
printf("
");
}
//折半插入排序
void BinInsertSort(int a[],int n){ //a为要排序的数组,n为元素总个数 (即长度)
int i,j,low=0,high=0,mid;
int tmp=0;
for(i=1;i<n;i++){ //同直接插入排序,假设第一个元素有序
//书上这里if判断 a[i]<a[i-1],意味着反序进行下列操作,正序本算法就没啥意义了
//但是仔细思考,折半查找中要求就是顺序排列
//比如 9 8 7 6 5 4 3 2 1 进行折半插入排序,其是顺序的,一定满足反序
//如果改一下 3 1 7 5 2 4 9 6这样乱序,显然不满足下面的折半查找算法,运行后必然是乱序
low=0;
high=i-1;
tmp=a[i];
//采用折半查找法判断插入位置,最终变量 low 表示插入位置
while(low<high){
mid=(low+high)/2;
if(a[mid]>tmp){
high=mid-1;
}
else{
low=mid+1;
}
}
//插入位置后的元素统一后移
for(j=i;j>low;j--){
a[j]=a[j-1];
}
a[low]=tmp; //插入元素
print(a,8,i);
}
}
//测试
int main(){
//这里a必须有序
int a[8]={9,7,6,5,4,3,2,1}; //预计 1 2 3 4 5 6 7 9
//int a[8]={3,1,7,5,2,4,9,6}; //运行后都是乱的 5 1 2 4 6 7 9 3
BinInsertSort(a,8);
}
复盘一下:
void BinInsertSort(int a[],int n){
int i,j,low=0,high=0,mid;
int tmp=0;
//遍历开始排序,不用判断,因为假设第一个有序后,其余一定都是反序的
for(i=1;i<n;i++){
low=0;
high=mid-1;
tmp=a[i];
}
//折半查找待插入的位置
while(low<=high){
mid=(low+high)/2;
if(a[mid]>tmp){
high=mid-1;
}
else{
low=mid+1;
}
}
//待插入的位置后移
for(j=i;j>low;j--){
a[j]=a[j-1];
}
//插入
a[low]=tmp;
}