一、希尔排序
1. 希尔排序的定义
希尔排序(Shell's Sort)是插入排序的一种又称“缩小增量排序”(Diminishing Increment Sort),是直接插入排序算法的一种更高效的改进版本。希尔排序是非稳定排序算法(接下的例子会说明)。该方法因 D.L.Shell 于 1959 年提出而得名。
希尔排序是把记录按下标的一定增量分组,对每组使用直接插入排序算法排序;
比较相隔较远距离(称为增量)的数,使得数移动时能跨过多个元素,则进行一次比较就可能消除多个元素交换。
随着增量逐渐减少,每组包含的关键词越来越多,当增量减至 1 时,整个文件恰被分成一组,算法便终止。
2. 算法思想:
希尔排序又称“分组插入排序”,先将整个待排元素序列分割成若干个子序列(由相隔某个“增量”的元素组成的)分别进行直接插入排序,然后依次缩减增量再进行排序,待整个序列中的元素基本有序(增量为1后)时,再对全体元素进行一次直接插入排序。
动态图如下:
注意:动态图中的gap为上面所说的 “增量”,为数组长度len除以2,每排序后一次除以2,直至gap=1。
动态图(2)如下:
接下来看一个例子:
第一步:将数组元素个数分为 nic = len/2 组,以这个例子为例分为10/2=5组(第一次的增量为5),就如下的9-4, 1-8, 2-6, 5-3, 7-5分为五种颜色。
第二步:比较大小,使用key来储存转换元素的值,相当于转换酱油和可乐的第三个空瓶子,
当第二个值 比 对比的前一个值小,就交换它们的值,(这里使用交换是不恰当的,交换是用在相邻的元素,但这样更便于理解)例如:9 - 4,4比9小,4就插入9的位置,9插入4的位置。
- gap = 10 / 2 = 5,第一趟排序,分为五组比较排序(流程图五种颜色显示):9 - 4, 1 - 8, 2 - 6, 5 - 3, 7 - 5, 一组一组的比较比较之后为4 - 1 - 2 - 3 - 5 - 9 - 8 - 6 - 5 - 7
- gap = 5 / 2 = 2, 第二趟排序,比较的组变为4 - 2 - 5 - 8 - 5 和 1 - 3 - 9 - 6 -7
- 比较循序为:2 - 4比较后转换为2 - 4,1 - 3 比较后还是1 - 3,接着4 - 5比较还是4 - 5,(事实上是对比一次红色组然后对比一次蓝色组这样对比下去)5 - 8比较后变为8 - 5,8 - 5比较后变为5 - 8,第一组增量就变为了:2 - 4 - 5 - 5 - 8,第二组为:1 - 3 - 6 - 7 - 9
- 就这样继续完成第二趟排序后数组为: 2 - 1 - 4 - 3 - 5 - 6 - 5 - 7 - 8 - 9
- gap = 2 / 2 = 1,增量减至 1 时,整个文件恰被分成一组(第三趟全为红色),熟悉的直接插入排序就来了,gap = 1第三趟排序结束,排序也就结束了经典算法(三)---插入排序
https://blog.youkuaiyun.com/code__01/article/details/134746531?spm=1001.2014.3001.5502
非稳定排序算法:
有下划线的 5 为后面的5,没有下划线的 5 为前面的5,但排序结束后,后面的 5 却排在了前面的 5 前面
程序流程图如下:
代码参考:
#include<stdio.h>
//复制函数:打印数组
void print_arr(int arr[], int n)
{
for (int i = 0; i < n; i++)
{
printf("%d ", arr[i]);
}
printf("\n");
}
// 希尔排序
void shell_sort(int arr[], int len)
{
int i, j, inc, key;
// 初始inc增量:len/2,每一趟之后除以二
for (inc = len / 2; inc > 0; inc /= 2)
{
// 每一趟采用插入排序
for (i = inc; i < len; i++)
{
key = arr[i];
for (j = i; j >= inc && key < arr[j - inc]; j -= inc)
arr[j] = arr[j - inc];
arr[j] = key;
}
print_arr(arr, len);
}
}
int main(int argc, char const* argv[])
{
int arr[] = { 9, 1, 2, 5, 7, 4, 8, 6, 3, 5};
int len = 10;//要排序的数组元素个数
print_arr(arr, len);
shell_sort(arr, len);
return 0;
}