一、插入排序
定义:每次将一个待排序的记录按其关键字大小插入排序到已排好序的子序列,直到全部记录插入完成。
分类:直接插入排序、折半插入排序、希尔排序。
1.直接插入排序(无哨兵)
(1)利用增量法(将无序区的第一个元素插入到有序区的适当位置形成新的有序区)
(2)算法思想:
将第i个位置的元素暂存在tmp中(tmp=R[i]);
j在有序区从后向前查找(j=i-1);
凡是关键字大于tmp的记录均往后移一个位置(if(R[j]>tmp) R[j+1]=R[j]);
若找到某个关键字小于或等于tmp,则将tmp放在它的后面(if(R[j]<=tmp) R[j+1]=tmp)。
(3)名词解释:归位(一个元素在整个排序结束前就已经放在其最终位置上)
(4)算法:
void InsertSort(Elemtype R[],int n)
{
int i,j; //i指的是无序区的第一个元素,j指的是有序区的最后一个元素
Elemtype tmp; //暂存比较元素
for(i=1;i<n;i++) //初始:i=0为第一个有序区,i<n是只有n个元素,数组下标从0开始
{
if(R[i].key<R[i-1].key) //比较无序区第一个元素和有序区的最后一个元素,确定i是否原地不动
{
tmp.key=R[i].key; //i位置元素需要移动,tmp暂存i位置元素
do
{
R[j+1].key=R[j].key; //更大的元素往后移,为tmp元素留位置
j--; //j--和--j的区别在于运算时前者先取j值做运算后+1,在此处并无不同
}while(j>=0 && tmp.key<R[j].key); //当j在范围内且比较元素始终小于被比较元素时继续寻找插入位置
R[j+1].key=tmp.key; //将所有大于i/tmp的元素后移找到了比i小的元素,放在其后
}
}
}
(5)算法分析:
空间复杂度:O(1)
时间复杂度:O(n²)
稳定的算法:由于每次插入都是从后往前比较后再移动,不会出现相同元素相对位置发生变化的情况。
适用性:适用于顺序存储和链式存储的线性表。
2.折半插入排序
(1)前提条件:有序区的元素时有序的,可以对有序区采用折半查找的方法找到插入位置,再通过移动元素进行插入。
(2)算法思想:
对有序区采用折半查找,找到比tmp值小的元素(low>high时R[high]);
将其后的有序区所有元素后移一位(for(j=i-1;j>high;j++) R[j+1]=R[j]);
再将tmp元素插入到其后(R[high+1]=tmp)。
(3)算法:
void insertSort(Elemtype R[], int n)
{
int i.j.mid,low,high;
Elemtype tmp;
for(i=1; i<n;i++)
{
if(R[i].key<R[i-1].key)
{
tmp=R[i];
low=0;
high=i-1;
while(high>=low) //折半查找插入位置,R[high]
{
mid = (low + hight)/2; //符号向下取整
if(R[mid].key>tmp.key)
high=mid-1;
else
low=mid+1;
}
for(j=i-1;j>high;j--)
R[j+1]=R[j];
R[hight+1]=tmp;
}
}
}
(4)算法分析:
空间复杂度:O(1)
时间复杂度:O(n²)
稳定算法。
3.希尔排序(缩小增量排序)
(1)定义:把待排序表分解成若干个形如L[i,i+d,i+2d,...,i+nd]的特殊子表,d为增量,对各个子表进行直接插入排序。
(2)算法思想:
取小于n的增量d1,把表中元素分为d1个组;
在各组内进行直接插入排序;
然后取第二个增量d2(<d1),重复上述操作;
直到d=1为止。
(3)算法:
void Shellsort(Elemtype R[],int n)
{
int i,j,d;
Elemtype tmp;
d=n/2;
while(d>0)
{
for(i=d;i<n;i++) //从d开始往后取元素,分别与相差d的前面元素作对比
{
tmp=R[i];
j=i-d;
while(j>=0 && tmp.key<R[j].key)
{
R[j+d]=R[j];
j=j-d;
}
R[j+d]=tmp;
}
d=d/2; //向下取整
}
}
(4)算法分析:
空间复杂度:O(1)
时间复杂度:O(n…^1.3)
不稳定的排序算法
二、习题总结
1.李春葆例题
2.王道选择题
(1)在基本有序的情况下,直接插入排序时间复杂度接近于O(n),相较于简单选择排序、快速排序、归并排序效率最高。
(2)序列越接近正序,直接插入排序算法比较次数越少。
(3)折半插入排序算法相较于直接插入排序算法元素比较次数更少,移动次数是不变的,因为原理差不多但相对位置不变。