插入排序的思想是:每一趟将一个待排序的元素,按其关键字值的大小插入到已经排序的部分文件中的适当位置上,直到全部插入完成。这里介绍三种插入排序方法:直接插入排序、折半插入排序和希尔排序。
直接插入排序
1.算法思想
直接插入排序的过程是将依次将每个元素插入到一个有序的序列中去。所有元素分为有序区和无序区,每次从无序区中拿出第一个元素,从后往前(下标递减)依次与有序区每个元素比较,找到正确的位置,并将元素插入到正确位置上。初始有序区只有一个元素。
2.性能分析
初始序列正序时效率最高,时间复杂度为O(n);初始序列无序时效率最低,时间复杂度为O(n2)。
折半插入排序
1.算法思想
在查找正确位置时使用折半查找(二分查找),由此进行的插入排序成为折半插入排序。
2.性能分析
折半插入排序的空间复杂度为O(1)。从时间上看,折半插入排序仅减少了关键词的比较次数,而元素的移动次数不变。因此,折半插入排序的平均时间复杂度仍为O(n2)。
希尔排序
1.算法思想
希尔(Shell)排序又称为缩小增量排序方法,其基本思想是:把元素按下标的一定增量d分组,对每组元素采用直接插入排序的方法进行排序,然后随着增量逐渐减少,所分成的组包含的元素越来越多,到d的值减少到1时,整个数据合成为一组,构成一组有序元素,则完成排序。
2.性能分析
当正序时效率最高,反序时效率最低。
完整代码
#include<iostream>
using namespace std;
//直接插入排序
void insert_sort(int a[], int n) {
int i,j,temp=0;
for(i=1;i<n;++i){
j = i-1;
temp = a[i];
while(j>=0 && temp<a[j]) {
a[j+1] = a[j];
--j;
}
a[j+1] = temp;
}
}
//折半插入排序
void insert_sort1(int a[], int n) {
int i,j,low,high,mid,temp=0;
for( i=1;i<n;++i) {
temp = a[i];
low = 0;
high = i-1;
//折半搜索a[i]插入的位置
while(low<=high) {
mid = (low+high)>>1;
if(temp<a[mid]) high = mid-1;
else low = mid+1;
}
//此时应将a[i]插入到high之后
//也就是将high之后的有序区的数都往后移动一个位置
for(j=i-1;j>high;--j)
a[j+1] = a[j];
//将a[i]插入到high之后
a[high+1] =temp;
}
}
//希尔排序
void shell_sort(int a[], int n) {
int i,j,temp=0;
//选取分量d=n/2
int d = n>>1;
while(d>0) {
//对每组元素采用直接插入排序
for(i=d;i<n;++i) {
temp = a[i];
j = i-d;
while(j>=0 && temp<a[j]) {
a[j+d] = a[j];
j -= d;
}
a[j+d] = temp;
}
//缩小增量
d = d>>1;
}
}
//输出数组
void print_array(int a[],int n) {
for(int i=0;i<n;++i){
cout<<a[i]<<" ";
}
cout<<endl;
}
//测试代码
int main() {
cout<<"Test insert_sort:"<<endl;
cout<<endl;
//直接插入测试数据
int a[] = {4,10,6,2,11,9,7};
int n = 7;
cout<<"Before sort:";
print_array(a,n);
cout<<"After insertion:";
insert_sort(a,n);
print_array(a,n);
cout<<endl;
//折半插入测试数据
int a1[] = {12,5,15,2,1,9,7,11};
int n1 = 8;
cout<<"Before sort:";
print_array(a1,n1);
cout<<"After binary insertion:";
insert_sort1(a1,n1);
print_array(a1,n1);
cout<<endl;
//希尔插入测试数据
int a2[] = {7,3,1,12,5,9};
int n2 = 6;
cout<<"Before sort:";
print_array(a2,n2);
cout<<"After binary insertion:";
shell_sort(a2,n2);
print_array(a2,n2);
return 0;
}
测试结果如下:
这里每个排序算法都用一组不同的测试数据,防止上个算法已经将数组排好序而影响测试结果。