精华内容
下载资源
问答
  • 目录:  1、为什么要用?(它的好处或优点)  2、原理是什么?(效果)  3、怎样去实现?... 1、时间复杂度: 平均情况:O(nlog2n) 根据步长序列的不同而不同、坏情况O(nlog2n) 根据步长序列的不...

    目录:

      1、为什么要用?(它的好处或优点)

      2、原理是什么?(效果)

      3、怎样去实现?(想马上看代码的同学点这里)

     

    为什么要用?

      希尔排序是直接插入排序的一种更高效的改进版本,是一种分组插入排序,而效率的优劣跟它所使用的步长序列有直接关系。

      1、时间复杂度: 平均情况:O(nlog2n)  根据步长序列的不同而不同、最坏情况O(nlog2n) 根据步长序列的不同而不同 ,最好情况O(n) 

      2、空间复杂度: O(1)

      3、稳定性: 不稳定

      4、复杂度:较直接插入排序复杂

      适用场景: 有研究表明“比较在希尔排序中是最主要的操作,而不是交换。”用已知最好的(塞奇威克(Sedgewick)提出的)步长序列的希尔排序比直接插入排序要快,甚至在小数组中比快速排序和堆排序还快,但是在涉及大量数据时希尔排序还是比快速排序慢。

     

    原理是什么?

      原理描述:

       插入排序由来已久了,相信看过 直接插入排序 的同学已经对插入排序有了一定的了解,聪明的同学肯定发现了它的两个规律:

        1、 对几乎已经排好序的数据操作效率特别高,甚至可以达到线性O(n)

        2、 对于一般的无序数据效率低,特别是逆序数据。

      那么是不是有什么方法可以提高它的效率呢?  答案是肯定的。整个直接插入排序的过程可以理解为,每找到一个小数就把它插入到前面来,而大数就相应的向后挤的过程,而大数自己是不会往后走的,也就是说每个小数在向前移动的过程中都要与前面的大数进行比较交换操作,

      就好像每个小个子要想去往正确的位置都需先越过前面的大个子,多么苦逼的一件事。。。

      人们肯定会想如果大的数一开始就在后面那就好了,有句话叫“没有条件,创造条件也要上”,那就先上数组变的相对有序,在用直接插入排序就好啦!  具体办法就是把数据分组组内排序,然后再次 数据分组+组内排序,且分组数量递减,直到分组数为1,也就是直接插入排序啦!  这就是 希尔排序,也称递减增量排序算法的思想啦!

    希尔排序的排序效率和选择步长序列有直接关系,相关步长序列如下,目前最好的序列是 4、塞奇威克(Sedgewick) 的步长序列(摘自维基百科

    1、希尔(Shell)原始步长序列:N / 2,N / 4,...,1(重复除以2);
    2、希伯德(Hibbard)的步长序列:1,3,7,...,2 k - 1;
    3、克努特(Knuth)的步长序列:1,4,13,...,(3 k - 1)/ 2;
    4、塞奇威克(Sedgewick) 的步长序列:1,5,19,41,109,....
      它是通过交织两个序列的元素获得的: 步长序列数组下标 n 从0开始

      n偶数用 :1,19,109,505,2161,...,9(4 k - 2 k)+ 1,k = 0,1,2,3,... 

      n奇数用 :5,41,209,929,3905,...。k + 2(2 k + 2 - 3)+ 1,k = 0,1,2,3,...

     

    例如  按步长序列 [1,3,5,...] 对数组[ 13 14 94 33 82 25 59 94 65 23 45 27 73 25 39 10 ] 进行希尔排序,首先按步长为5 进行分组,每行为一个分组得到:

    13   25   45   10
    14   59   27
    94   94   73
    33   65   25
    82   23   39

     

     然后对每行分组进行排序得到:

    10   13   25   45 
    14   27   59
    73   94   94
    25   33   65
    23   39   82 

     

    然后再按步长为3进行分组,每行为一个分组得到:

    10   25   27   39   94   45 
    14   23   94   25   65
    73   13   33   59   82

     

    对每行分组进行排序得到:

    10   25   27   39   45   94 
    14   23   25   65   94
    13   33   59   73   82

     

    至此初始数组:

          [ 13 14 94 33 82 25 59 94 65 23 45 27 73 25 39 10 ]

    而现在的数组:

          [ 10 14 13 25 23 33 27 25 59 39 65 73 45 94 82 94 ]

    在来一次直接插入排序或说事步长为1的分组并排序就得到最终结果了

    10   13   14   23   25   25   27   33   39   45   59   65   73   82   94   94 

     

    看起来 比直接分组排序 多了些步骤,而实际上 是让一些小数跳过了一些比较和交换操作,直接从后面跳到了前面,从而提高了效率

    在分组中的排序步骤同 直接分组排序如下:

    宏观效果:

        

    怎样去实现?

    使用已知的最好的由 塞奇威克(Sedgewick) 提出的步长序列:1,5,19,41,109,.... 

      它是通过交织两个序列的元素获得的: 步长序列数组下标 n 从0开始

     

      n偶数用 :1,19,109,505,2161,...,9(4 k - 2 k)+ 1,k = 0,1,2,3,... 

     

      n奇数用 :5,41,209,929,3905,...。k + 2(2 k + 2 - 3)+ 1,k = 0,1,2,3,...

     

    java 实现代码:

     

    import java.lang.Math;
    
    class shell_sort {
        // 塞奇威克(Sedgewick) 步长序列函数, 传入数组长度(最大分组个数不可超过数组长度)
        public static int[] Sedgewick(int length) 
        {     
            int[] arr = new int[length];
            int n,i = 0,j = 0;
            for(n = 0; n < length; n++)  
            {  
                if(n % 2 == 0)  
                {  
                    arr[n] = (int) (9 * ( Math.pow(4, i) - Math.pow(2, i) ) + 1); 
                    i++;
                }  
                else  
                {  
                    arr[n] = (int) (Math.pow(2, j+2) * ( Math.pow(2, j+2) - 3 ) + 1); 
                    j++;  
                }  
                if(arr[n] >= length)
                {  
                    break;
                }
            }
            int[] a = new int[n];
            for(int k = 0; k < a.length; k++){
                a[k] = arr[k];
            }
            System.out.println("步长序列:");
            printArray(a,0,1);
            return a;
        }
        public static void shell(int[] arr){
            int[] sedgewick = Sedgewick(arr.length);// 得到塞奇威克(Sedgewick) 步长序列数组
            int s,k,i,j,t;
            // 循环出所有步长
            for(s = sedgewick.length -1 ; s >= 0 ; s--){
                // 步长为sedgewick[s] 即分为 sedgewick[s] 个组
                System.out.println("分"+ sedgewick[s] +"组");
                for(k = 0; k < sedgewick[s]; k++){
                    System.out.println("第"+ (k+1) +"组排序:");
                    // 对每组数据进行排序
                    printArray(arr,k,sedgewick[s]);
                    for(i = k + sedgewick[s]; i < arr.length; i += sedgewick[s]){
                        // 分组中,按插入排序排序数据,交换数据按步长 sedgewick[s]
                         t = arr[i];
                         j = i - sedgewick[s]; 
                         while(j >= 0 && arr[j] > t){
                             arr[j + sedgewick[s]] = arr[j];
                             j-=sedgewick[s];
                        }
                         arr[j+sedgewick[s]] = t;
                         printArray(arr,k,sedgewick[s]);
                    }
                    System.out.println();
                }
            }
            
        }
        public static void main (String[] args) throws java.lang.Exception
        {
             int[] arr = { 13,14,94,33,82,25,59,94,65,23,45,27,73,25,39,10};
             System.out.println("原数据:");
             printArray(arr,0,1);
             shell(arr);
        }
        public static void printArray(int[] arr,int i, int j){
            for(int n = i ; n < arr.length; n+= j){
                System.out.print(arr[n]+"   ");
            }
            System.out.println();
        }
    }

     

     

     

    输出结果 :

    原数据:
    13 14 94 33 82 25 59 94 65 23 45 27 73 25 39 10
    步长序列:
    1 5
    分5组
    第1组排序:
    13 25 45 10
    13 25 45 10
    13 25 45 10
    10 13 25 45

    第2组排序:
    14 59 27
    14 59 27
    14 27 59

    第3组排序:
    94 94 73
    94 94 73
    73 94 94

    第4组排序:
    33 65 25
    33 65 25
    25 33 65

    第5组排序:
    82 23 39
    23 82 39
    23 39 82

    分1组
    第1组排序:
    10 14 73 25 23 13 27 94 33 39 25 59 94 65 82 45
    10 14 73 25 23 13 27 94 33 39 25 59 94 65 82 45
    10 14 73 25 23 13 27 94 33 39 25 59 94 65 82 45
    10 14 25 73 23 13 27 94 33 39 25 59 94 65 82 45
    10 14 23 25 73 13 27 94 33 39 25 59 94 65 82 45
    10 13 14 23 25 73 27 94 33 39 25 59 94 65 82 45
    10 13 14 23 25 27 73 94 33 39 25 59 94 65 82 45
    10 13 14 23 25 27 73 94 33 39 25 59 94 65 82 45
    10 13 14 23 25 27 33 73 94 39 25 59 94 65 82 45
    10 13 14 23 25 27 33 39 73 94 25 59 94 65 82 45
    10 13 14 23 25 25 27 33 39 73 94 59 94 65 82 45
    10 13 14 23 25 25 27 33 39 59 73 94 94 65 82 45
    10 13 14 23 25 25 27 33 39 59 73 94 94 65 82 45
    10 13 14 23 25 25 27 33 39 59 65 73 94 94 82 45
    10 13 14 23 25 25 27 33 39 59 65 73 82 94 94 45
    10 13 14 23 25 25 27 33 39 45 59 65 73 82 94 94

     

    在线测试地址 :https://www.shucunwang.com/RunCode/java/#id/b8f9435e80e07068633bc3adf17c9cc7

    开源代码地址 :https://git.oschina.net/ITxiaoyan/SortAlgorithm

    更多排序算法请查看:排序算法笔记 http://www.cnblogs.com/daohuoren/p/6605077.html 

    2017-03-25 

    转载于:https://www.cnblogs.com/daohuoren/p/6614766.html

    展开全文
  • 怎样求最大值(最小值或中间值)平均数怎么弄 去掉其中两个最大值和两个最小值的公式 去一行最高分最低分求平均值 在9个数值中去掉最高与最低然后求平均值 求最大值(n列) 如何实现求平均值时只对不等于零的数求...
  • 猜人物猜音乐 将队员平均分组,主持人提三至四个条件,由各组员猜结果.猜得最多的组获胜 5. yes或no. 分组,主持人对每组准备几个词语,由组员分别提问,主持人只能用yes和no回答.看最短时间猜出最多的是哪个组. 6. 倒...
  • 猜人物猜音乐 将队员平均分组,主持人提三至四个条件,由各组员猜结果.猜得最多的组获胜 5. YES或NO. 分组,主持人对每组准备几个词语,由组员分别提问,主持人只能用YES和NO回答.看最短时间猜出最多的是哪个组. 6. 倒...
  • 猜人物猜音乐 将队员平均分组,主持人提三至四个条件,由各组员猜结果.猜得最多的组获胜 5. yes或no. 分组,主持人对每组准备几个词语,由组员分别提问,主持人只能用yes和no回答.看最短时间猜出最多的是哪个组. 6. 倒...
  • 室内团队游戏简介.doc

    2021-01-15 15:37:51
    猜人物猜音乐 将队员平均分组,主持人提三至四个条件,由各组员猜结果.猜得最多的组获胜 5. yes或no. 分组,主持人对每组准备几个词语,由组员分别提问,主持人只能用yes和no回答.看最短时间猜出最多的是哪个组. 6. 倒...
  • EXCEL函数公式集

    热门讨论 2010-03-16 03:26:38
    怎样求最大值(最小值或中间值)平均数怎么弄 去掉其中两个最大值和两个最小值的公式 去一行最高分最低分求平均值 在9个数值中去掉最高与最低然后求平均值 求最大值(n列) 如何实现求平均值时只对不等于零的数求...
  • 2019数据运营思维导图

    2019-03-29 21:34:09
    用户调研 用户留存分析流程 第一步:分组 按照不同的(时间/渠道/行为等)维度进行用户分组 时间分组 通常用于看整体数据,看整体留存是否出现异常情况 渠道分组 对比不同渠道留存数据 通过不同渠道数据对比,找到...
  • 数据运营思维导图

    2018-04-26 14:24:22
    5、平均使用时长和平均使用次数 可以使用柱状图来展现 两项宏观行为指标可反映出用户对app的依赖程度 如果留存较好,但时长和次数均不高,则可能是因过于强调每日登录奖励,但持续的app内容用户家缺乏吸引力所致 ...
  • C#.net_经典编程例子400个

    热门讨论 2013-05-17 09:25:30
    39 1.11 设置窗体位置 40 实例038 设置窗体在屏幕中的位置 40 实例039 始终在上面的窗体 41 1.12 设置窗体大小 42 实例040 限制窗体大小 42 实例041 获取桌面大小 42 实例042 ...
  • 实例039 始终在上面的窗体 41 1.12 设置窗体大小 42 实例040 限制窗体大小 42 实例041 获取桌面大小 42 实例042 在窗口间移动按钮 43 实例043 如何实现Office助手 44 1.13 窗体控制技术 45 实例044...
  • 实例039 始终在上面的窗体 41 实例040 从桌面右下角显示的窗体 41 1.12 设置窗体大小 43 实例041 获取桌面大小 43 实例042 在窗口间移动按钮 44 实例043 如何实现Office助手 45 1.13 窗体控制技术 46 实例044 在...
  • C#程序开发范例宝典(第2版).part02

    热门讨论 2012-11-12 07:55:11
    实例039 始终在上面的窗体 41 实例040 从桌面右下角显示的窗体 41 1.12 设置窗体大小 43 实例041 获取桌面大小 43 实例042 在窗口间移动按钮 44 实例043 如何实现Office助手 45 1.13 窗体控制技术 46 实例...
  • C#程序开发范例宝典(第2版).part13

    热门讨论 2012-11-12 20:17:14
    实例039 始终在上面的窗体 41 实例040 从桌面右下角显示的窗体 41 1.12 设置窗体大小 43 实例041 获取桌面大小 43 实例042 在窗口间移动按钮 44 实例043 如何实现Office助手 45 1.13 窗体控制技术 46 实例...
  • 实例039 始终在上面的窗体 41 实例040 从桌面右下角显示的窗体 41 1.12 设置窗体大小 43 实例041 获取桌面大小 43 实例042 在窗口间移动按钮 44 实例043 如何实现Office助手 45 1.13 窗体控制技术 46 实例...
  • 实例039 始终在上面的窗体 41 实例040 从桌面右下角显示的窗体 41 1.12 设置窗体大小 43 实例041 获取桌面大小 43 实例042 在窗口间移动按钮 44 实例043 如何实现Office助手 45 1.13 窗体控制技术 46 实例...
  • 程序开发范例宝典>>

    2012-10-24 10:41:28
    实例039 始终在上面的窗体 41 实例040 从桌面右下角显示的窗体 41 1.12 设置窗体大小 43 实例041 获取桌面大小 43 实例042 在窗口间移动按钮 44 实例043 如何实现Office助手 45 1.13 窗体控制...
  • 实例039 始终在上面的窗体 41 实例040 从桌面右下角显示的窗体 41 1.12 设置窗体大小 43 实例041 获取桌面大小 43 实例042 在窗口间移动按钮 44 实例043 如何实现Office助手 45 1.13 窗体控制技术 ...
  • 实例039 始终在上面的窗体 41 实例040 从桌面右下角显示的窗体 41 1.12 设置窗体大小 43 实例041 获取桌面大小 43 实例042 在窗口间移动按钮 44 实例043 如何实现Office助手 45 1.13 窗体控制技术 ...
  • C#程序开发范例宝典

    2010-12-15 20:05:16
    实例039 始终在上面的窗体...... 41 1.12 设置窗体大小...... 42 实例040 限制窗体大小...... 42 实例041 获取桌面大小...... 42 实例042 在窗口间移动按钮...... 43 实例043 如何实现Office助手.........
  • delphi 开发经验技巧宝典源码

    热门讨论 2010-08-12 16:47:23
    第1章 开发环境 1 1.1 环境设置 2 0001 如何定制工具栏 2 ...0296 如何在屏幕前面显示滚动字幕 192 0297 制作磁性窗体 193 0298 制作浮动窗口 194 0299 制作另类提示窗口 195 0300 将窗体...
  • 经典SQL语句大全

    热门讨论 2014-12-20 12:00:30
    3),例如:在一个外部表中导入数据,由于某些原因第一次只导入了一部分,但很难判断具体位置,这样只有在下一次全部导入,这样也就产生好多重复的字段,怎样删除重复字段 alter table tablename --添加一个自增列 add...
  • 3),例如:在一个外部表中导入数据,由于某些原因第一次只导入了一部分,但很难判断具体位置,这样只有在下一次全部导入,这样也就产生好多重复的字段,怎样删除重复字段 alter table tablename --添加一个自增列 ...
  • 10)按照性别分组查询所有的平均年龄 我的答案: select avg(age) from student group by sex; 18、什么是存储过程?为什么存储过程要比单纯的SQL语句执行起来要快? 我的答案: 存储过程算是一种优化...
  • See you in BUPT 北京邮电大学计算机考研报考资料、复试资料汇总 for 2020 适用报考范围: 计算机学院、网络技术研究院、网络空间安全学院、软件学院 QQ交流群1:460294132 QQ交流群2:263763735 ...

空空如也

空空如也

1 2
收藏数 25
精华内容 10
关键字:

怎样分组最平均