设有n个记录R[1]~R[n]。
一、插入排序
1. 直接插入排序
直接插入排序是指将R[i]~R[n]插入到已经有序的R[1]~R[i-1]序列中。R[0]是一个哨兵,起到作为边界条件并作为暂存单元的作用。
实际上,一切为简化边界条件而引入的附加节点(元素)均可称为哨兵。例如单链表中的头结点。
对于有n个记录的集合,要进行n-1趟排序。
其最优时间复杂度是O(n),平均时间复杂度是O(n*n)。当文件初始有序的状态和排序的要求一致时可以达到最优时间复杂度。
代码片段如下:
/*****************************************
*****************插入排序*****************
*****************************************/
void insert_sort(vector<int> &v) {
int j = 0;
int len = v.size() - 1;
for (int i = 2; i <=len; ++i) {
v[0] = v[i];
j = i - 1;
while (v[0] < v[j]) {
v[j + 1] = v[j]; //记录后移
--j;
}
v[j + 1] = v[0]; //插入
}
}
2. 希尔排序
希尔排序是将待排记录进行分组。首先设定一个增量d,然后将增量为d的元素分为一组。对于每一组中的元素,对它们进行直接插入排序。
当增量k=1时,希尔排序和直接插入基本一致,只是在希尔排序中没有设置哨兵而需要判断数组下标是否为负越界。
希尔排序的时间和增量的选取有关,好的增量应该有如下特性:
(1)最后一个增量必须为1.
(2)应尽量避免序列中的值互为倍数(尤其是相邻的值)的情况。
希尔排序的时间性能优于直接插入排序:
(1)当文件初态基本有序时,直接插入排序所需的比较和移动次数均较少。
(2)当n值较小时,n和n*n的差别也较小,即直接插入排序的最优时间复杂度和最坏时间复杂度差别不大。
(3)在希尔排序开始时的增量较大,分组较多,每组中的记录少,故各组内直接插入排序较快;
后来增量d(i)逐渐减小,分组数也逐渐减小,各组中的记录数逐渐增多,但由于已经以d(i-1)作为距离排过序,使文件接近有序状态,所以新的一趟排序也较快。
所以希尔排序在效率上相对于直接插入排序有很大的改进。<