【白话排序算法】希尔/谢尔排序法

news/2024/5/19 5:47:30 标签: 算法, 排序算法, 数据结构, 堆排序, 快速排序

谢尔排序法(Shell’s Sort)又称缩小增量排序法。他在1959年由谢尔(D.L.Shell)提出的。当时主流的排序算法时间复杂度都是 O ( n 2 ) O(n^2) O(n2)。谢尔排序是有望突破这个复杂度的一批算法之一。题外话,对比现在如此多O(nlogn)时间复杂度的排序算法,可见当时人们对排序算法的认知匮乏。你如果能穿越回60年前,绝对是一个了不起的人…

谢尔排序理解起来还是有些困难的。不过我可以试图解释下面这样一个思想,你应该能感觉到谢尔排序是可以降低时间复杂度的。

以下内容需要您对冒泡排序有一定的理解,可以看看我之前写的关于冒泡排序的文章。

在冒泡排序中,核心是相邻两个元素交替位置,在这个过程中,其实大量的没有必要的交换,即交换之后会再被交换。
在这里插入图片描述
观察一下9这个数,为了让他能够到正确的位置,所有其他元素都不得不进行位置的交替。而这些其他元素的位置交替仅仅是为了让9能够冒泡上去。

那么有没有可能在交替的过程中,让其他元素哪怕至少能够离其最终的位置近一些。因为我们知道,冒泡排序有一个特点:

若待排序的序列是倒序的,那么冒泡排序时间复杂度是 O ( n 2 ) O(n^2) O(n2),若待排序的序列本身就是有序的,时间复杂度仅仅为O(n)。即,若待排序的序列基本有序,时间复杂度将会大幅降低

谢尔排序正是利用了这样一个特点,当位置交替的时候,尽可能让交替变的有意义,即那些大的元素尽量往后排,而小的元素尽量往前排,让一趟交替后,让序列尽可能的有序一些,来达到最终降低时间复杂度的目的。

这样一个思想是可行的,你能明白么?下面来说一下如何实现。

为了能够让大的元素往后排,小的元素往前排,谢尔排序会以子序列的方式跳跃的交替元素的位置,这里也就是冒泡排序,进而让序列尽可能有序。
在这里插入图片描述
观察下上图,可以把相当颜色的元素集合看成一个子序列,并对子序列进行冒泡排序(或其他的排序方式),而一趟结束的结果是不是已经实现了某种程序上接近有序了?谢尔排序之后通过不断缩小间隔元素的大小,当间隔为1去进行排序的时候,已经相当于完整的冒泡排序,但此时序列已经基本有序。从而实现了尽可能的降低时间复杂度的目的,很巧妙吧。下面我来用JavaScript语言来实现下:

function ShellSort(seq) {
	let i, j, flag, temp, gap = seq.length;
	while(gap > 1) {
		gap = Math.floor(gap / 2);
		do {
			flag = 0;
			for (i=0;i<=seq.length-gap;i++) {
				j = i + gap;
				if (seq[i] > seq[j]) {
					temp = seq[i];
					seq[i] = seq[j];
					seq[j] = temp;
					flag = 1;
				}
			}
		} while (flag != 0)
	}
}
ShellSort(seq)
console.log(seq) // [1, 2, 3, 4, 5, 6, 6, 7, 9 ]

关于算法中的gap取值,实际上并没有确定的规则,每次取序列长度的一半似乎是一种比较常用的方法。

谢尔排序需要去仔细的思考其思想。相对于插入,选择,冒泡,包含后边说的快排,都难理解一些。希望读者能静下心来,慢慢想想,就不难理解了。

我来总结一下我个人的思考:谢尔排序就是通过排序子序列的方式,让原有的序列不断的接近有序,再利用基本有序的序列排序时间复杂度低的特性,来最终通过一次完整的排序保证结果有序。

另外值得注意的是,谢尔排序的时间复杂度是介于 O ( n 2 ) O(n^2) O(n2)与O(nlogn)的。

谢尔排序的由于也涉及到了跨元素间的交换,所以是一种不稳定的排序方式。


http://www.niftyadmin.cn/n/1383039.html

相关文章

功能测试报告的编写(版本测试报告与总结测试报告的应用)

测试报告是 测试人员在测试过程中用于反映测试状况的文档&#xff0c;其重要性通过网上哀求、跪求、旋转360度冰天雪地各种求测试报告模块的帖子中就可见一斑。其实测试报告的 内容基本都是模板的那些&#xff0c;只是在实际测试过程中&#xff0c;如何去整理内容结构&#xff…

《React Native 精解与实战》书籍连载「React Native 网络请求与列表绑定」

此文是我的出版书籍《React Native 精解与实战》连载分享&#xff0c;此书由机械工业出版社出版&#xff0c;书中详解了 React Native 框架底层原理、React Native 组件布局、组件与 API 的介绍与代码实战&#xff0c;以及 React Native 与 iOS、Android 平台的混合开发底层原理…

瑞士HUBER+SUHNER收购光交换机供应商Polatis

光纤连接领域的领先供应商&#xff0c;瑞士HuberSuhner日前宣布&#xff0c;公司已经在2016年5月30日同意收购光交换机供应商Polatis。 此次交易预计在6月完成&#xff0c;但是具体交易条款尚未透露。 总部位于贝德福德和剑桥的私有企业Polatis拥有员工110名。自成立以来&#…

使用VSCode打断点debug javascript / typescript

我们经常在浏览器的devtools中使用debug工具去调试代码&#xff0c;那么如果我运行的是Nodejs&#xff0c;也就是运行环境是nodejs, 那么应该如何debug打断点呢&#xff1f; 其实VSCode已经内部集成了调试工具&#xff0c;专门针对nodejs运行环境的&#xff0c;如果你需要debu…

eclipse 调试jdk源码class文件,变量无法显示问题

2019独角兽企业重金招聘Python工程师标准>>> 调试jdk源码时&#xff0c;变量无法显示提示说“key cannot be resolved to a variable”&#xff0c;为什么呢&#xff1f;因为在JDK中,sun对rt.jar中的类编译时,去除了调试信息。 解决方法如下 注意&#xff1a;如果你…

从一个简单的代理服务器开始(1)

2019独角兽企业重金招聘Python工程师标准>>> 代理里边用的一些基本模块不一一介绍了。 我们先从代理服务器谈起吧。 很多公司都严格控制上网。所有的网页浏览都要从一个指定的代理服务器入口。 什么是代理服务器&#xff1f;当你使用代理服务器时&#xff0c;发生了…

C#使用黑体字

lbl.Font new System.Drawing.Font(new FontFamily("黑体"), 12.0F, FontStyle.Bold);转载于:https://www.cnblogs.com/swtool/p/5334245.html

一个简单例子例子说明Mysql的七种join连接

先放一张文氏图震贴 现有数据如下 mysql> select * from user; -------------- | id | name | -------------- | 1 | zhangsan | | 2 | lisi | | 4 | zhaoliu | --------------mysql> select * from user_info; ---------- | id | age | ---------- | 1 …