排序(3) 希尔排序
一、前言
希尔(Shell)又称为缩小增量排序,它是一种插入排序。它是直接插入排序算法的一种威力加强版。
希尔排序,也称递减增量排序算法,以其设计者希尔(Donald Shell)的名字命名,该算法于1959年公布。
图片来自维基百科
二、算法思想
对于n个待排序的数列,取一个小于n的整数gap(gap被称为步长),将待排序元素分成若干组子序列,所以距离为gap的倍数的记录放在同一组中;然后,对各组内的元素进行直接插入排序。
这一趟排序完成之后,每一组内的元素都输有序的。然后减少gap的值,并重复执行上述的分组和排序。重复这样的操作直到gap=1时,整个序列就是有序的。
注意:
不要与归并排序相混淆,两者本质上是不一样的:归并排序的分是将相邻的元素化为一组,而希尔排序则是按照步长来分组的。
打个比方,军训的时候,教官从第一个人数到第八个人然后说“你们一组”,这是归并排序;
而希尔排序则是,教官说“从第一个人开始,依次报数,奇数的是一组”。
时间复杂度:
对插入算法的改进,低于O(n^2),具体与选择的增量序列有关。
稳定性:
不稳定
使用场景:
时间复杂度和增量序列的联系紧密,好的增量序列才能保证有好的时间复杂度,使用较少。
具体实例演示:
下面用希尔排序来对数组 {13 14 94 33 82 25 59 94 65 23 45 27 73 25 39 10} 排序(按照2i的分组序列)
Step 1
首先,我打算分为两个一组,共有16个数,就是八组,步长为8。
{13,65} {14,23} {94,45} {33,27} {82,73} {25,25} {59,39} {94,10}
组内用直接插入排序,得到
{13,65} {14,23} {45,94} {27,33} {73,82} {25,25} {39,59} {10,94}
Step 2
第二步,将新序列分为四个一组,共有四组,步长为4
{13,45,73,39} {65,94,82,59} {14,27,25,10} {23,33,25,94}
组内用直接插入排序,得到
{13,39,45,73} {59,65,82,94} {10,14,25,27} {23,25,33,94}
Step 3
第三步,八个一组,共两组,步长为2
{13,45,59,82,10,25,23,33} {39,73,65,94,14,27,25,94}
组内用直接插入排序,得到
{10,13,23,25,33,45,59,82} {14,25,27,39,65,73,94,94}
Step 4
第四步,16个一组,共一组,得到
{10,13,23,25,33,45,59,82,14,25,27,39,65,73,94,94}
组内用直接插入排序,得到
{10,13,14,23,25,25,27,33,39,45,59,65,73,82,94,94}
排序完成。
三、代码
/*
希尔排序
Time : 2018-2-20
Author : Stell Chen
Content : a simple example of Shell sort.
*/
#include<stdio.h>
/*
a[] 为待排序数组
n 为数组长度
*/
void shell_sort(int a[], int n) {
int i, j, gap;
//确定每次分组的步长->gap既相当于分多少组
for (gap = n/2; gap > 0; gap/=2)
{
printf("\n\n步长为%d\n", gap);
//对分组进行排序,使每组都形成一个有序的序列
for (i = 0; i < gap; i++)
{
//如果a[j] < a[j-gap],则寻找a[j]位置,并将后面数据的位置都后移
for ( j = i+gap; j < n; j+=gap)
{
if (a[j] < a[j - gap]) {
int temp = a[j];
int k = j - gap;
while (a[k] > temp && k >= 0) {
a[k + gap] = a[k];
k -= gap;
}
a[k + gap] = temp;
}
}
}
printf("排序中:\n");
for (int i = 0; i < 8; i++)
printf("%d ", a[i]);
}
}
int main() {
int a[8] = { 13,14,94,33,82,25,59,65 };
printf("排序前:\n");
for (int i = 0; i < 8; i++)
printf("%d ", a[i]);
shell_sort(a, 8);
printf("\n\n排序后:\n");
for (int i = 0; i < 8; i++)
printf("%d ", a[i]);
return 0;
}
执行结果如下:
四、参考文章
1.维基百科
https://zh.wikipedia.org/wiki/%E5%B8%8C%E5%B0%94%E6%8E%92%E5%BA%8F
2.排序(3)希尔排序
http://cuijiahua.com/blog/2017/12/algorithm_3.html
3.希尔排序
http://www.cnblogs.com/skywang12345/p/3597597.html
4.逍遥游——经典排序算法 - 希尔排序Shell Sort
https://blog.newnius.com/shell-sort.html