希尔排序算法

目录

ShellSort希尔排序

整体思路

图解分析

【1】预排序

单组排序

多组并排

【2】直接插入排序

关于gap取值 

总代码实现

时间复杂度


ShellSort希尔排序

希尔排序法又称缩小增量法。

  • 希尔排序法的基本思想是:先选定一个整数,把待排序文件中所有记录分成个 组,所有距离为的记录分在同一组内,并对每一组内的记录进行排序。然后,取,重复上述分组和排序的工 作。当到达=1时,所有记录在统一组内排好序。 
  • 希尔排序=预排序+直接插入排序
  • 预排序:让大的数值更快的到达后面,小的数值更快的到达前面。(达到一个让数组元素接近顺序的效果)
  • gap是间距值❗
  • 直接插入排序相当于gap==1,希尔排序相当gap存在值了。

希尔排序的特性总结:

1. 希尔排序是对直接插入排序的优化。

2. 当gap > 1时都是预排序,目的是让数组更接近于有序。当gap == 1时,数组已经接近有序的了,这样就 会很快。这样整体而言,可以达到优化的效果。我们实现后可以进行性能测试的对比。

3. 稳定性:不稳定 

4. 希尔排序的时间复杂度不好计算,因为gap的取值方法很多,导致很难去计算,因此在好些树中给出的 希尔排序的时间复杂度都不固定:

《数据结构(C语言版)》--- 严蔚敏

《数据结构-用面相对象方法与C++描述》--- 殷人昆

整体思路

  • gap是数值之间的间距值❗
  • 直接插入排序相当于gap==1,希尔排序相当gap存在值了。
  • gap是几,就可以把整体分为几组。(除去gap = n的情况)(gap=gap/2或者gap=gap/3+1)
  • 分组和每组里面的元素个数的关系
  1. gap = n(gap随着n的变换而变化,gap的值不固定)
  2. gap/2(每次gap组,每组里面的元素个数:2,4,8......)*2 【n/2,n/4,n/8....】
  3. gap/3+1 (每次gap组,每组里面的元素个数:3,9,27...)*2【n/3,n/9,n/27....】
  4. 随着gap的变小,组数会变小,每组里面的数值个数会变大。

    gap的值

  • 一个数无论是奇数还是偶数/2 最后都等于1
  • gap的值不是固定的,可以是gap/2或者gap/3+1
  • gap值无论是/2 /3,最后都必须==1 ,最后要直接插入排序
  • gap>1时时预排序,目的是让整体数值更加接近有序
  • gap == 1的时候就是直接插入排序,目的是让整体值有序。
  • gap的值越大,大的值更快的调到后面,小的值可以更快的调到前面,越不接近有序。
  • gap的值越小,大的值更慢的调到后面,小的值可以慢的调到前面,越接近有序。
  • gap的值不是固定的,gap的值是随着整体n的大小变化而变化的。
  • 随着gap的变小,组数会变小,每组里面的数值个数会变大。
  • 预排序gap的上一个值排完之后会对下一个值得排序调整次数产生影响。

  • 整体思路

  • 一趟:类似直接插入排序的一趟,间距从1变为gap
  • 一组:加入循环,完成一组的排序(类似直接插入排序整体)
  • 多组:加入三层嵌套循环/多组并排。(完成多组排序)(gap是多少就有多少组)
  • 整体:完成整个数组的排序(多次预排序直到最后插入排序gap=1)(n个值)gap=n(gap=gap/2或者gap=gap/3+1)

图解分析

  • gap是数值之间的间距值❗
  • gap=n(n是整个的数值个数)
  • gap=gap/2
  • gap=10/2=5
  • gap=5/2=2
  • gap=2/2=1
  • 注意:无论gap用gap/2或者gap/3+1或者其他最后gap的值必须为1,因为最后要进行直接插入排序,完成整体的排序。 

【1】预排序

为了理解,这里我们先把gap理解为固定值gap == 3是一个固定值。 假设n=11

单组排序

  • 一组一组排序
  • 三个嵌套循环
  • 控制起始位置i=j(0/1/2)
  • i=0(0/3/6)
  • i=1(1/4/7)
  • i=2(2/5)
  • i=0/3/6/1/4/7/2/5
  • 控制数组元素下标,防止越界i<n-gap(i<11-3=8)

//升序
//写法1:三层嵌套循环
void ShellSort(int* a, int n)
{//多组int gap = 3;for (int j = 0; j < gap; j++){//每组for (int i = j; i < n - gap; i += gap){int end = i;int tmp = a[end + gap];//一趟while (end >= 0){if (a[end] > tmp){a[end + gap] = a[end];end -= gap;}else//<={break;}}a[end + gap] = tmp;}}
}

多组并排

  • 多组并排
  • 两个嵌套循环
  • 控制起始位置i=0/1/2
  • i=0/1/2/3/4/5/6/7
  • 控制数组元素下标,防止越界i<n-gap(i<11-3=8)

//写法2
//多组并排
void ShellSort(int* a, int n)
{//多组int gap = 3;for (int i = 0; i < n - gap; i++){int end = i;int tmp = a[end + gap];//一趟while (end >= 0){if (a[end] > tmp){a[end + gap] = a[end];end -= gap;}else//<={break;}}a[end + gap] = tmp;}
}

【2】直接插入排序

实际上如果整体的数量过大,gap为3是非常不合适的。所以,gap不可能为固定值,gap的取值是随着n变化的,所以gap有两种方式去取值。

关于gap取值 

  • gap=gap/2
  • gap=gap/3+1
  • 注意:无论gap用gap/2或者gap/3+1或者其他。最后gap的值必须为1,因为最后要进行直接插入排序,完成整体的排序。 
  • gap是几,就可以把整体分为几组。(除去gap = n的情况)(gap=gap/2或者gap=gap/3+1)
  • 分组和每组里面的元素个数的关系
  • gap = n(gap随着n的变换而变化,gap的值不固定)
  • gap/2(每次gap组,每组里面的元素个数:2,4,8......)*2 【n/2,n/4,n/8....】
  • gap/3+1 (每次gap组,每组里面的元素个数:3,9,27...)*2【n/3,n/9,n/27....】
  • 随着gap的变小,组数会变小,每组里面的数值个数会变大。
void ShellSort(int* a, int n)
{//整体int gap = n;while (gap > 1){//每组//gap = gap / 2;gap = gap / 3 + 1;//..........}}
}

总代码实现

void ShellSort(int* a, int n)
{//整体int gap = n;while (gap > 1){//每组//gap = gap / 2;gap = gap / 3 + 1;for (int i = 0; i < n - gap; i++){int end = i;int tmp = a[end + gap];//一趟while (end >= 0){if (a[end] > tmp){a[end + gap] = a[end];end -= gap;}else//<={break;}}a[end + gap] = tmp;}}
}

时间复杂度

  • 希尔排序的时间复杂度O(N^1.3)
  • O(N^1.3)比O(N*logN)略慢,效率略低一点。
  • 希尔排序VS直接插入排序(秒入过万VS分入过万)
  • 预排序gap的上一个值排完之后会对下一个值得排序调整次数产生影响。
  • O(N^1.3)需要套用数学模型,统计学来计算,这里只是近似计算。记住最后结论即可。

🙂感谢大家的阅读,若有错误和不足,欢迎指正。下篇选择排序&堆排序。大家新年快乐!! 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/689997.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

swap交换分区及buffers和cached

swap交换分区 swap 是 linux 系统磁盘管理的一块特殊的分区&#xff0c;当实际的物理内存不足的时候&#xff0c;操作系统会从整个内存中&#xff0c;取出一部分暂时没在使用的内存&#xff0c;拿出来放到交换分区&#xff0c;从而提供给当前正在使用的程序&#xff0c;可以使…

Vue3快速上手(七) ref和reactive对比

一、ref和reactive对比 表格形式更加直观吧&#xff1a; 项目refreactive是否支持基本类型支持不支持是否支持对象类型支持支持对象类型是否支持属性直接赋值不支持&#xff0c;需要.value支持是否支持直接重新分配对象支持&#xff0c;因为操作的.value不支持&#xff0c;需…

120 Linux C++ 通讯架构实战 nginx整体结构,nginx进程模型,nginx调整worker进程数量,nginx重载配置文件,热升级,关闭

一 nginx整体结构 1.1 master进程和worker进程概览&#xff08;父子关系&#xff09; 启动nginx&#xff0c;看到了master进程和 worker 进程。 ps -ef | grep nginx 第一列&#xff1a;进程所属的用户id 第二列&#xff1a;进程ID&#xff0c;也叫做PID&#xff0c;用来唯…

Unity中关于群组的一些组件

前言 在游戏开发环境中&#xff0c;UI组件是构建玩家交互界面的基础。以下是一些常见UI组件的详细解释和它们适用的场景&#xff0c;方便我们更好地理解和使用这些工具。 1. Graphic Raycaster Graphic Raycaster组件是游戏UI交互的核心。在Unity等游戏引擎中&#xff0c;当玩…

@arco.design Modal renderContent 增加样式

方式一&#xff1a;通过 h 函数 import { h } from vueMessage.error({content: () > {return h(div, {}, [手机号 , h(span, { style: { color: red } }, staffPhone), 已存在])}, })方式二&#xff1a;通过 jsx 方式 注意&#xff1a;lang 需要改为 jsx 或者 tsx <s…

JS面向对象:八.原型链的问题

<!DOCTYPE html> <html> <head lang"en"><meta charset"UTF-8"><title>原型链的问题</title> </head> <body> <script>function Humans(){this.clothing["trousers","dress",&…

OSQP文档学习

OSQP官方文档 1 QSQP简介 OSQP求解形式为的凸二次规划&#xff1a; x ∈ R n x∈R^n x∈Rn&#xff1a;优化变量 P ∈ S n P∈S^n_ P∈Sn​&#xff1a;半正定矩阵 特征 &#xff08;1&#xff09;高效&#xff1a;使用了一种自定义的基于ADMM的一阶方法&#xff0c;只需…

java当日时间段获取

需求&#xff1a;获取当天日期到当前访问的时间段&#xff0c;如当日是2024-02-19&#xff0c;那么此刻访问&#xff0c;日期期间就是2024-02-19 00:00:00到2024-02-19 16:58:00 代码如下&#xff1a; Date datenew Date();String currentDatedate2Str(date,"yyyy-MM-dd&q…

关于Sora的一些紧迫问题...

OpenAI Sora 概述 OpenAI最新的创新&#xff0c;Sora&#xff0c;在人工智能领域开辟了新的天地。Sora是一个文本到视频的扩散模型&#xff0c;可以将文本描述转化为逼真的视频内容。它解决了一个重大的技术挑战&#xff0c;即在视频中保持主体的一致性&#xff0c;即使它们暂…

Java 线程池的基本操作

Java 线程池的基本操作 package com.zhong.thread.threadpool;import java.util.concurrent.*;/*** ClassName : ThreadPool* Description : 线程池的基本操作* Author : zhx* Date: 2024-02-19 18:03*/ public class ThreadPool {public static void main(String[] args) {// …

C语言每日一题(59)左叶子之和

题目链接 力扣网404 左叶子之和 题目描述 给定二叉树的根节点 root &#xff0c;返回所有左叶子之和。 示例 1&#xff1a; 输入: root [3,9,20,null,null,15,7] 输出: 24 解释: 在这个二叉树中&#xff0c;有两个左叶子&#xff0c;分别是 9 和 15&#xff0c;所以返回 2…

基于SpringBoot的高校竞赛管理系统

基于SpringBoot的高校竞赛管理系统的设计与实现~ 开发语言&#xff1a;Java数据库&#xff1a;MySQL技术&#xff1a;SpringBootMyBatis工具&#xff1a;IDEA/Ecilpse、Navicat、Maven 系统展示 主页 个人中心 管理员界面 老师界面 摘要 高校竞赛管理系统是为了有效管理学校…

低代码开发与网络信息安全:构建高效防护体系

随着数字化转型的加速&#xff0c;越来越多的企业开始关注低代码开发平台&#xff0c;以提高软件开发效率&#xff0c;缩短上市时间。然而&#xff0c;随之而来的网络信息安全问题也日益严峻。如何在享受低代码开发带来的便捷与高效的同时&#xff0c;确保网络信息安全成为企业…

K8s进阶之路-命名空间级-服务发现 :

服务发现&#xff1a; Service&#xff08;东西流量&#xff09;&#xff1a;集群内网络通信、负载均衡&#xff08;四层负载&#xff09;内部跨节点&#xff0c;节点与节点之间的通信&#xff0c;以及pod与pod之间的通信&#xff0c;用Service暴露端口即可实现 Ingress&#…

Vscode python pyside6 制作视频播放器

一、界面如下 包含控件 qcombox、qtablewidget、qpushbotton、qverticalslider 二、运行代码 media_player.py import sysfrom PySide6 import QtWidgets from PySide6.QtWidgets import * from PySide6.QtMultimedia import * from PySide6.QtMultimediaWidgets import QVi…

林浩然与杨凌芸的Java List大冒险

林浩然与杨凌芸的Java List大冒险 Lin Haoran and Yang Lingyun’s Java List Adventure 在一个阳光明媚的日子&#xff0c;程序员界的“侠客”林浩然和他那聪明伶俐的同事兼好友杨凌芸正在Java王国里进行一场别开生面的大冒险。这次他们的目标是征服两个强大的List家族成员——…

c++面试

c基础 面试题 1&#xff1a;变量的声明和定义有什么区别 1.定义:为变量分配地址和存储空间&#xff0c;声明:不分配地址。 2.一个变量可以在多个地方声明&#xff0c;但是只在一个地方定义。 3.加入 extern 修饰的是变量的声明&#xff0c;说明此变量将在文件以外或在文件后…

备战蓝桥杯 Day4

目录 注意&#xff1a;递推开long long 1140&#xff1a;验证子串 1131&#xff1a;基因相关性 1176&#xff1a;谁考了第k名 1177&#xff1a;奇数单增序列 1180&#xff1a;分数线划定 1184&#xff1a;明明的随机数 1185&#xff1a;单词排序 1186&#xff1a;出现…

图论之dfs与bfs的练习

dfs--深度优选搜索 bfs--广度优先搜索 迷宫问题--dfs 问题&#xff1a; 给定一个n*m的二维迷宫数组其中S是起点&#xff0c;T是终点&#xff0c;*是墙壁&#xff08;无法通过&#xff09;&#xff0c; .是道路 问从起点S出发沿着上下左右四个方向走&#xff0c;能否走到T点&a…

视频监控需求八问:视频智能分析/视频汇聚平台EasyCVR有何特性?

最近TSINGSEE青犀视频在与业内伙伴进行项目合作的过程中&#xff0c;针对安防监控可视化视频管理系统EasyCVR视频融合平台在电信运营商项目中的应用&#xff0c;进行了多方面的项目需求沟通。今天我们就该项目沟通为案例&#xff0c;来具体了解一下用户关心度较高的关于视频智能…