华杰让我看了一道面试题:现有一段程序S,可以对任意n个数进行排序。如果现在需要对n^2个数进行排序,最少需要调用S多少次?(只允许调用S,不可以做别的操作)。

        看到了这个,我想试试希尔排序,就学学。

一.理论准备

        希尔排序是基于直接插入排序的,不懂得请看这一篇http://www.cnblogs.com/hxsyl/archive/2013/06/02/3113656.html

        希尔排序(Shell Sort)是插入排序的一种,是针对直接插入排序算法的改进,是将整个无序列分割成若干小的子序列分别进行插入排序,希尔排序并不稳定。该方法又称缩小增量排序,因DL.Shell于1959年提出而得名。

        基本思想:先取一个小于n的整数d1作为第一个增量,把文件的全部记录分成d1个组。所有距离为d1的倍数的记录放在同一个组中。先在各组内进行直接插入排序;然后,取第二个增量d2<d1重复上述的分组和排序,直至所取的增量dt=1(dt<dt-l<…<d2<d1),即所有记录放在同一组中进行直接插入排序为止。

     希尔排序的时间性能优于直接插入排序的原因:
     ①当文件初态基本有序时直接插入排序所需的比较和移动次数均较少。
     ②当n值较小时,n和n2的差别也较小,即直接插入排序的最好时间复杂度O(n)和最坏时间复杂度0(n2)差别不大。
     ③在希尔排序开始时增量较大,分组较多,每组的记录数目少,故各组内直接插入较快,后来增量di逐渐缩小,分组数逐渐减少,而各组的记录数目逐渐增多,但由于已经按di-1作为距离排过序,使文件较接近于有序状态,所以新的一趟排序过程也较快。
        因此,希尔排序在效率上较直接插人排序有较大的改进。

        增量序列的选择:Shell排序的执行时间依赖于增量序列。
    好的增量序列的共同特征(查到的资料都这么讲):
     ① 最后一个增量必须为1;
     ② 应该尽量避免序列中的值(尤其是相邻的值)互为倍数的情况。      

二.Java实现

  1. public class ShellSort {
  2.  
  3. 	public static void main(String[] args) {
  4.  
  5. 		int[] arr = new int[]{44,33,99,10,30,20,59,78,23,48};
  6.  
  7. 		System.out.print("排序前:");
  8.  
  9. 		for(int o: arr) {
  10.  
  11. 			System.out.print(o+" ");
  12.  
  13. 		}
  14.  
  15. 		System.out.println();
  16.  
  17. 		shellSort(arr);
  18.  
  19. 		System.out.print("排序后:");
  20.  
  21. 		for(int o: arr) {
  22.  
  23. 			System.out.print(o+" ");
  24.  
  25. 		}
  26.  
  27. 		System.out.println();
  28.  
  29. 	}
  30.  
  31. 	private static void shellSort(int[] arr) {
  32.  
  33. 		int j;
  34.  
  35. 		int len = arr.length;
  36.  
  37. 		for(int val=len>>1; val>0; val>>=1) {
  38.  
  39. 			//下面是对本次的所有分组做直接插入排序
  40.  
  41. 			for(int i=val; i<len; i++) {
  42.  
  43. 				int temp = arr[i];
  44.  
  45. 				/*
  46.  
  47. 				 * 为什么每次都用temp比较呢?
  48.  
  49. 				 * 因为直接插入就是找到temp的合适位置。
  50.  
  51. 				 * 为什么temp<arr[j-val]这个条件可以放在for内呢?
  52.  
  53. 				 * 因为原来的组内数据已经有序,找到位置就停止便是。
  54.  
  55. 				 * 不甚理解的去看直接插入排序吧。
  56.  
  57. 				 */
  58.  
  59. 				for(j=i; j>=val&&temp<arr[j-val]; j-=val) {
  60.  
  61. 					/*
  62.  
  63. 					 * 为什么是arr[j-val]不是arr[j]呢?
  64.  
  65. 					 * 因为j=i开始的,而且条件是j>=val&&temp<arr[j-val]
  66.  
  67. 					 */
  68.  
  69. 					arr[j] = arr[j-val];
  70.  
  71. 				}
  72.  
  73. 				/*
  74.  
  75. 				 * 注意不是arr[i] = temp
  76.  
  77. 				 * 直接插入排序也是这样的。
  78.  
  79. 				 * 为什么呢?
  80.  
  81. 				 * 因为j是位置,i是待插入元素
  82.  
  83. 				 */
  84.  
  85. 				arr[j] = temp;
  86.  
  87. 			}
  88.  
  89. 		}
  90.  
  91. 	}
  92.  
  93. }
  94.  

三.问题

        希尔排序一定正确么?换句话说如何选取增量序列才能保证正确(包括长度、值)?是的,最后一次只要保证增量是1就ok(不管序列长度,只不过效率就低了),若是序列只有1,那就是直接插入排序了,不知道对否。

四.结束语

        写完正准备叫老婆去吃饭,隔壁宿舍一哥们过来说大一新生已经攻占食堂了。

Java实现希尔排序的更多相关文章

  1. Java实现希尔排序(增量递减排序)

    package Insert.sort; import java.util.Scanner; /*又叫缩小增量排序,本质是插入排序,将待排的序列增量分成几个子序列,分别对每个子序列进行直接插入排序 * ...

  2. JAVA数据结构--希尔排序

    希尔排序通过将比较的全部元素分为几个区域来提升插入排序的性能.这样可以让一个元素可以一次性地朝最终位置前进一大步.然后算法再取越来越小的步长进行排序,算法的最后一步就是普通的插入排序,但是到了这步,需 ...

  3. Java之希尔排序

    希尔排序 前面已经知道了插入排序,明白插入排序的原理,不断比较来交换相邻的元素,这样的话效率不高,为此希尔排序,在插入排序上做出了改进,通过间隔增量来比较并交换元素,这样可以减少比较交换的次数. pa ...

  4. Java算法-希尔排序

    希尔排序的诞生是由于插入排序在处理大规模数组的时候会遇到需要移动太多元素的问题.希尔排序的思想是将一个大的数组“分而治之”,划分为若干个小的数组,以 gap 来划分,比如数组 [1, 2, 3, 4, ...

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

    希尔排序思想:使数组中随意间隔为h的元素都是有序的. 希尔排序是插入排序的优化.先对数组局部进行排序,最后再使用插入排序将部分有序的数组排序. 代码例如以下: /** * * @author seab ...

  6. 排序算法:Java实现希尔排序

    希尔排序的思路是先分组再整合 先对下标进行分组,比如当数组长度为20时,一开始选定一个间隔值为10 对数组进行排序,每隔10个元素比较大小并交换,以下标为间隔,1和11比较.2和12比较......1 ...

  7. java算法----排序----(6)希尔排序(最小增量排序)

    package log; public class Test4 { /** * java算法---希尔排序(最小增量排序) * * @param args */ public static void ...

  8. 【算法拾遗(java描写叙述)】--- 插入排序(直接插入排序、希尔排序)

    插入排序基本思想 每次将一个待排序的记录按其keyword大小插入到前面已经拍好序的子文件的适当位置,直到全部记录插入完毕为止. 直接插入排序 基本思想 直接插入排序的基本操作是将一个记录插入到已排好 ...

  9. 排序之希尔排序(shell sort)

    前言 本篇博客是在伍迷兄的博客基础上进行的,其博客地址点击就可以进去,里面好博客很多,我的排序算法都来自于此:一些数据结构方面的概念我就不多阐述了,伍迷兄的博客中都有详细讲解,而我写这些博客只是记录自 ...

随机推荐

  1. chrome下老是弹出网页显示 true

    事实上这个问题是chrome下安装了一些插件的原因,一般来说是安装迅雷插件会出现这个问题,删除迅雷插件就好了.

  2. [Ionic] Ionic Quickstart for Windows

    1. Install ionic 2. Create ionic app ionic start myApp tabs //create a app cd myApp ionic serve // o ...

  3. Java 加密 base64 encode

    版权声明:本文为博主原创文章,未经博主允许不得转载. [前言] 计算机中的数据都是二进制的,不管是字符串还是文件,而加密后的也是二进制的, 而我们要看到的往往是字符串,本文就介绍了将byte[]转为各 ...

  4. JMeter使用记录1 -- JDBC測试

    场景:使用jmeter对web应用和mysql数据库进行压力測试 JMeter是一款很强大的測试工具.能够用来測试web,数据库.从07年用过之后一直对它情有独钟,以下记录下在一个项目中对它的简单使用 ...

  5. LabView 快捷键

    对象调整和移动Shift-click 选择多个对象,在现有选择的基础上添加对象(方向键) 以一个像素为单位移动所选对象Shift- 以几个像素为单位移动所选对象Shift-click (拖动对象) 在 ...

  6. c语言中的 %u 什么意思啊?

    %d 有符号10进制整数 %i 有符号10进制整数 %o 无符号8进制整数 %u 无符号10进制整数 %x 无符号的16进制数字,并以小写abcdef表示%X 无符号的16进制数字,并以大写ABCDE ...

  7. iOS 开发中的争议(二)

    这是该系列的第二篇.在本文中,我想讨论的是:对于 UI 界面的编写工作,到底应该用 xib/storyboard 完成,还是用手写代码来完成? 本着 “使用过才有发言权” 原则,我介绍一下我的经历: ...

  8. 使用Broadcast实现android组件之间的通信 分类: android 学习笔记 2015-07-09 14:16 110人阅读 评论(0) 收藏

    android组件之间的通信有多种实现方式,Broadcast就是其中一种.在activity和fragment之间的通信,broadcast用的更多本文以一个activity为例. 效果如图: 布局 ...

  9. 高效 jquery 的奥秘

    当你准备使用 jQuery,我强烈建议你遵循下面这些指南: 1. 缓存变量 DOM 遍历是昂贵的,所以尽量将会重用的元素缓存. // 糟糕 h = $('#element').height(); $( ...

  10. 在iis中mantisbt配置过程

    最近需要安装个mantisbt,由于不想再安装个apache服务器,因此直接使用iis作为php解析服务器.同时为了方便管理安装包,将php安装包和扩展包能够独立存放在D:\Program Files ...