算法学习之排序算法(四)(希尔排序)

1、算法思想

先将整个待排元素序列分割成若干个子序列(由相隔某个“增量”的元素组成的)分别进行直接插入排序,然后依次缩减增量再进行排序,待整个序列中的元素基本有序(增量足够小)时,再对全体元素进行一次直接插入排序。因为直接插入排序在元素基本有序的情况下(接近最好情况),效率是很高的,因此希尔排序在时间效率上比前两种方法有较大提高。

希尔(Shell)排序又称为缩小增量排序,它是一种插入排序。它是直接插入排序算法的一种威力加强版。

希尔排序的基本思想是

把记录按步长 gap 分组,对每组记录采用直接插入排序方法进行排序。

随着步长逐渐减小,所分成的组包含的记录越来越多,当步长的值减小到 1 时,整个数据合成为一组,构成一组有序记录,则完成排序。

在上面这幅图中:

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

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

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

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

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

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

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

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

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

2、代码实现(严格定义)

void shellsort1(int a[], int n)
{
    int i, j, gap;

    for (gap = n / 2; gap > 0; gap /= 2) //步长
        for (i = 0; i < gap; i++)        //直接插入排序
        {
            for (j = i + gap; j < n; j += gap)
                if (a[j] < a[j - gap])
                {
                    int temp = a[j];
                    int k = j - gap;
                    while (k >= 0 && a[k] > temp)
                    {
                        a[k + gap] = a[k];
                        k -= gap;
                    }
                    a[k + gap] = temp;
                }
        }
}

3、改进代码

void shellsort2(int a[], int n)
{
    int j, gap;

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

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-08-24 04:19:08

算法学习之排序算法(四)(希尔排序)的相关文章

排序四 希尔排序

要点 希尔(Shell)排序又称为缩小增量排序,它是一种插入排序.它是直接插入排序算法的一种威力加强版. 该方法因DL.Shell于1959年提出而得名. 希尔排序的基本思想是:把记录按下标的一定增量 gap 分组,对每组记录采用直接插入排序方法进行排序.随着增量逐渐减小,所分成的组包含的记录越来越多,到增量的值减小到 1 时,整个数据合成为一组,构成一组有序记录,则完成排序. 我们来通过演示图,更深入的理解一下这个过程. 在上面这幅图中: 初始时,有一个大小为 10 的无序序列. 在第一趟排序

SDUT 3403 数据结构实验之排序六:希尔排序

数据结构实验之排序六:希尔排序 Time Limit: 1000MS Memory Limit: 65536KB Submit Statistic Problem Description 我们已经学习了各种排序方法,知道在不同的情况下要选择不同的排序算法,以期达到最好的排序效率:对于待排序数据来说,若数据基本有序且记录较少时, 直接插入排序的效率是非常好的,希尔排序就是针对一组基本有序的少量数据记录进行排序的高效算法.你的任务是对于给定的数据进行希尔排序,其中增量dk=n/(2^k)(k=1,2

13. 蛤蟆的数据结构进阶十三排序实现之希尔排序法

13. 蛤蟆的数据结构进阶十三排序实现之希尔排序法 本篇名言:"一个人光溜溜的到这个世界来 ,最后光溜溜的离开这个世界而去 , 彻底想起来 , 名利都是身外物 ,只有尽一人的心力 , 使社会上的人多得他工作的裨益 ,是人生最愉快的事情.--邹韬奋" 下面是希尔排序法了. 欢迎转载,转载请标明出处:http://blog.csdn.net/notbaron/article/details/47706135 1.  希尔排序 希尔排序(ShellSort)是插入排序的一种.也称缩小增量排序

算法学习笔记 KMP算法之 next 数组详解

最近回顾了下字符串匹配 KMP 算法,相对于朴素匹配算法,KMP算法核心改进就在于:待匹配串指针 i 不发生回溯,模式串指针 j 跳转到 next[j],即变为了 j = next[j]. 由此时间复杂度由朴素匹配的 O(m*n) 降到了 O(m+n), 其中模式串长度 m, 待匹配文本串长 n. 其中,比较难理解的地方就是 next 数组的求法.next 数组的含义:代表当前字符之前的字符串中,有多大长度的相同前缀后缀,也可看作有限状态自动机的状态,而且从自动机的角度反而更容易推导一些. "前

经典排序算法学习笔记四——希尔排序

一.希尔排序 数据结构 数组 最差时间复杂度 根据步长序列的不同而不同.已知最好的:O(n*log ^{2}n) 最优时间复杂度 O(n) 平均时间复杂度 根据步长序列的不同而不同. 最差空间复杂度 O(n) 1.算法思想: 先取一个正整数d1<n,把所有序号相隔d1的数组元素放一组,组内进行直接插入排序: 然后取d2<d1,重复上述分组和排序操作: 直至di=1,即所有记录放进一个组中排序为止. 我是栗子,栗子,栗子 假设有这样一组数[ 13 14 94 33 82 25 59 94 65

算法(第四版)学习笔记之java实现希尔排序

希尔排序思想:使数组中任意间隔为h的元素都是有序的.希尔排序是插入排序的优化,先对数组局部进行排序,最后再使用插入排序将部分有序的数组排序. 代码如下: /** * * @author seabear * */ public class ShellSort { public static void sort(Comparable[] a) { int N = a.length; int h = 1; while(h < N/2) { h = 4 * h + 1; } while(h >= 1)

数据结构和算法之排序六:希尔排序

经过前面五篇排序方法的介绍,我们了解到了递归思想以及分而治之的归并和快速排序,当然也涉及到了比较简单易懂的数据值传递冒泡,选择,以及插入排序.可以说每一种排序方式都各有千秋,都适合在不同的环境下进行使用,但是我们有时会不会思考一个问题,那就是我们在学习插入排序的时候的主题思想是将每一个数据取出来,然后和后边的前边的数据逐一进行比较,那么,我们是不是要进行N-1次的循环,或者说我们是不是要进行大约N的平方次比较,我们知道,在进行值的交换和比较是非常消耗时间的,那么是不是违背了我们算法的发展.有没有

排序系列 之 希尔排序算法 —— Java实现

基本思想: 希尔排序的实质就是分组插入排序,又称缩小增量法. 将整个无序序列分割成若干个子序列(由相隔某个"增量"的元素组成的)分别进行直接插入排序,然后依次缩减增量再进行排序,待整个序列中的元素基本有序时,再对全体元素进行一次直接插入排序. 因为直接插入排序在元素基本有序的情况下,效率是很高的,因此希尔排序在时间效率上有很大提高. 实例: 无序序列:int a[] = {3,1,5,7,2,4,9,6}; 第一趟时: n=8; gap=n/2=4; 把整个序列共分成了4个子序列{3,

算法学习(二):O(n^2)排序算法

总结一下学习的复杂度为O(n^2)的三种排序算法:选择排序,插入排序,希尔排序. (1)选择排序:从第一个位置开始每次查找剩下的位置中最小的数值放入当前位置: (2)插入排序:从第二个位置开始,每次都将当前位置的数值插入前面合适的位置,对于几乎有序的数列来说,插入排序能带来更高的效率: (3)希尔排序:变步长区间的插入排序,指定一个步长衰减率,每一轮插入排序都将间隔指定步长的数值排序完成,当步长衰减为1时,就成了标准的插入排序. 代码实现: (1)选择排序 var selectSort = fu

数据结构和算法学习六,之非递归排序

http://blog.csdn.net/feixiaoxing/article/details/6844826 在上面一篇博客当中,我们发现普通查找和排序查找的性能差别很大.作为一个100万的数据,如果使用普通的查找方法,那么每一个数据查找平均下来就要几十万次,那么二分法的查找呢,20多次就可以搞定.这中间的差别是非常明显的.既然排序有这么好的效果,那么这篇博客中,我们就对排序算做一个总结. 按照我个人的理解,排序可以分为两种:一种是非递归排序,它主要按照非递归的方法对数据进行排序,也就是说主