PHP数据结构(二十一) ——希尔排序
PHP数据结构(二十一)——希尔排序
(原创内容,转载请注明来源,谢谢)
一、概述
希尔排序,又称缩小增量排序,也属于插入排序类方法,时间上有较大改进。前面叙述的插入排序方法的时间复杂度都是O(n2),当待排序记录都是正序时,时间复杂度提高到O(n)。
希尔排序的基本思想是:先将整个待排记录序列分割成为若干子序列分别进行直接插入排序,待整个序列中的记录基本有序时,再对全体进行一次插入排序。
二、算法
希尔排序实质上就是跳跃版的直接插入排序,其每次都设定一个不同的增量,如第一次增量是5、第二次增量是3,进行两轮插入排序后,最后再从头进行一次直接插入排序。
以第一次增量为5,第二次增量为3,数组长度为10举例,说明希尔排序算法。
1)把数组进行分组,因为增量是5,因此把下标048、159、26、37分别划分到各组,对每组依次进行直接插入排序,排序后每一组包含的数组下标还是原先的那几个数字(如048组进行插入排序,假设0对应的值大于4,则排序后下标变为408,不占用其他组的下标),排序后数组部分有序,此时称为完成一轮希尔排序。
2)以0369、147、258的下标值分组,分别对这三组值进行插入排序。此时称为完成第二轮希尔排序。
3)将前两轮排序后的数组,从头开始进行插入排序。
4)以此为拓展,可以输入一组增量数组,按照增量的值,依次进行分组的插入排序,最后再进行一次增量为1的插入排序。
三、实现源码
//希尔排序 输入的第一个参数为增量数组,不用输入最终的增量1
publicfunction shellInsertSort(array $arrIncr, array $arr = array()){
//如果增量数组长度小于1,直接调用直接插入排序即可
if(1> count($arrIncr)){
return$this->directInsertSort($arr);
}
$arr= $this->_checkNeedSort($arr);
if(!$arr){
return$arr;
}
//循环调用增量数组中的增量
foreach($arrIncras $incr){
//如果增量大于或等于数组长度,则直接取下一个增量
for($i=$incr;$i<count($arr);$i++){
$tmp= $arr[$i];
//以增量$incr的序列组成数组,同样假设前i-1个数有序,对第i个进插入排序
for($j=$i-$incr;$j>=0&&$tmp<$arr[$j];$j=$j-$incr){
$arr[$j+$incr]= $arr[$j];
}
$arr[$j+$incr]= $tmp;
}
}
//最后一组数组,调用直接插入排序,步长为1
$arr= $this->directInsertSort($arr);
return$arr;
}
四、评价
希尔排序的好坏,和选定的因子有非常大的关系,目前尚无定论哪种最好。但是经过大量的推导,当增量函数dlta[k]=2t-k+1-1时,时间复杂度为O(n3/2),其中t为排序的趟数,k的范围是1<=k<=t<=log2(n+1)(向下取整)。
增量函数的建议方法:
1)1,2,3,5,9…dlta[k]=2t-k+1 (0<=k<=t<= log2(n-1)(向下取整))
2)1,4,13,40…dlta[k]=(3t-k-1)/2 (0<=k<=t<= log2(2n+1)(向下取整))
增量函数要求:应使增量序列中的值没有除1以外的公因子,最终的增量值必须是1。
——written by linhxx 2017.07.18
相关阅读:
PHP数据结构(二十) ——其他插入排序
PHP数据结构(十九) ——B+树
PHP数据结构(十八) ——直接插入排序
PHP数据结构(十七) ——内部排序综述
PHP数据结构(十六) ——B树
PHP数据结构(十五) ——哈希表
PHP数据结构(十四) ——键树(双链树)
PHP数据结构(十三) ——动态查找表(二叉排序树)
PHP数据结构(十二) ——静态查找表
PHP数据结构(十一) ——图的连通性问题与最小生成树算法(2)
PHP数据结构(十一) ——图的连通性问题与最小生成树算法(1)
PHP数据结构(十) ——有向无环图与拓扑算法
PHP数据结构(九) ——图的定义、存储与两种方式遍历
PHP数据结构(八) ——赫夫曼树实现字符串编解码(实践2)
PHP数据结构(八) ——赫夫曼树实现字符串编解码(实践1)
PHP数据结构(八) ——赫夫曼树实现字符串编解码(理论)
PHP数据结构(七) ——串与实现KMP算法
PHP数据结构(六) ——树与二叉树之概念及存储结构
PHP数据结构(六) ——数组的相乘、广义表
PHP数据结构(五) ——数组的压缩与转置
PHP数据结构(四) ——队列
PHP数据结构(三)——运用栈实现括号匹配
PHP数据结构(二)——链式结构线性表
PHP数据结构(一)——顺序结构线性表
- Fluent NHibernate RC 1.0 --升级内容
- 驳“反驳老赵之“伪”递归”
- 关于今天很热的--FizzBuzzWhizz
- 了解EF CodeFirst的Migrator功能与Migrator.Net对比
- struts技术的logic标签
- 【翻译】使用Visual Studio创建Asp.Net Core MVC (一)
- 你不知道的Javascript:有趣的setTimeout
- ADO.NET 2.0 中的新增 DataSet 功能
- WinRar 4.20 – 文件扩展名欺骗(0Day)
- 黑掉ATM取款机?只需一条短信
- DNS迭代穷举脚本
- 走进计算机取证分析的神秘世界
- SYNPROXY:最廉价的抗DoS攻击方案
- 如何使用AndroidStudio将开源项目library发布到jcenter
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- Leetcode刷题 206. 反转链表 递归迭代两种方法实现
- airtest本地连接和远程连接
- Flutter基础widgets教程-TextField篇
- poco对象生成的几种方式根据你使用不同的ui决定
- java.lang.ClassNotFoundException: org.springframework.web.context.ContextLoaderL
- SpringMVC系列之SpringMVC快速入门 MVC设计模式介绍+什么是SpringMVC+ SpringMVC的作用及其基本使用+组件解析+注解解析
- [Go] GoAdminGroup/go-admin的安装和运行
- 算法篇:滑动窗口(一)
- PHP代码审计02之filter_var()函数缺陷
- Flutter基础widgets教程-Tooltip篇
- 08 . Jenkins之SpringCloud微服务+Vue+Docker持续集成
- Spark 模型选择和调参
- Spark Parquet详解
- Spark 频繁模式挖掘
- Flutter基础widgets教程-WidgetsApp篇