插入排序分为直接插入排序和希尔排序
每次将一个待排序的记录,按其关键字大小插入到前面已经排好序的子列表当中的适当位置,直到全部记录插入完成为止。
对直接插入排序我的理解就是:先将第一个记录视为一个有序序列,然后依次将后面的记录插入到这个有序序列中来。每次要插入的记录时,须从后往前依次比较有序序列中的记录,直到找到在有序序列中的位置,记录下该位置,该位置开始的每个记录都后移一位,然后将插入记录插入该位置。这样每插入一个记录进去,有序序列长度加1,剩余记录减1,直到所有记录都插入到有序序列中,排序完成。
算法实现(C#):
public void InsertSort(SeqList<int>R)
{
for(int i=1;i<R.Length;i++) //外层循环,控制执行(n-1)趟排序
{
if(R.Data[i]<R.Data[i-1]) //判断大小,决定是否需要交换
{
int temp=R.Data[i]; //如果需要交换,则将待排序记录放入临时变量中
int j=0;
for(j=i-1;j>=0&&temp<R.Data[j];j--) //内层循环,在有序序列中从后往前比较,找到待排序记录在有序列中位置(位置空出)
{
R.Data[j+1]=R.Data[j]; //将有序记录往后移
}
R.Data[j+1]=temp; //将临时变量中的值放入正确位置,即空出的位置
}
}
}
时间复杂度分析:最好情况下为O(n),最坏情况下为O(n2)。比较次数期望为n2/4。
希尔排序:也称缩小增量排序。将记录序列分成若干子序列,每个子序列分别进行插入排序。关键是这种子序列不是由相邻记录构成的,而是按一定间隔从序列取出来组成的。在直接插入排序算法中,每次插入一个数,使有序序列只增加1个节点, 并且对插入下一个数没有提供任何帮助。如果比较相隔较远距离(称为增量)的数,使得数移动时能跨过多个元素,则进行一次比较就可能消除多个元素交换。D.L.shell于1959年在以他名字命名的排序算法中实现了这一思想。算法先将要排序的一组数按某个增量d分成若干组,每组中记录的下标相差d.对每组中全部元素进行排序,然后再用一个较小的增量对它进行,在每组中再进行排序。当增量减到1时,整个要排序的数被分成一组,排序完成。
算法实现(C#):
public void ShellSort(SeqList<int>R,int[] increment)
{
int i,j,temp,d; //希尔排序中的一趟排序,d为当前增量
for(int m=0;m<increment.Length;m++)
{
d=increment[m];
//将R[d+1...n]分别插入各组当前的有序区
for(i=d;i<R.Length;i++)
{
if(R.Data[i]<R.Data[i-d])
{
temp=R.Data[i];j=i-d;
do
{//查找R[i]的插入位置
R.Data[j+d]=R.Data[j]; //后移记录
j=j-d; //查找前一记录
}while(j>0&&temp<R.Data[j]);
R.Data[j+d]=temp; //插入R[i]到正确的位置上
}
}
}
}
时间复杂度分析:接近于O(n(log2n)2)。希尔排序适用于中等规模的记录序列排序。