#include<stdio.h>
#include<stdlib.h>
#include<malloc.h>
#define MaxSize 50
//折半插入排序 是针对 在 整个顺序表 或 数组的"有序区"里 用'二分查找法'
//先查找到 待插入元素A[i]应该插入的位置,然后再移动比A[i]大的元素,最后插入A[i]
//所以这里的"折半",是对数组 或 顺序表 "有序区" 的折半,而不是对整个数组的折半.
//!! A[i]最后插入的位置一定是A[low]或者A[high+1]; (这里low = high +1)
void BinaryInsertSort(int A[],int n){
int i,j,low,high,mid;
//这个大的for循环作用: 提供需要排序的元素(从A[2]~A[n-1]) (时间复杂度:O(n))
for(i = 2;i < n;i++){ //这里i从2开始,那是因为A[1]是默认排好了的
A[0] = A[i]; //将要排序的元素先放在A[0]里
low = 1;
high = i-1;
//下面要开始找目前A[0]中的元素 所 应该排的位置
//用二分查找法查找
while(low<=high){ //本轮循环作用:找A[0]应该插入的位置 (时间复杂度:O(log2n))
mid = (low + high)/2; //注意,这个'时间复杂度'是"比较"!!
if(A[0] < A[mid])
high = mid - 1;
else
low = mid + 1;
} //这一轮循环结束时,(如果没有重复元素,必定是查找失败的)
//这时low > high 且 low = high + 1;
//因为二分查找的区间是顺序表,所以low所指的元素>A[0]>high所指的元素
//因此这轮的A[0]最后会被插在A[low]的位置中(或者说A[high + 1])
for(j = i-1;j <= low;j--){ //本轮循环作用: 移动元素
A[j+1] = A[j]; //这轮循环的时间复杂度:O(n)
} //注意!这个'时间复杂度'是"移动元素"!!
A[low] = A[0]; //插入
}
}
//总结:由于一共有三个循环:1.for循环 2.while循环(用于查找) 3. for循环(用于移动)
//所以'折半插入排序' 查找的次数 约为:O(1.for) * O(2.while) = O(nlog2n)
//(!!但这只是查找)
//这种方法 元素移动的次数并未改变,仍 依赖于 待排序表 的初始状态
//所以,折半插入排序 的 时间复杂度 仍为 O(1.for) * O(3.for) = O(n^2).
//是一种稳定的排序方法
【数据结构—排序】折半插入排序
于 2022-11-01 21:03:56 首次发布