数据结构课程中的插入排序算法:本篇文章主要记录总结三种简单常见的插入排序算法(直接插入排序,折半插入排序,希尔排序)的基本思想和简单实现。
插入排序:
在排序算法中,数据结构课程中常见的三种插入排序算法是:直接插入排序,折半插入排序,希尔排序。插入排序算法的基本思想是:从给定的一个关键字序列中,每排序一趟就将一个待排序的元素,按照其关键字值的大小插入到已经排好序的部分文件中,直到全部值都插入完成,排序结束;其中,不同的插入排序方法,建立第一个排好序的部分文件的方法不同。插入排序与初始数据序列顺序有关,当初始序列越接近正序,性能越好。
下面依次介绍这三种插入排序:
1、直接插入排序
思想:最简单的排序方法,对于给定的一个关键字序列,将它的第一个元素作为一个排好序的部分文件,然后将后面的元素一个个的按照关键字大小插入到这个序列中,插入完毕之后排序结束;在指定元素插入到部分有序文件时,先对文件进行查找,找到元素应该插入的位置,然后将元素插入其中。
用C/C++实现的对含n个元素的一维数组的排序算法如下:
//直接插入排序 void InsertSort1(int a[],int n) { int i,j,temp; //从第二个元素开始插入 for(i=1;i<n;i++) { temp=a[i]; j=i-1; //查找 while(j>=0&&a[j]>temp) { a[j+1]=a[j]; j--; } a[j+1]=temp; //插入 } }对于直接插入排序:
2、折半插入排序
思想:折半插入排序的本质思想和直接插入排序别无二致,只是在折半插入排序中对于有序的部分文件进行的查找为折半查找(二分查找),而直接插入排序用的是顺序查找。
用C/C++实现的对含n个元素的一维数组的排序算法如下:
//折半插入排序 void InsertSort2(int a[],int n) { int i,j,temp,low,mid,high; for(i=1;i<n;i++) { temp=a[i]; low=0; high=i-1; //折半查找 while(low<=high) { mid=(low+high)/2; if(a[mid]<temp) low=mid+1; else high=mid-1; } //插入 for(j=i-1;j>=high+1;j--) a[j+1]=a[j]; a[high+1]=temp; } }对于折半插入排序,从时间上看,仅仅是减少了关键字的比较次数,平均时间复杂度没有改变,相关性能和直接插入排序一样。
3、希尔排序
思想:希尔排序又称缩小增量排序法,它把给定的关键字序列的元素按照下标的增量d分组,对每组元素采用的还是直接插入排序,然后将增量逐渐减小,当d最终减小到1时,整个数据合成为一组,排序完成。
用C/C++实现的对含n个元素的一维数组的排序算法如下:
//希尔排序 void ShellSort(int a[],int n) { int i,j,d,temp;//d为增量 d=n/2; while(d>0) { //简单插入排序思想 for(i=d;i<n;i++) { temp=a[i]; j=i-d; while(j>=0&&a[j]>temp) { a[j+d]=a[j]; j=j-d; } a[j+d]=temp; } d=d/2; } }
对于希尔排序:正序时效率最高,反序时效率最低;核心还是简单插入排序,相关性能如下:
最后关于算法的测试:
/*插入排序算法*/ #include <iostream> using namespace std; //直接插入排序 void InsertSort1(int a[],int n) { int i,j,temp; //从第二个元素开始插入 for(i=1;i<n;i++) { temp=a[i]; j=i-1; //查找 while(j>=0&&a[j]>temp) { a[j+1]=a[j]; j--; } a[j+1]=temp; //插入 } } //折半插入排序 void InsertSort2(int a[],int n) { int i,j,temp,low,mid,high; for(i=1;i<n;i++) { temp=a[i]; low=0; high=i-1; //折半查找 while(low<=high) { mid=(low+high)/2; if(a[mid]<temp) low=mid+1; else high=mid-1; } //插入 for(j=i-1;j>=high+1;j--) a[j+1]=a[j]; a[high+1]=temp; } } //希尔排序 void ShellSort(int a[],int n) { int i,j,d,temp;//d为增量 d=n/2; while(d>0) { //简单插入排序思想 for(i=d;i<n;i++) { temp=a[i]; j=i-d; while(j>=0&&a[j]>temp) { a[j+d]=a[j]; j=j-d; } a[j+d]=temp; } d=d/2; } } //测试主函数 int main() { int a[10]={144,232,111,678,329,834,123,230,567,431}; cout<<"排序之前的元素序列为:"; for(int i=0;i<10;i++) { cout<<a[i]<<" "; } cout<<endl; //InsertSort1(a,10); //InsertSort2(a,10); ShellSort(a,10); cout<<"排序之后的元素序列为:"; for(int i=0;i<10;i++) { cout<<a[i]<<" "; } cout<<endl; }
运行结果如下:
总结:排序思想总结参考于《新编数据结构习题与解析》,算法全部是最简单的实现,之所以没有参看教课书籍是因为那些书中的内容太全面,但是并不一定通俗易懂;算法实现用Codeblocks编译器运行通过;看思想总是会有云里雾里,似懂非懂的感觉,但是结合实践之后,发现那些思想的总结真是珍品,句句在理。
写这篇文章用于记录学习,也希望对像我一样的初学者有用。