直接插入排序、折半插入排序 O(n^2)
希尔排序
7,10,9,8,4,7模拟
!!!注意:
1、折半插入和直接插入之间的区别:
排序的总趟数取决于元素的个数N,两者都是N-1趟。
元素的移动次数取决于初始序列,两者相同。
使用的辅助空间都是O(1)
折半插入的比较次数与序列初始状态无关,为O(nlog2n);而直接插入的比较次数与序列初始态有关,为o(n)~o(n^2)
直接插入排序
将序列分为排序好的和未排序部分,从前往后将a[i]插入到前段排好序的序列中,同时将插入点到a[i]的元素向后移动一位
void insert_sort(int a[],int len)//直接插入排序
{
//平均O(n^2)
int i,j;
for(i=1;i<len;i++){
int temp = a[i];
//朴素
//查找插入点
for(j=i-1;j>=0;j--){//找出不大于temp的最后一个元素--插入点的前一个位置
if(a[j]>temp){
a[j+1]=a[j];//同时后移
}else
break;
}
a[j+1]=temp;//注意是+1,
}
}
折半插入排序
在直接插入排序中进行优化,查找插入点时使用折半查找,前面的是顺序查找。
ps:为了算法稳定性,如果有相等点–找到相等点之后还需要继续向后寻找,即找到所有相等点的最后一个的位置。
void insert_sort_binary(int a[],int len)//折半插入排序
{
int i;
//平均O(n^2)
for(i=1;i<len;i++){
int temp = a[i];
//折半查找优化--也是O(n^2)
int low = 0;int high=i-1;
while(low<=high){
int mid = (low+high)/2;
if(a[mid]==temp){
low=mid+1;//折半应该是return mid,为了算法稳定性--找到相等的点后,继续向后查找
}
if(a[mid]<temp){
low = mid+1;
}else{
high = mid-1;
}
}
for(int j=i-1;j>=low;j--){//将插入点之后的元素都后移一位
a[j+1]=a[j];
}
a[low]=temp;//low为插入点
}
}
小结
希尔排序
“直接插入排序”适用于表“基本有序”的情况
void shell_sort(int a[],int len)//希尔排序
{
int i,j,d;
for(d=len/2;d>=1;d/=2){//将子表划分为
for(i=d;i<len;i+=d){//直接插入排序(按子表进行排序)
int temp = a[i];
for(j=i-d;j>=0;j-=d){
if(a[j]>temp)
a[j+d]=a[j];
else
break;
}
a[j+d]=temp;
}
}
}
测试代码
#include<bits/stdc++.h>
using namespace std;
int main()
{
int len;
len = 6;
int a[10] = {7,10,9,8,4,7};
// insert_sort(a, len);
// insert_sort_binary(a, len);
shell_sort(a, len);
for(int i=0;i<len;i++){
cout<<a[i]<<' ';
}
cout<<endl;
}