经典算法(四)---希尔排序

一、希尔排序

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的位置。

  1. gap = 10 / 2 = 5,第一趟排序,分为五组比较排序(流程图五种颜色显示):9 - 4, 1 - 82 - 6,  5 - 3, 7 - 5, 一组一组的比较比较之后为4 - 1 - 2 - 3 - 5 - 9 - 8 - 6 - 5 - 7
  2. gap = 5 / 2 = 2,    第二趟排序,比较的组变为4 - 2 - 5 - 8 - 5  和  1 - 3 - 9 - 6 -7
  3. 比较循序为:2 - 4比较后转换为2 - 41 - 3 比较后还是1 - 3,接着4 - 5比较还是4 - 5,(事实上是对比一次红色组然后对比一次蓝色组这样对比下去)5 - 8比较后变为8 - 58 - 5比较后变为5 - 8,第一组增量就变为了:2 - 4 - 5 - 5 - 8,第二组为:1 - 3 - 6 - 7 - 9 
  4. 就这样继续完成第二趟排序后数组为: 2 - 1 - 4 - 3 - 5 - 6 - 5 - 7 - 8 - 9 
  5. gap = 2 / 2 = 1,增量减至 1 时,整个文件恰被分成一组(第三趟全为红色),熟悉的直接插入排序就来了,gap = 1第三趟排序结束,排序也就结束了经典算法(三)---插入排序icon-default.png?t=N7T8https://blog.csdn.net/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;
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

'撒野奔跑.

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值