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

2024-01-27 09:20

本文主要是介绍【白话排序算法】希尔/谢尔排序法,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

谢尔排序法(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.chinasem.cn/article/649793

相关文章

不懂推荐算法也能设计推荐系统

本文以商业化应用推荐为例,告诉我们不懂推荐算法的产品,也能从产品侧出发, 设计出一款不错的推荐系统。 相信很多新手产品,看到算法二字,多是懵圈的。 什么排序算法、最短路径等都是相对传统的算法(注:传统是指科班出身的产品都会接触过)。但对于推荐算法,多数产品对着网上搜到的资源,都会无从下手。特别当某些推荐算法 和 “AI”扯上关系后,更是加大了理解的难度。 但,不了解推荐算法,就无法做推荐系

康拓展开(hash算法中会用到)

康拓展开是一个全排列到一个自然数的双射(也就是某个全排列与某个自然数一一对应) 公式: X=a[n]*(n-1)!+a[n-1]*(n-2)!+...+a[i]*(i-1)!+...+a[1]*0! 其中,a[i]为整数,并且0<=a[i]<i,1<=i<=n。(a[i]在不同应用中的含义不同); 典型应用: 计算当前排列在所有由小到大全排列中的顺序,也就是说求当前排列是第

csu 1446 Problem J Modified LCS (扩展欧几里得算法的简单应用)

这是一道扩展欧几里得算法的简单应用题,这题是在湖南多校训练赛中队友ac的一道题,在比赛之后请教了队友,然后自己把它a掉 这也是自己独自做扩展欧几里得算法的题目 题意:把题意转变下就变成了:求d1*x - d2*y = f2 - f1的解,很明显用exgcd来解 下面介绍一下exgcd的一些知识点:求ax + by = c的解 一、首先求ax + by = gcd(a,b)的解 这个

综合安防管理平台LntonAIServer视频监控汇聚抖动检测算法优势

LntonAIServer视频质量诊断功能中的抖动检测是一个专门针对视频稳定性进行分析的功能。抖动通常是指视频帧之间的不必要运动,这种运动可能是由于摄像机的移动、传输中的错误或编解码问题导致的。抖动检测对于确保视频内容的平滑性和观看体验至关重要。 优势 1. 提高图像质量 - 清晰度提升:减少抖动,提高图像的清晰度和细节表现力,使得监控画面更加真实可信。 - 细节增强:在低光条件下,抖

【数据结构】——原来排序算法搞懂这些就行,轻松拿捏

前言:快速排序的实现最重要的是找基准值,下面让我们来了解如何实现找基准值 基准值的注释:在快排的过程中,每一次我们要取一个元素作为枢纽值,以这个数字来将序列划分为两部分。 在此我们采用三数取中法,也就是取左端、中间、右端三个数,然后进行排序,将中间数作为枢纽值。 快速排序实现主框架: //快速排序 void QuickSort(int* arr, int left, int rig

usaco 1.3 Mixing Milk (结构体排序 qsort) and hdu 2020(sort)

到了这题学会了结构体排序 于是回去修改了 1.2 milking cows 的算法~ 结构体排序核心: 1.结构体定义 struct Milk{int price;int milks;}milk[5000]; 2.自定义的比较函数,若返回值为正,qsort 函数判定a>b ;为负,a<b;为0,a==b; int milkcmp(const void *va,c

poj 3974 and hdu 3068 最长回文串的O(n)解法(Manacher算法)

求一段字符串中的最长回文串。 因为数据量比较大,用原来的O(n^2)会爆。 小白上的O(n^2)解法代码:TLE啦~ #include<stdio.h>#include<string.h>const int Maxn = 1000000;char s[Maxn];int main(){char e[] = {"END"};while(scanf("%s", s) != EO

秋招最新大模型算法面试,熬夜都要肝完它

💥大家在面试大模型LLM这个板块的时候,不知道面试完会不会复盘、总结,做笔记的习惯,这份大模型算法岗面试八股笔记也帮助不少人拿到过offer ✨对于面试大模型算法工程师会有一定的帮助,都附有完整答案,熬夜也要看完,祝大家一臂之力 这份《大模型算法工程师面试题》已经上传CSDN,还有完整版的大模型 AI 学习资料,朋友们如果需要可以微信扫描下方CSDN官方认证二维码免费领取【保证100%免费

hdu 1285(拓扑排序)

题意: 给各个队间的胜负关系,让排名次,名词相同按从小到大排。 解析: 拓扑排序是应用于有向无回路图(Direct Acyclic Graph,简称DAG)上的一种排序方式,对一个有向无回路图进行拓扑排序后,所有的顶点形成一个序列,对所有边(u,v),满足u 在v 的前面。该序列说明了顶点表示的事件或状态发生的整体顺序。比较经典的是在工程活动上,某些工程完成后,另一些工程才能继续,此时

dp算法练习题【8】

不同二叉搜索树 96. 不同的二叉搜索树 给你一个整数 n ,求恰由 n 个节点组成且节点值从 1 到 n 互不相同的 二叉搜索树 有多少种?返回满足题意的二叉搜索树的种数。 示例 1: 输入:n = 3输出:5 示例 2: 输入:n = 1输出:1 class Solution {public int numTrees(int n) {int[] dp = new int