1.直接插入排序
直接插入排序 是一种最简单的排序算法,它的基本操作是将一个记录插入已排好的有序表,从而得到一个新的、记录数增加1的有序表。
例如:设有一个由待排序的一组记录组成的线性表,关键字的初始序列为{48,35,66,91,74,18}。我们可以认为第一个关键字{48}组成的线性表已是有序表;将第二个关键字插入前面的有序表,使之有序,得到序列{35,48};再将第三个关键字插入,使之有序,得到序列{35,48,66};如此重复,直到所有关键字都已插入,完成排序。
直接插入排序思想:
- (1)假设由前i - 1个记录关键字组成的子序列r[1,…,i-1]已为正序,在子序列中寻找合适位置并插入关键字r[i],使得子序列成为含有i个关键字的正子序列。
- (2)对有n个记录关键字的序列,重复上述过程至i=n,完成整个序列的直接插入排序。
直接插入排序算法:
typedef struct {
KeyType r[MAXSIZE + 1]; //0号单元闲置
int length; //顺序表长度
}SqList; //用于排序的顺序表类型
//1.直接插入排序
void Insert(SqList& L, int i) { //插入第i个记录
KeyType temp = L.r[i];
int j;
for (j = i; j > 1; j--) {
if (L.r[j] < L.r[j - 1])
L.r[j] = L.r[j - 1];
else
break;
}
L.r[j] = temp;
}
void InsertSort(SqList& L) { //直接插入排序算法
for (int i = 2; i <= L.length; i++)
Insert(L, i);
}
2.希尔排序
希尔排序 又称“缩小增量排序”,是一种改进的插入排序,在时间效率上有较大的提高。
通过对直接插入排序的分析可知,其算法时间复杂度为O(n),当待排记录序列有序时,其时间复杂度可以提高至O(n),当待排序列按关键字基本有序时,插入排序的效率可以大幅提高。另一方面,由于直接插入排序法很简单,所以在n值很小时效率也比较高。
希尔排序的基本操作过程是: 先将整个待排记录序列分为若干子序列,分别进行直接插入排序,待整个序列基本有序时,在对全体进行一次直接插入排序。设d为子序列的增量,即在序列中,每间隔d个取一个关键字,组成子序列,。例如进行3趟排序:第一趟,d = 5,分别以1,2,3,4,5记录为起点,每间隔5个记录取一个记录,组成5个记录的子序列然后在原来记录的存储位置上分别对这5个记录子序列进行直接插入排序。第二趟、第三趟分别取d = 3, d = 1。最后一次d = 1,完成整个序列的排序。
希尔排序示例: 以关键字序列{48,35,66,91,74,18,22,48,57,3}为例,d分别取5、3、1。
希尔排序算法:
//2.希尔排序
void ShellInsert(SqList& L, int d) { //增量为d的直接插入排序
//对间隔d的子序列进行直接插入排序
int i, j;
KeyType temp;
for (i = d + 1; i <= L.length; i++) {
if (L.r[i] < L.r[i - d]) { //需将L.r[i]插入有序增量子表
temp = L.r[i];
for (j = i; j > d; j = j - d) {
if (temp < L.r[j - d])
L.r[j] = L.r[j - d];
else
break;
}
L.r[j] = temp; //将记录r[i]插入正确位置
}
}
}
void ShellSort(SqList& L, int d[], int t) { //希尔排序
//按增量序列d[0,...,t - 1],对顺序表L进行希尔排序
for (int k = 0; k < t; k++)
ShellInsert(L, d[k]);
}