博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
排序算法总结之希尔排序
阅读量:6946 次
发布时间:2019-06-27

本文共 2747 字,大约阅读时间需要 9 分钟。

一,希尔排序算法介绍

①希尔排序又称缩小增量排序 ,它本质上是一个插入排序算法。为什么呢?

因为,对于插入排序而言,插入排序是将当前待排序的元素与前面所有的元素比较,而希尔排序是将当前元素与前面增量位置上的元素进行比较,然后,再将该元素插入到合适位置。当一趟希尔排序完成后,处于增量位置上的元素是有序的。

②希尔排序算法的效率依赖于增量的选取

假设增量序列为 h(1),h(2).....h(k),其中h(1)必须为1,且h(1)<h(2)<...h(k) 。

第一趟排序时在增量为h(k)的各个元素上进行比较;

第二趟排序在增量为h(k-1)的各个元素上进行比较;

..........

最后一趟在增量h(1)上进行比较。由此可以看出,每进行一趟排序,增量是一个不断减少的过程,因此称之为缩小增量。

当增量减少到h(1)=1时,这里完全就是插入排序了,而在此时,整个元素经过前面的 k-1 趟排序后,已经变得基本有序了,而我们知道,对于插入排序而言,当待排序的数组基本有序时,插入排序的效率是非常高的。因此,希尔排序就是利用“增量”技巧将插入排序的平均时间复杂度O(N^2)降低为亚二次方。

 

二,希尔排序实例分析

假设原始数组为: 81   94   11   96   12   35    增量序列为 h(1)=1  h(2)=3

这里一共有两个增量序列,故一共有两趟排序。第一趟按照增量3来排序

处于增量3上的元素集合如下:<81      96>,<94      12>,<11      35>排序之后变成:<81      96>,<12      94>,<11      35>

即,数组变成了:81   12   11   96   94   35

可以看出,在增量为3的各个位置上的元素都是有序的。

经过前面一趟排序,此时数组已经基本有序,再使用增量为1的排序时(插入排序),比较的次数将会大大地降低。

第二趟按增量为h(1)=1 来排序,排序后数组变成:

11   12   35   81   94   96

 

三,算法实现

1 public class ShellSort { 2      3     /** 4      * 使用希尔推荐的增量: h(k)=N/2 , h(i)=h(i+1)/2 5      * @param arr 待排序数组 6      */ 7     public static 
> void shellSort(T[] arr){ 8 9 int j;10 for(int gap = arr.length; gap >= 1; gap /=2)//排序的趟数11 {12 13 /*每对增量序列为:14 *
.....
15 */16 for(int i = gap; i < arr.length; i++)//在"增量位置上" 进行插入排序17 {18 T tmp = arr[i];19 for(j = i; j >= gap && tmp.compareTo(arr[j - gap]) < 0; j-= gap)20 arr[j] = arr[j - gap];21 arr[j] = tmp;22 }23 }24 }25 26 //for test purpose27 public static void main(String[] args) {28 Integer[] arr = {81,94,11,96,12,35,17,95,28,58,41,75,15};29 shellSort(arr);30 for (Integer integer : arr) {31 System.out.print(integer + " ");32 }33 }34 }

①第10行for循环表示,一共有多少个增量。增量的序列的个数,就是希尔排序的趟数。

上面的增量序列为: arr.length/2 , arr.length/2/2, arr.length/2/2/2    ....   2,  1

②里层的两个for循环(第16行至23行)实际上是一个插入排序

③第16行for循环表示:从数组的第 arr.length/2 下标起,对各组增量序列上的元素进行插入排序。gap等于arr.length/2时的排序分析如下:

对于第一趟排序而言(gap等于arr.length/2),一共有多少组呢?答案是一共有 arr.length - arr.length/2 + 1 组。

即:arr[arr.length/2]   arr[0] 这两个元素是一组

arr[arr.length/2 + 1]   arr[1] 这两个元素是一组

.....

arr[arr.length -1]   arr[arr.length-1-gap]这两个元素是一组,此时gap等于arr.length/2

④第19行for循环,就是插入排序中的将当前元素与前面的元素进行比较。这里的前面元素是相差 gap 个位置上的元素。

比如, arr[length/2]  与 arr[length/2-gap]进行比较。

 

四:参考资料

 

至此,五大基于内存的排序算法:插入排序、希尔排序;归并排序、快速排序;堆排序 全部已经实现了一遍。

插入排序和希尔排序是一类,本质上希尔排序就是插入排序。插入排序它的增量就是1,而希尔排序则按多个增量进行排序,增量逐渐减少至1

归并排序和快速排序很像。之所以像,是因为它们都基于分治、递归。归并排序每次将原数组递归分成两个大小相等的子数组,而快速排序则是基于pivot元素将原数组分成两个子数组。归并排序不断地分解原数组,直到划分的两个子数组中只存在一个元素时,这时,这两个子数组可以视为都是有序的。从而,再合并两个有序的子数组,来实现排序。

堆排序,借助了二叉堆,逻辑上是一棵完全二叉树,物理存储结构是一个一维数组。通过不断地删除堆顶元素,来实现排序。

 

 

转载地址:http://tcenl.baihongyu.com/

你可能感兴趣的文章
CentOS6.5最小化安装,自定义安装包
查看>>
hello world!
查看>>
从ASM迁移到ARM(1):平台支持的迁移服务
查看>>
扩展jQuery easyui datagrid增加动态改变列编辑的类型
查看>>
通过Linux shell实现的花生壳动态域名解析(DDNS)
查看>>
Mysql 生成按月份统计SQL语句,为null设置为0
查看>>
驰骋工作流程引擎回答湖南朋友的21个问题
查看>>
使用htmlPurifier 过滤输入能不能不要把&转义成&
查看>>
6、OC —— 内存管理基本概念
查看>>
在多台linux主机上执行相同的命令
查看>>
1.6的锁优化(适应性自旋/锁粗化/锁削除/轻量级锁/偏向锁)
查看>>
vsm安装(6)
查看>>
webapi使用System.Web.Http.Cors配置跨域访问的几点注意事项
查看>>
使用 JIRA API 更新用户头像
查看>>
IE浏览器“增强保护模式”的笔记
查看>>
SEP防火墙规则处理顺序
查看>>
linux AMP默认安装位置
查看>>
oracle表空间的创建、删除、查看、表空间不存在、及修改默认表空间详解
查看>>
Docker-compose install
查看>>
函数的使用
查看>>