数据结构课程中的插入排序算法:本篇文章主要记录总结三种简单常见的插入排序算法(直接插入排序,折半插入排序,希尔排序)的基本思想和简单实现。
插入排序:
在排序算法中,数据结构课程中常见的三种插入排序算法是:直接插入排序,折半插入排序,希尔排序。插入排序算法的基本思想是:从给定的一个关键字序列中,每排序一趟就将一个待排序的元素,按照其关键字值的大小插入到已经排好序的部分文件中,直到全部值都插入完成,排序结束;其中,不同的插入排序方法,建立第一个排好序的部分文件的方法不同。插入排序与初始数据序列顺序有关,当初始序列越接近正序,性能越好。
下面依次介绍这三种插入排序:
思想:最简单的排序方法,对于给定的一个关键字序列,将它的第一个元素作为一个排好序的部分文件,然后将后面的元素一个个的按照关键字大小插入到这个序列中,插入完毕之后排序结束;在指定元素插入到部分有序文件时,先对文件进行查找,找到元素应该插入的位置,然后将元素插入其中。
用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;
}
}
对于折半插入排序,从时间上看,仅仅是减少了关键字的比较次数,平均时间复杂度没有改变,相关性能和直接插入排序一样。
思想:希尔排序又称缩小增量排序法,它把给定的关键字序列的元素按照下标的增量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编译器运行通过;看思想总是会有云里雾里,似懂非懂的感觉,但是结合实践之后,发现那些思想的总结真是珍品,句句在理。
写这篇文章用于记录学习,也希望对像我一样的初学者有用。