华杰让我看了一道面试题:现有一段程序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实现


public class ShellSort {

	public static void main(String[] args) {

		int[] arr = new int[]{44,33,99,10,30,20,59,78,23,48};
		System.out.print("排序前:");
		for(int o: arr) {
			System.out.print(o+" ");
		}
		System.out.println();
		shellSort(arr);
		System.out.print("排序后:");
		for(int o: arr) {
			System.out.print(o+" ");
		}
		System.out.println();
	}

	private static void shellSort(int[] arr) {

		int j;
		int len = arr.length;
		for(int val=len>>1; val>0; val>>=1) {
			//下面是对本次的所有分组做直接插入排序
			for(int i=val; i<len; i++) {
				int temp = arr[i];
				/*
				 * 为什么每次都用temp比较呢?
				 * 因为直接插入就是找到temp的合适位置。
				 * 为什么temp<arr[j-val]这个条件可以放在for内呢?
				 * 因为原来的组内数据已经有序,找到位置就停止便是。
				 * 不甚理解的去看直接插入排序吧。
				 */
				for(j=i; j>=val&&temp<arr[j-val]; j-=val) {
					/*
					 * 为什么是arr[j-val]不是arr[j]呢?
					 * 因为j=i开始的,而且条件是j>=val&&temp<arr[j-val]
					 */
					arr[j] = arr[j-val];
				}
				/*
				 * 注意不是arr[i] = temp
				 * 直接插入排序也是这样的。
				 * 为什么呢?
				 * 因为j是位置,i是待插入元素
				 */
				arr[j] = temp;
			}
		}
	}

}

三.问题

        希尔排序一定正确么?换句话说如何选取增量序列才能保证正确(包括长度、值)?是的,最后一次只要保证增量是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. [Node.js] Web Scraping with Pagination and Advanced Selectors

    When web scraping, you'll often want to get more than just one page of data. Xray supports paginatio ...

  2. hdu2047.java递推题

    阿牛的EOF牛肉串 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total S ...

  3. 数据库的CRUD操作

    一:数据库的CRUD操作,C是指create新增,R是指retrieve检索,U是指update更改,D是指delete删除 SQL语句分为3类: 1.DDL指数据定义语言如:create,drop, ...

  4. C#选择文件、选择文件夹、打开文件(或者文件夹)

    1.选择文件用OpenDialog OpenFileDialog dialog = new OpenFileDialog(); dialog.Multiselect = true;//该值确定是否可以 ...

  5. HTML+CSS基础学习笔记(3)

    一.提交按钮.重置按钮 1.type="submit" 提交按钮 2.type="reset"   重置按钮 二.form表单中的label标签 格式: < ...

  6. html不同文档类型支持的元素标签

  7. 文件夹IsShow字段为空

    IsShow为YesNo字段,默认值为Yes:在Library中新建一个文件的时候会给出默认值yes,但是新建一个文件夹的时候,默认为空,所以f.Item["IsShow"]为空, ...

  8. dispatchkeyevent的调用机制

    http://blog.csdn.net/look85/article/details/23740761 dispatchKeyEvent和onKeyDown关系: 当键盘按下时 首先触发dispat ...

  9. 初学HTML5系列二:HTML5新增的事件属性

    Window事件属性: 属性 值 描述 onafterprint  script 文档打印之后运行的脚本. 属性发生于用户设置页面打印并且打印对话框已出现之后. onbeforeprint  scri ...

  10. SET NOCOUNT 的意义.

    SET NOCOUNT 使返回的结果中不包含有关受 Transact-SQL 语句影响的行数的信息. 语法 SET NOCOUNT { ON | OFF } 当 SET NOCOUNT 为 ON 时, ...