python编程实现希尔排序


Posted in Python onApril 13, 2017

观察一下”插入排序“:其实不难发现她有个缺点:

如果当数据是”5, 4, 3, 2, 1“的时候,此时我们将“无序块”中的记录插入到“有序块”时,估计俺们要崩盘,每次插入都要移动位置,此时插入排序的效率可想而知。  

shell根据这个弱点进行了算法改进,融入了一种叫做“缩小增量排序法”的思想,其实也蛮简单的,不过有点注意的就是:

增量不是乱取,而是有规律可循的。

python编程实现希尔排序

希尔排序时效分析很难,关键码的比较次数与记录移动次数依赖于增量因子序列d的选取,特定情况下可以准确估算出关键码的比较次数和记录的移动次数。目前还没有人给出选取最好的增量因子序列的方法。增量因子序列可以有各种取法,有取奇数的,也有取质数的,但需要注意:增量因子中除1 外没有公因子,且最后一个增量因子必须为1。希尔排序方法是一个不稳定的排序方法。

首先要明确一下增量的取法(这里图片是copy别人博客的,增量是奇数,我下面的编程用的是偶数):

      第一次增量的取法为: d=count/2;

      第二次增量的取法为:  d=(count/2)/2;

      最后一直到: d=1; 

好,注意看图了,第一趟的增量d1=5, 将10个待排记录分为5个子序列,分别进行直接插入排序,结果为(13, 27, 49, 55, 04, 49, 38, 65, 97, 76)

第二趟的增量d2=3, 将10个待排记录分为3个子序列,分别进行直接插入排序,结果为(13, 04, 49, 38, 27, 49, 55, 65, 97, 76)

第三趟的增量d3=1, 对整个序列进行直接插入排序,最后结果为(04, 13, 27, 38, 49, 49, 55, 65, 76, 97)

重点来了。当增量减小到1时,此时序列已基本有序,希尔排序的最后一趟就是接近最好情况的直接插入排序。可将前面各趟的"宏观"调整看成是最后一趟的预处理,比只做一次直接插入排序效率更高。

本人是学python的,今天用python实现了希尔排序。

def ShellInsetSort(array, len_array, dk): # 直接插入排序
 for i in range(dk, len_array): # 从下标为dk的数进行插入排序
 position = i
 current_val = array[position] # 要插入的数

 index = i
 j = int(index / dk) # index与dk的商
 index = index - j * dk

 # while True: # 找到第一个的下标,在增量为dk中,第一个的下标index必然 0<=index<dk
 # index = index - dk
 # if 0<=index and index <dk:
 # break


 # position>index,要插入的数的下标必须得大于第一个下标
 while position > index and current_val < array[position-dk]:
 array[position] = array[position-dk] # 往后移动
 position = position-dk
 else:
 array[position] = current_val



def ShellSort(array, len_array): # 希尔排序
 dk = int(len_array/2) # 增量
 while(dk >= 1):
 ShellInsetSort(array, len_array, dk)
 print(">>:",array)
 dk = int(dk/2)

if __name__ == "__main__":
 array = [49, 38, 65, 97, 76, 13, 27, 49, 55, 4]
 print(">:", array)
 ShellSort(array, len(array))

输出:

>: [49, 38, 65, 97, 76, 13, 27, 49, 55, 4]
>>: [13, 27, 49, 55, 4, 49, 38, 65, 97, 76]
>>: [4, 27, 13, 49, 38, 55, 49, 65, 97, 76]
>>: [4, 13, 27, 38, 49, 49, 55, 65, 76, 97]

首先你得先会插入排序,不会你必然看不懂。 

python编程实现希尔排序

插入排序,即是对上图三个黄色框中的数进行插入排序。举个例子:13,55,38,76

直接看55,55<13, 不用移动。接着看38,38<55,那么55后移,数据变为[13,55,55,76],接着比较13<38, 那么38替换55,变成[13,38,55,76]。其它同理,略。

这里有个问题,比如第二个黄色框[27,4,65],4<27, 那27往后移,接着4就替换第一个,数据变成[4,27,65],但是计算机怎么知道4就是在第一个啊??

我的做法是,先找出[27,4,65]第一个数的下标,在这个例子中27的下标为1。当要插入的数的下标大于第一个下标1时,才可以往后移,前一个数不可以往后移有两种情况,一种是前面有数据,且小于要插入的数,那你只能插在它后面。另一种,很重要,当要插入数比前面所有数都小时,那插入数肯定是放在第一个,此时要插入数的下标=第一个数的下标。(这段话,感觉初学者应该不大懂……)

为了找到第一个数的下标,最开始想的是用循环,一直到最前面:

while True: # 找到第一个的下标,在增量为dk中,第一个的下标index必然 0<=index<dk
 index = index - dk
 if 0<=index and index <dk:
 break

在Debug时,发现用循环太浪费时间了,特别是当增量d=1时,直接插入排序为了插入列表最后一个数,得循环减1,直到第一个数的下标,后来我学聪明了,用下面的方法:

j = int(index / dk) # index与dk的商
index = index - j * dk

时间复杂度:

希尔排序的时间复杂度是所取增量序列的函数,尚难准确分析。有文献指出,当增量序列为d[k]=2^(t-k+1)时,希尔排序的时间复杂度为O(n^1.5), 其中t为排序趟数。

稳定性: 不稳定

希尔排序效果: 

 python编程实现希尔排序

参考资料: 编程是我自己实现的。建议Debug看看运行过程

1.非系统的学习也是在浪费时间 2.做一个会欣赏美,懂艺术,会艺术的技术人

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Python 相关文章推荐
用python做一个搜索引擎(Pylucene)的实例代码
Jul 05 Python
使用TensorFlow实现SVM
Sep 06 Python
Python分支语句与循环语句应用实例分析
May 07 Python
pycharm运行scrapy过程图解
Nov 22 Python
Python实现动态给类和对象添加属性和方法操作示例
Feb 29 Python
keras 实现轻量级网络ShuffleNet教程
Jun 19 Python
Python txt文件常用读写操作代码实例
Aug 03 Python
python 发送邮件的四种方法汇总
Dec 02 Python
python 办公自动化——基于pyqt5和openpyxl统计符合要求的名单
May 25 Python
python迷宫问题深度优先遍历实例
Jun 20 Python
pytorch中的torch.nn.Conv2d()函数图文详解
Feb 28 Python
Python内置类型集合set和frozenset的使用详解
Apr 26 Python
python实现解数独程序代码
Apr 12 #Python
python访问抓取网页常用命令总结
Apr 11 #Python
Python 登录网站详解及实例
Apr 11 #Python
python实现FTP服务器服务的方法
Apr 11 #Python
python读写json文件的简单实现
Apr 11 #Python
Python实现Mysql数据库连接池实例详解
Apr 11 #Python
详解Python中类的定义与使用
Apr 11 #Python
You might like
PHP5新特性: 更加面向对象化的PHP
2006/11/18 PHP
php中配置文件操作 如config.php文件的读取修改等操作
2012/07/07 PHP
PHP中spl_autoload_register函数的用法总结
2013/11/07 PHP
使用PHP备份MySQL和网站发送到邮箱实例代码
2013/11/28 PHP
PHP中的print_r 与 var_dump 输出数组
2016/06/13 PHP
Thinkphp3.2.3整合phpqrcode生成带logo的二维码
2016/07/21 PHP
PHP 文件上传后端处理实用技巧方法
2017/01/06 PHP
javascript中不等于的代码是什么怎么写
2013/12/29 Javascript
javascript里绝对用的上的字符分割函数总结
2014/07/31 Javascript
利用JavaScript的AngularJS库制作电子名片的方法
2015/06/18 Javascript
JavaScript实现级联菜单的方法
2015/06/29 Javascript
jquery+css实现的红色线条横向二级菜单效果
2015/08/22 Javascript
轻松学习jQuery插件EasyUI EasyUI实现拖动基本操作
2015/11/30 Javascript
ionic2自定义cordova插件开发以及使用(Android)
2017/06/19 Javascript
JS 仿支付宝input文本输入框放大组件的实例
2017/11/14 Javascript
npm 常用命令详解(小结)
2019/01/17 Javascript
Vue中图片Src使用变量的方法
2019/10/30 Javascript
在vue中实现禁止屏幕滚动,禁止屏幕滑动
2020/07/22 Javascript
toString.call()通用的判断数据类型方法示例
2020/08/28 Javascript
[07:39]第一届亚洲邀请赛回顾视频
2017/02/14 DOTA
[41:08]TNC vs VG 2018国际邀请赛小组赛BO2 第一场 8.16
2018/08/17 DOTA
[01:52]PWL S2开团时刻第四期——DOTA2成语故事
2020/12/03 DOTA
Python操作列表之List.insert()方法的使用
2015/05/20 Python
举例讲解Python面向对象编程中类的继承
2016/06/17 Python
Python 专题四 文件基础知识
2017/03/20 Python
Anaconda2 5.2.0安装使用图文教程
2018/09/19 Python
python实现网页自动签到功能
2019/01/21 Python
利用Python查看微信共同好友功能的实现代码
2019/04/24 Python
Django使用uwsgi部署时的配置以及django日志文件的处理方法
2019/08/30 Python
用python绘制樱花树
2020/10/09 Python
Jacadi Paris美国官方网站:法国童装品牌
2017/10/15 全球购物
接受捐赠答谢词
2014/01/27 职场文书
个人借款担保书
2014/04/02 职场文书
美术学专业求职信
2014/07/23 职场文书
教师党的群众路线教育实践活动学习心得体会
2014/10/30 职场文书
超越Nginx的Web服务器caddy优雅用法
2022/06/21 Servers