希尔排序是插入排序的一种,是直接插入排序的改进版本。

对于上节介绍的直接插入排序法,如果数据原来就已经按要求的顺序排列,则在排序过程中不需要进行数据移动操作,即可得到有序数列。但是,如果最初的数据是按倒序排列的,则在进行插入排序时每次的比较都需要向后移动数据,这样,将导致算法的效率很低。

希尔排序的思想是把数列划分为若干个较小的数列,对每组数列使用直接插入排序算法排序,随着增量逐渐减少,每组包含的数字越来越多,当增量减至1时,整个数列恰被分成一组,最后再使用一次直接插入排序对整个数列进行排序。

例如有4, 3, 6, 2, 7, 1, 5, 8八个数字,第一次分成四组,即8/2组。如下图,相同颜色的数字为一组,下标为x的数字和下标为x+4的数字为一组。

对这四个数组分别做直接插入排序,即两两比较,如果大的在前则交换位置,得到:

然后缩小组数,4/2=2,缩小为两组。如下图:

对这两个数组分别做直接插入排序,得到:

再次缩小组数,2/2=1,缩小为一组,那么所有数字都。如下图:

最后,对4, 1, 5, 2, 6, 3, 7, 8这个数列执行一次直接插入排序。

总结上面的规律,可以得出:

第一次分组数s = n / 2 == 0 ? n / 2 : n / 2 + 1

取数规则是[x]和[x+n/2]为一组

当然,这只是比较简单的分组方式,不一定是最优的。来看代码:

  1. public class ShellSort {
  2. private int[] numbers;
  3. public ShellSort(int[] numbers) {
  4. this.numbers = numbers;
  5. }
  6. /**
  7. * 对数组分组并对每个组做直接插入排序, 完成后缩小组的数量, 重复插入排序, 直到缩小到一个组
  8. * 第一次分组数: section = n/2 == 0 ? n/2 : n/2+1, 分组规则: 每隔n/2挑一个数, 即[x]和[x+n/2]为一组
  9. */
  10. public void sort() {
  11. int section = this.numbers.length / 2;
  12. int j;
  13. int temp;
  14. while(section >= 1) {
  15. for(int i = section; i < this.numbers.length; i++) {
  16. temp = this.numbers[i];
  17. j = i - section;
  18. while(j >= 0 && this.numbers[j] > temp) {
  19. this.numbers[j + section] = this.numbers[j];
  20. j = j - section;
  21. }
  22. this.numbers[j + section] = temp;
  23. }
  24. section /= 2;
  25. }
  26. System.out.print("排序后: ");
  27. for(int x = 0; x < numbers.length; x++) {
  28. System.out.print(numbers[x] + "  ");
  29. }
  30. }
  31. public static void main(String[] args) {
  32. int[] numbers = new int[] { 4, 3, 6, 2, 7, 1, 5, 8 };
  33. System.out.print("排序前: ");
  34. for(int x = 0; x < numbers.length; x++) {
  35. System.out.print(numbers[x] + "  ");
  36. }
  37. System.out.println();
  38. ShellSort ss = new ShellSort(numbers);
  39. ss.sort();
  40. }
  41. }

运行:

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

希尔排序的时间复杂度,最坏是O(n^2),平均O(n^3/2)。

Java与算法之(10) - 希尔排序的更多相关文章

  1. python算法介绍:希尔排序

    python作为一种新的语言,在很多功能自然要比Java要好一些,也容易让人接受,而且不管您是成年人还是少儿都可以学习这个语言,今天就为大家来分享一个python算法教程之希尔排序,现在我们就来看看吧 ...

  2. python算法与数据结构-希尔排序算法(35)

    一.希尔排序的介绍 希尔排序(Shell Sort)是插入排序的一种.也称缩小增量排序,是直接插入排序算法的一种更高效的改进版本.希尔排序是非稳定排序算法. 希尔排序是把记录按下标的一定增量分组,对每 ...

  3. 几种常见排序算法之Java实现(插入排序、希尔排序、冒泡排序、快速排序、选择排序、归并排序)

    排序(Sorting) 是计算机程序设计中的一种重要操作,它的功能是将一个数据元素(或记录)的任意序列,重新排列成一个关键字有序的序列. 稳定度(稳定性)一个排序算法是稳定的,就是当有两个相等记录的关 ...

  4. 9, java数据结构和算法: 直接插入排序, 希尔排序, 简单选择排序, 堆排序, 冒泡排序,快速排序, 归并排序, 基数排序的分析和代码实现

    内部排序: 就是使用内存空间来排序 外部排序: 就是数据量很大,需要借助外部存储(文件)来排序. 直接上代码: package com.lvcai; public class Sort { publi ...

  5. 排序算法入门之希尔排序(java实现)

    希尔排序是对插入排序的改进.插入排序是前面元素已经有序了,移动元素是一个一个一次往后移动,当插入的元素比前面排好序的所有元素都小时,则需要将前面所有元素都往后移动.希尔排序有了自己的增量,可以理解为插 ...

  6. Hark的数据结构与算法练习之希尔排序

    算法说明 希尔排序是插入排序的优化版. 插入排序的最坏时间复杂度是O(n2),但如果要排序的数组是一个几乎有序的数列,那么会降低有效的减低时间复杂度. 希尔排序的目的就是通过一个increment(增 ...

  7. 八大排序算法之二希尔排序(Shell Sort)

    希尔排序是1959 年由D.L.Shell 提出来的,相对直接排序有较大的改进.希尔排序又叫缩小增量排序 基本思想: 先将整个待排序的记录序列分割成为若干子序列分别进行直接插入排序,待整个序列中的记录 ...

  8. C#算法基础之希尔排序

    using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.T ...

  9. Java与算法之(11) - 合并排序

    天下事,合久必分,分久必合.合并排序的基本思想正是先分再合. 例如对3, 1这个数列排序,首先是分,分为3和1两个数列,然后再合并并排序.合并需要额外的辅助空间,即建立一个两个数列长度之和的空数组用于 ...

随机推荐

  1. oracle 主键自增 设置----杜恩德

    <div id="topicList"> <div class="forFlow"> <div class = "pos ...

  2. log4go的输出优化

    又看了一些golang的日志包和相关的文章,仔细阅读了go 1.9.2系统提供的log和go-log,产生了对log4go的日志输出进行优化的想法. 结构化与multiwriter log使用mult ...

  3. 【HTML】HTML基础知识

    <!DOCTYPE html>表示HTML5文档申明,不区别大小写,通常这么写. <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 ...

  4. 如何高效撤销Git管理的文件在各种状态下的更改

    一.背景 企业中我们一般采用分布式版本管理工具git来进行版本管理,在团队协作的过程中,我们难免会遇到误操作,需要撤销更改的情况,那么我们怎么高效的进行撤销修改呢?对于还未提交到暂存区的代码怎么高效撤 ...

  5. 基于POI和DOM4将Excel(2007)文档写进Xml文件

    刚进公司的training, 下面是要求: Requirements Write a java program to read system.xlsx Use POI API to parse all ...

  6. 安装两个JDK后配置环境变量没用?

    在实际开发中,由于项目的需要,可能JDK的版本是不同的.比如我们前一个项目所需JDK版本是1.6的,项目完成后,下一个项目JDK版本又是需要1.7的,为了防止由于切换项目我们需要频繁的安装卸载JDK, ...

  7. vim 当前用户显示行号

    在 -/.vimrc 中添加 set nu 如果文件不存在可以直接新建这个文件 -表示当前用户的主目录

  8. [ZJOI2015]地震后的幻想乡

    题目传送门 SOL:不会积分的我瑟瑟发抖. 所以我选择状压DP. 我们有以下一个dp状态: f[S][i],S表示点集,i表示这个点集向外联了i条边. 那么答案就是f[(1<<n)-1][ ...

  9. VS2010 Extension实践(3)——实现自定义配置

    在之前的两篇曾提到通过VSSDK(MSDN也叫VSX)来拓宽思路,实现一些MEF Extension所不能做到的功能,比如获取IVsUIShell服务来执行Command等等,这里我给各位看官展示如何 ...

  10. 关于微信小程序,一些想法

    不负众望,小程序终于在昨天1月9日正式上线,从凌晨微信公开课发布了微信<一月九日,一年之约>到现在,整整一天的时间,朋友圈.自媒体平台都在不断的发着关于小程序的各种文章,"APP ...