三、希尔排序

序言

希尔排序算法是按其设计者希尔(Donald Shell)的名字命名,该算法由1959年公布,是插入排序的一种更高效的改进版本。它的作法不是每次一个元素挨一个元素的比较。而是初期选用大跨步(增量较大)间隔比较,使记录跳跃式接近它的排序位置;然后增量缩小;最后增量为 1 ,这样记录移动次数大大减少,提高了排序效率。希尔排序对增量序列的选择没有严格规定。
希尔排序是基于插入排序的以下两点性质而提出改进方法的:
插入排序在对几乎已经排好序的数据操作时, 效率高, 即可以达到线性排序的效率
但插入排序一般来说是低效的, 因为插入排序每次只能将数据移动一位
算法思路:
先取一个正整数 d1(d1 < n),把全部记录分成 d1 个组,所有距离为 d1 的倍数的记录看成一组,然后在各组内进行插入排序
然后取 d2(d2 < d1)
重复上述分组和排序操作;直到取 di = 1(i >= 1) 位置,即所有记录成为一个组,最后对这个组进行插入排序。一般选 d1 约为 n/2,d2 为 d1 /2, d3 为 d2/2 ,…, di = 1。

标准实现

图解

图解

实例

假设有数组 array = [80, 93, 60, 12, 42, 30, 68, 85, 10],首先取 d1 = 4,将数组分为 4 组,如下图中相同颜色代表一组:
图解

然后分别对 4 个小组进行插入排序,排序后的结果为:
图解

然后,取 d2 = 2,将原数组分为 2 小组,如下图:
图解

然后分别对 2 个小组进行插入排序,排序后的结果为:
图解

最后,取 d3 = 1,进行插入排序后得到最终结果:
图解

标准代码

//实现方式 1A - 2A   2A - 3A     1B - 2B 2B - 3B
void shell_sort(Element *arr, int len) {
    int i, j, gap;

    for (gap = len / 2; gap > 0; gap /= 2) //步长
        for (i = 0; i < gap; i++)        //循环步长分组
        {
            for (j = i + gap; j < len; j += gap) //步长递进.插入排序
                if (arr[j] < arr[j - gap]) {
                    int temp = arr[j];
                    int k = j - gap;
                    while (k >= 0 && arr[k] > temp) {
                        arr[k + gap] = arr[k];
                        k -= gap;
                    }
                    arr[k + gap] = temp;
                }
        }
};

输入

void test_shell_sort(){
    int len = 6;
    Element arr[6] = {1, 2, 3, 7, 6, 5};
    shell_sort(arr, len);
    printArr(arr,len);
};

运行结果

1 2 3 5 6 7 

改良

//shell排序的另外一种思路.  1A - 2A   1B - 2B  2A-3A  2B-3B
void shell_sort_plus(int arr[], int len)
{
    int j, gap;

    for (gap = len / 2; gap > 0; gap /= 2)
        for (j = gap; j < len; j++)//从数组第gap个元素开始
            if (arr[j] < arr[j - gap])//每个元素与自己组内的数据进行直接插入排序
            {
                int temp = arr[j];
                int k = j - gap;
                while (k >= 0 && arr[k] > temp)
                {
                    arr[k + gap] = arr[k];
                    k -= gap;
                }
                arr[k + gap] = temp;
            }
}

输入

void test_shell_sort_plus(){
    int len = 6;
    Element arr[6] = {1, 2, 3, 7, 6, 5};
    shell_sort_plus(arr, len);
    printArr(arr,len);
};

运行结果

1 2 3 5 6 7 

其他

其实还有一种实现是用交换的方式.

void shell_sort_swap(int arr[], int len)
{
    int i, j, gap;

    for (gap = len / 2; gap > 0; gap /= 2)
        for (i = gap; i < len; i++)
            for (j = i - gap; j >= 0 && arr[j] > arr[j + gap]; j -= gap)
                swap(&arr[j], &arr[j + gap]);
}

code地址

https://github.com/HumorSmith/Alorthim/tree/master/sort

引用:

http://blog.csdn.net/morewindows/article/details/6668714
http://bubkoo.com/2014/01/15/sort-algorithm/shell-sort/

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值