纯手撸——折半插入排序

折半插入排序需要注意的是:

  • 折半插入的顺序表必须有序
  • 比较次数是运用折半查找减少了比较次数,故涉及到手撸折半查找的代码
  • 后移次数仍然没有优化
#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;
}
原文地址:https://www.cnblogs.com/wangzheming35/p/13451454.html