(4)排序之希尔排序

转载:http://www.cnblogs.com/jingmoxukong/p/4303279.html

要点

希尔(Shell)排序又称为缩小增量排序,它是一种插入排序。它是直接插入排序算法的一种威力加强版。该方法因DL.Shell于1959年提出而得名。

希尔排序的基本思想是:

把记录按步长 gap 分组,对每组记录采用直接插入排序方法进行排序。 随着步长逐渐减小,所分成的组包含的记录越来越多,当步长的值减小到 1 时,整个数据合成为一组,构成一组有序记录,则完成排序。

我们来通过演示图,更深入的理解一下这个过程。

在上面这幅图中:

初始时,有一个大小为 10 的无序序列。

第一趟排序中,我们不妨设 gap1 = N / 2 = 5,即相隔距离为 5 的元素组成一组,可以分为 5 组。

接下来,按照直接插入排序的方法对每个组进行排序。

第二趟排序中,我们把上次的 gap 缩小一半,即 gap2 = gap1 / 2 = 2 (取整数)。这样每相隔距离为 2 的元素组成一组,可以分为 2 组。

按照直接插入排序的方法对每个组进行排序。

第三趟排序中,再次把 gap 缩小一半,即gap3 = gap2 / 2 = 1。 这样相隔距离为 1 的元素组成一组,即只有一组。

按照直接插入排序的方法对每个组进行排序。此时,排序已经结束

需要注意一下的是,图中有两个相等数值的元素 5 和 5 。我们可以清楚的看到,在排序过程中,两个元素位置交换了

所以,希尔排序是不稳定的算法。

核心代码

void shellSort(int *a,int n){
    int gap=n/2;
    while(gap>=1){
        //把距离为gap的元素编为一个组,扫描所有组
        for(int i=gap;i<n;i++){
            int j=0;
            int temp=a[i];
            //对距离为gap的元素组进行排序
            for(j=i-gap;j>=0&&temp<a[j];j=j-gap)//一定要注意!!!
                a[j+gap]=a[j];
            a[j+gap]=temp;
        }
        gap/=2;//减少增量
    }
}

算法分析

希尔排序的算法性能


排序类别


排序方法


时间复杂度


空间复杂度


稳定性


复杂性


平均情况


最坏情况


最好情况


插入排序


希尔排序


O(Nlog2N)


O(N1.5)


 


O(1)


不稳定


较复杂

时间复杂度

步长的选择是希尔排序的重要部分。只要最终步长为1任何步长序列都可以工作。

算法最开始以一定的步长进行排序。然后会继续以一定步长进行排序,最终算法以步长为1进行排序。当步长为1时,算法变为插入排序,这就保证了数据一定会被排序。 Donald Shell 最初建议步长选择为N/2并且对步长取半直到步长达到1。虽然这样取可以比O(N2)类的算法(插入排序)更好,但这样仍然有减少平均时间和最差时间的余地。可能希尔排序最重要的地方在于当用较小步长排序后,以前用的较大步长仍然是有序的。比如,如果一个数列以步长5进行了排序然后再以步长3进行排序,那么该数列不仅是以步长3有序,而且是以步长5有序。如果不是这样,那么算法在迭代过程中会打乱以前的顺序,那就不会以如此短的时间完成排序了。

已知的最好步长序列是由Sedgewick提出的(1, 5, 19, 41, 109,...)

这项研究也表明“比较在希尔排序中是最主要的操作,而不是交换。”用这样步长序列的希尔排序比插入排序和堆排序都要快,甚至在小数组中比快速排序还快,但是在涉及大量数据时希尔排序还是比快速排序慢。

算法稳定性

由上文的希尔排序算法演示图即可知,希尔排序中相等数据可能会交换位置,所以希尔排序是不稳定的算法。

直接插入排序和希尔排序的比较

直接插入排序是稳定的;而希尔排序是不稳定的。

直接插入排序更适合于原始记录基本有序的集合。

希尔排序的比较次数和移动次数都要比直接插入排序少,当N越大时,效果越明显。

在希尔排序中,增量序列gap的取法必须满足:最后一个步长必须是 

直接插入排序也适用于链式存储结构;希尔排序不适用于链式结构

运行结果

排序前:      9    1    2    5    7    4    8    6    3    5

gap = 5:    4    1    2    3    5    9    8    6    5    7

gap = 2:    2    1    4    3    5    6    5    7    8    9

gap = 1:    1    2    3    4    5    5    6    7    8    9

排序后:      1    2    3    4    5    5    6    7    8    9

时间: 2024-08-29 03:48:29

(4)排序之希尔排序的相关文章

JavaScript排序算法(希尔排序、快速排序、归并排序)

以var a = [4,2,6,3,1,9,5,7,8,0];为例子. 1.希尔排序. 希尔排序是在插入排序上面做的升级.是先跟距离较远的进行比较的一些方法. function shellsort(arr){ var i,k,j,len=arr.length,gap = Math.ceil(len/2),temp; while(gap>0){ for (var k = 0; k < gap; k++) { var tagArr = []; tagArr.push(arr[k]) for (i

高级排序之希尔排序

希尔排序对于多达几千个数据项的,中等大小规模的数组排序表现良好,希尔排序不像快速排序和其它时间复杂度为O(n*logn)的排序算法那么快,因此,对非常大的文件排序,它不是最优选择,但是希尔排序比选择排序和插入排序这种时间复杂度为O(n²)的排序要快的多,并且它非常容易实现,代码简短 希尔排序也是插入排序的一种,在插入排序中,如果最小的数在最后面,则复制的次数太多,而希尔解决了这个问题,它也是n-增量排序,它的思想是通过加大插入排序中元素的间隔,并在这些有间隔的元素中进行插入排序,当这些数据项排过

插入排序、冒泡排序、选择排序、希尔排序、快速排序、归并排序、堆排序和LST基数排序——C++实现

首先是算法实现文件Sort.h,代码如下: /* * 实现了八个常用的排序算法:插入排序.冒泡排序.选择排序.希尔排序 * 以及快速排序.归并排序.堆排序和LST基数排序 * @author gkh178 */ #include <iostream> template<class T> void swap_value(T &a, T &b) { T temp = a; a = b; b = temp; } //插入排序:时间复杂度o(n^2) template<

处理海量数据的高级排序之——希尔排序(C++)

希尔算法简介                                                                                                                                        常见排序算法一般按平均时间复杂度分为两类:O(n^2):冒泡排序.选择排序.插入排序O(nlogn):归并排序.快速排序.堆排序 简单排序时间复杂度一般为O(n^2),如冒泡排序.选择排序.插入排序等高级排序时间复杂

数据结构 排序(希尔排序)

//排序--希尔排序法 #include<stdio.h> #include<stdlib.h> #include<string.h> #include<time.h> /* 强调:网上,书上的希尔排序法都有问题 希尔排序并非按一个增量d,将一个数组分成若干小的数组,对每个数组进行插入排序,这个理论不适用下面的代码 也不符合希尔排序的时间复杂度 真正的希尔排序步骤 第一步,通过业界常规 d = 数组长度 / 3 + 1; 求出增量d 第二步:取数组第一个元素

(转载)经典排序算法-希尔排序

经典排序算法 - 希尔排序Shell sort 希尔排序Shell Sort是基于插入排序的一种改进,同样分成两部分, 第一部分,希尔排序介绍 第二部分,如何选取关键字,选取关键字是希尔排序的关键 第一块希尔排序介绍 准备待排数组[6 2 4 1 5 9] 首先需要选取关键字,例如关键是3和1(第一步分成三组,第二步分成一组),那么待排数组分成了以下三个虚拟组: [6 1]一组 [2 5]二组 [4 9]三组 看仔细啊,不是临近的两个数字分组,而是3(分成了三组)的倍数的数字分成了一组, 就是每

【排序】希尔排序算法

    特别说明: 对于算法,重在理解其思想.解决问题的方法,思路.因此,以下内容全都假定待排序序列的存储结构为:顺序存储结构.     希尔排序算法摘要: 希尔排序又称为“缩小增量排序”.直接插入排序算法在效率上虽说没办法突破 ,但其在少量数据或待排序列基本有序的情况下,效率却是非常高效的.因此,为进一步提高排序算法的效率,就需要适当地构造前述的那些条件.希尔排序就是第一批突破排序算法时间复杂度  的一个算法.因此,希尔排序算法算是一种属于插入排序类别的方法. 希尔排序算法思想: 算法总体描述

经典排序算法 - 希尔排序Shell sort

经典排序算法 - 希尔排序Shell sort 希尔排序Shell Sort是基于插入排序的一种改进,同样分成两部分, 第一部分,希尔排序介绍 第二部分,如何选取关键字,选取关键字是希尔排序的关键 第一块希尔排序介绍 准备待排数组[6 2 4 1 5 9] 首先需要选取关键字,例如关键是3和1(第一步分成三组,第二步分成一组),那么待排数组分成了以下三个虚拟组: [6 1]一组 [2 5]二组 [4 9]三组 看仔细啊,不是临近的两个数字分组,而是3(分成了三组)的倍数的数字分成了一组, 就是每

20191209-八大排序之希尔排序

1. 希尔排序 算法核心思想 希尔排序本质也是一种插入排序,但是是根据简单插入排序进行优化后的一种更加高效的版本,别称缩小增量排序.希尔排序的核心思想是将排序数组按照步长进行分组,然后对分组的元素进行直接插入排序,循环缩小分组步长,最后当步长长度为1的时候排序结束.希尔排序在数组中采用的是跳跃式分组的策略,通过某个增量将数组元素划分为若干组,然后分组进行插入排序,随后逐步缩小增量,继续按组进行插入排序操作,直至增量为1.具体逻辑如下: 设定初始步长为gap=len(arr)//2 按照步长遍历列

奔走在算法的大路上(一)排序之希尔排序

希尔排序是插入排序的一种更高效的改进版本.它的作法不是每次一个元素挨一个元素的比较.而是初期选用大跨步(增量较大)间隔比较,使记录跳跃式接近它的排序位置:然后增量缩小:最后增量为 1 ,这样记录移动次数大大减少,提高了排序效率.希尔排序对增量序列的选择没有严格规定. 希尔排序最关键的是选对增量,关于增量的选择,建议参考:http://zh.wikipedia.org/wiki/希尔排序  中的步长序列. 希尔排序的核心思想是:由一定规则将带排序的长序列切割成多个子序列,子序列进行内部插入排序,如