1.希尔排序
- 希尔排序是希尔(Donald Shell)于1959年提出的一种排序算法。希尔排序也是一种插入排序,它是简单插入排序经过改进之后的一个更高效的版本,也称为缩小增量排序,同时该算法是冲破O(n2)的第一批算法之一。它与插入排序的不同之处在于,它会优先比较距离较远的元素。希尔排序又叫缩小增量排序。
1.1 基本思想
- 将待排序列划分为若干组,在每一组内进行插入排序,以使整个序列基本有序,然后再对整个序列进行插入排序。
- 例如:将 n 个数据元素分成 d 个子序列:
- { R[1],R[1+d],R[1+2d],…,R[1+kd] }
- { R[2],R[2+d],R[2+2d],…,R[2+kd] }
- …
- { R[d],R[2d],R[3d],…,R[kd],R[(k+1)d] }
- 其中,d 称为增量,它的值在排序过程中从大到小逐渐缩小,直至最后一趟排序减为 1。
1.2 图示
1.3 代码实现
// 分类 -------------- 内部比较排序
// 数据结构 ---------- 数组
// 最差时间复杂度 ---- O(n^2)
// 最优时间复杂度 ---- O(n^1.3)
// 平均时间复杂度 ---- O(nlogn)
// 所需辅助空间 ------ O(1)
// 稳定性 ------------ 不稳定
#include <stdio.h>
#include <stdlib.h>
void println(int array[], int len)
{
int i = 0;
for (i = 0; i < len; i++)
{
printf("%d ", array[i]);
}
printf("\n");
}
void ShellSort(int array[], int len)
{
int i = 0;
int j = 0;
int k = -1;
int temp = -1;
int gap = len;
do
{
gap = gap / 3 + 1; // gap如何变化无强制要求,但gap最终要收敛于1,工程实践经验除以3性能较好,现无理论方法证明。
//gap = 1; // gap=1时,希尔排序退化为擦入排序
// 分组
for (i = gap; i < len; i += gap)
{
k = i;
temp = array[k];
// 擦入排序
for (j = i - gap; (j >= 0) && (array[j] > temp); j -= gap)
{
array[j + gap] = array[j];
k = j;
}
array[k] = temp;
}
} while (gap > 1);
}
int main(int argc, char *argv[])
{
int array[] = { 21,25,49,25,16,8 };
int len = sizeof(array) / sizeof(*array);
printf("希尔排序前:");
println(array, len);
ShellSort(array, len);
printf("希尔排序前:");
println(array, len);
system("pause");
return 0;
}
- 运行结果:
- 希尔排序是不稳定的排序算法,虽然一次插入排序是稳定的,不会改变相同元素的相对顺序,但在不同的插入排序过程中,相同的元素可能在各自的插入排序中移动,最后其稳定性就会被打乱。
- 比如序列:{ 3, 5, 10, 8, 7, 2, 8, 1, 20, 6 },h=2时分成两个子序列 { 3, 10, 7, 8, 20 } 和 { 5, 8, 2, 1, 6 } ,未排序之前第二个子序列中的8在前面,现在对两个子序列进行插入排序,得到 { 3, 7, 8, 10, 20 } 和 { 1, 2, 5, 6, 8 } ,即 { 3, 1, 7, 2, 8, 5, 10, 6, 20, 8 } ,两个8的相对次序发生了改变。
2.快速排序
2.1 基本思想