【数据结构】希尔排序

news2024/11/23 15:01:12

文章目录

  • 前言
  • 一、希尔排序的演示图例
  • 二、希尔排序:插入排序的优化版本
  • ☆三、核心算法思路
  • 四、算法思路步骤
    • (一)预排序 gap>1
    • (二)gap=1 插入排序 完成排序收尾
  • 五、码源详解
    • (1)ShellSort1 —— gap组 轮完一组再接下一组
    • (2)ShellSort2 —— 多组并排
  • 【关于gap幅度的选择】
  • 六、效率分析
    • (1)时间复杂度 O(N^ 1.3)(和O(N*logN)是一个量级的,可能O(N^ 1.3)会略差于O(N*logN))
    • 稳定性:不稳定



前言

前面我们学习了直接插入排序,我们可知道一个特点:当插排接近有序时,会非常的高效 。因此希尔研究出的希尔排序,令插排前面的数据更接近有序,就更高效。效率远超预期。


一、希尔排序的演示图例

在这里插入图片描述


二、希尔排序:插入排序的优化版本

希尔排序(Shell Sort)是一种排序算法,由美国计算机科学家Donald Shell于1959年提出。希尔排序是插入排序的一种改进版本Shell从插入排序中感悟到了插入排序只要保持 要调整待插入的数据的前面的数据越有序,排序的效率就越高旨在减少插入排序的交换操作和比较次数,从而提高排序效率。这个算法的名字是以发明者的名字命名的,虽然它也被称为 “递减增量排序”


☆三、核心算法思路

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

  • 基本思路:
    先选定一个整数 gap(间距),把待排序文件中所有记录分成gap个组所有距离为gap的记录分在同一组内,并对每一组内的记录进行排序。然后,取gap=gap/2 或 gap=gap/3+1 ( 增量逐渐递减 ),重复上述分组和排序的工作。当gap到达=1时,所有记录在统一组内排好序(=插入排序)。

旨在通过 将间距为gap的数据之间的插入排序
将大的数据通过 间距gap的插入排序 更快的甩到后面去,小的数据甩到前面来
使待排序的序列在gap增量递减到1之前 [也就是在真正的插入排序之前] ,使数据更接近有序,让最后一次gap==1时的插入排序实现高效排序


四、算法思路步骤

(一)预排序 gap>1

  1. 分组排,间距为 gap 的数据都分为一组共有 gap 组(gap的间隔中,就是分好的组数)
  2. 间距为 gap 的数据都分为一组,每组数据进行单趟间距为gap的插入排序。(和插入排序的思路一样,但能让大的数据通过间距gap更快的甩到后面去,小的数据更快的到前面来)
  3. 增量递减 gap=gap/2 或 gap=gap/3+1(一般取这个) [ gap随n变化 ],进行多次预排序【gap递减的幅度也是有讲究的,请看下文 】
  4. gap越大,跳的越快,越不接近有序;gap越小越慢,越接近有序一点

多次预排的意义:让大的数据更快的到后面去,让小的数更快的到前面来。

(二)gap=1 插入排序 完成排序收尾

gap==1 时,就是插入排序。完成全部数据的排序。这时的数据已经非常接近有序了,这时的插入排序将会非常高效!


五、码源详解

(1)ShellSort1 —— gap组 轮完一组再接下一组

运用两层循环:

  1. 外层循环控制轮到的组号
  2. 内层循环控制一组内间隔为gap之间数据的比较
//希尔排序 —— 一组一组轮
void ShellSort(DataType* a, int n) {
	int gap = n;
	while (gap > 1) {
		//gap = gap / 2;
		gap = gap / 3 + 1;  //+1确保除到最后gap=1  //gap根据n的大小进行变化  //gap也能取n/2(最终除出来一定为1)

		//将 数组中 间隔为gap的数分为一组,共分为gap组,(间隔的数据中间的个数,便是所有已经分好的组数)
		//一组一组遍历
		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 (tmp < a[end]) {              //比tmp大就往后移
						a[end + gap] = a[end];
						end -= gap;                //再继续向前比较
					}
					else {
						break;
					}

					a[end + gap] = tmp;
				}
			}
		}
	}
}

注意:边界问题建议大家套值进去试,不容易出错。

(2)ShellSort2 —— 多组并排

一组排完第一个gap,就跳到另一组排另一组的第一个gap(每组都一部分一部分地排)

//希尔排序 —— 多组并排
void ShellSort(DataType* a, int n) {
	int gap = n;
	while (gap > 1) {
		
		//gap = gap / 2;      //gap也能取n/2(最终除出来一定为1)
		gap = gap / 3 + 1;    //+1确保除到最后gap=1  //gap根据n的大小进行变化  

		for (int i = 0; i < n - gap; i++) {
			int end = i;
			int tmp = a[end + gap];
			while (end >= 0) {
				if (tmp < a[end]) {
					a[end + gap] = a[end];
					end -= gap;      //希尔排序的本质还是插入排序(end从前往后,每个end都向前遍历一次,遍历与其间隔gap的数),只不过是先通过gap分组来排出个相对有序,然后实现更高效的插入排序
				}
				else {
					break;
				}
				a[end + gap] = tmp;   //若发生了值的交换, end-=gap后 再加上gap 就是现在end的位置,就是将小的tmp值换到现在end的位置
									  //若当前没有发生值的交换,则让tmp储存下一个相距gap的值 a[end+gap],让下一个值再进行 向前比较遍历
			}
		}
	}
}


【关于gap幅度的选择】

在这里插入图片描述《数据结构-用面相对象方法与C++描述》— 殷人昆

gap越大,跳的越快,越不接近有序,gap越大能让大和小数据更快地到两边。
gap越小越慢,越接近有序一点。

相比之下,gap=gap / 3 + 1 是比较适合的大小

int gap = n;
	while (gap > 1) {
		//gap = gap / 2;
		gap = gap / 3 + 1;  //+1确保除到最后gap=1  //gap根据n的大小进行变化  //gap也能取n/2(最终除出来一定为1)


六、效率分析

(1)时间复杂度 O(N^ 1.3)(和O(NlogN)是一个量级的,可能O(N^ 1.3)会略差于O(NlogN))

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

《数据结构(C语言版)》— 严蔚敏
在这里插入图片描述

《数据结构-用面相对象方法与C++描述》— 殷人昆
在这里插入图片描述
因为咋们的gap是按照Knuth提出的方式取值的,而且Knuth进行了大量的试验统计,我们暂时就按照O(n^1.25)到 O(1.6* n^1.25) 来算。

结论:O(N^ 1.3)
以 gap=N / 3 为例,有N/3组数据,每组里有3个数据进行比较,每组比3次 => 一个gap 比较(N/3 * 3 = N)次,但其中并不是都要交换 => N^2 => N^1.3 (N*logN).

稳定性:不稳定

呈如图这样的趋势:先增大,中间性能增大,再回复到小。

是个数学问题 " 复变函数 "
图中的变化参数 大概为 log2 N(底数为2)
在这里插入图片描述



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

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

相关文章

OceanBase:01-单机部署(开发环境)

目录 一、体系架构 二、配置要求 三、解压安装包 四、执行安装 五、配置环境变量 六、快速部署 七、访问数据库 OceanBase 数据库&#xff08;OceanBase Database&#xff09;是一款蚂蚁集团完全自研的企业级原生分布式数据库&#xff0c;在普通硬件上实现金融级高可用&…

msvcp140.dll重新安装的解决方法,快速修复dll丢失问题

在计算机使用过程中&#xff0c;我们经常会遇到一些错误提示&#xff0c;其中之一就是“msvcp140.dll丢失”。这个错误通常会导致某些应用程序无法正常运行&#xff0c;给用户带来很大的困扰。那么&#xff0c;如何解决msvcp140.dll丢失的问题呢&#xff1f;本文将详细介绍解决…

基于transformer的解码decode目标检测框架(修改DETR源码)

提示:transformer结构的目标检测解码器,包含loss计算,附有源码 文章目录 前言一、main函数代码解读1、整体结构认识2、main函数代码解读3、源码链接二、decode模块代码解读1、decoded的TransformerDec模块代码解读2、decoded的TransformerDecoder模块代码解读3、decoded的De…

软件测试面试最经典的5个问题

软件测试面试灵魂五问&#xff01; 请做一下自我介绍&#xff1f;你为什么从上家公司离职&#xff1f;为什么转行做测试? 你对测试行业的认识&#xff1f;你的期望薪资是多少&#xff1f;最后&#xff0c;你要问我什么&#xff1f; 一、请做一下自我介绍 简历上有的可以一两…

VLAN与配置

VLAN与配置 什么是VLAN 以最简单的形式为例。如下图&#xff0c;此时有4台主机处于同一局域网中&#xff0c;很明显这4台主机是能够直接通讯。但此时我需要让处于同一局域网中的PC3和PC4能通讯&#xff0c;PC5和PC6能通讯&#xff0c;并且PC3和PC4不能与PC5和PC6通讯。 为了实…

【工具】【IDE】Qt Creator社区版

Qt Creator社区版下载地址&#xff1a;https://download.qt.io/archive/qt/ 参考&#xff1a;https://cloud.tencent.com/developer/article/2084698?areaSource102001.8&traceIduMchNghqp8gWPdFHvSOGg MAC安装并配置Qt&#xff08;超级简单版&#xff09; 1.安装brew&…

单链表的详解实现

单链表 结构 单链表结构中有两个数据&#xff0c;一个是存储数据的&#xff0c;还有一个指针指向下一个节点。 该图就是一个简单单链表的结构图。 接口实现 SLNode* CreateNode(SLNDataType x);//申请节点 void SLTprint(SLNode* head);//打印链表 void SLTPushBack(SLNode*…

【Echarts】玫瑰饼图数据交互

在学习echarts玫瑰饼图的过程中&#xff0c;了解到三种数据交互的方法&#xff0c;如果对您也有帮助&#xff0c;不胜欣喜。 一、官网教程 https://echarts.apache.org/examples/zh/editor.html?cpie-roseType-simple &#xff08;该教程数据在代码中&#xff09; import *…

springboot-2.7.3+ES-7.10.0

跟着官网走&#xff0c;能干99。一年几次变&#xff0c;次次不一样。刚部署好ES-6.8&#xff0c;又买阿里云Es-7.10.0根本忙不完。 做为JDK1.8最后一个版本。今天就拿新技术部署一套。致辞&#xff1a;大家以后就用这套好了。别轻易触发springboot3.0了 学习无止境&#xff1…

【使用Python编写游戏辅助工具】第三篇:鼠标连击器的实现

前言 这里是【使用Python编写游戏辅助工具】的第三篇&#xff1a;鼠标连击器的实现。本文主要介绍使用Python来实现鼠标连击功能。 鼠标连击是指在很短的时间内多次点击鼠标按钮&#xff0c;通常是鼠标左键。当触发鼠标连击时&#xff0c;鼠标按钮会迅速按下和释放多次&#xf…

言情小说怎么推广?如何推广网络小说?

网络小说是一种文学形式&#xff0c;它的受众群体相当广泛&#xff0c;其实也面临着很强的竞争&#xff0c;因此&#xff0c;网络推广是小说宣传的一项重要工作&#xff0c;这里小马识途营销顾问就分享一下小说推广的渠道和方法。 1、软文推广 在推广小说的过程中&#xff0c;…

面试10000次依然会问的【synchronized】,你还不会?

引言 synchronized 关键字是实现线程同步的核心工具&#xff0c;它能够确保在任一时刻&#xff0c;只有一个线程能够访问被同步的方法或代码块。 这不仅保证了操作的原子性&#xff0c;即这些操作要么完全执行&#xff0c;要么完全不执行&#xff1b;同时也确保了操作的可见性…

高效操作,轻松打造企业百度百科,展现实力形象

百度百科已经成为企业提升形象的重要渠道&#xff0c;拥有自己的百科词条意味着企业在互联网上拥有更高的知名度和可信度。接下来&#xff0c;将为大家介绍企业百度百科的创建过程和一些技巧&#xff0c;帮助企业更好地在百度百科上展现自身实力。 首先&#xff0c;创建企业百度…

基于Tensorflow卷积神经网络玉米病害识别系统(UI界面)

欢迎大家点赞、收藏、关注、评论啦 &#xff0c;由于篇幅有限&#xff0c;只展示了部分核心代码。 文章目录 一项目简介 二、功能三、系统四. 总结 一项目简介 Tensorflow是一个流行的机器学习框架&#xff0c;可用于训练和部署各种人工智能模型。玉米病害识别系统基于Tensorf…

明明用的不是自己机器视觉软件,甚至是盗版,机器视觉公司为什么还要申请那么多专利?

我首先看下专利是什么&#xff1f; 专利分为发明、实用新型、外观设计三种类型。 发明是指对产品、方法或者其改进所提出的新的技术方案。 实用新型是指对产品的形状构造或者其结合所提出的适于实用的新的技术方案。一般对日用品、机械、电器等产品的简单改进比较适用于申请…

Mysql数据目录结构以及文件类型解析

目录 1. 数据目录 2. Data目录 3. 数据库目录 1&#xff09;db.opt 2&#xff09;.frm 3&#xff09;.MYD和.MYI 4&#xff09;.ibd 5&#xff09;.ibd和.ibdata 在 MySQL 中&#xff0c;物理文件存放在数据目录中。数据目录与安装目录不同&#xff0c;安装目录用来存储…

NLP之Bert介绍和简单示例

文章目录 1. Bert 介绍2. 代码示例 1. Bert 介绍 2. 代码示例

Express框架开发接口之轮播图API

1.获取所有轮播图、 // 处理轮播图 const handleDB require(../handleDB/index) // 获取所有轮播图 exports.allCarousel (req, res) > {(async function () {let results await handleDB(res, "book_carousel", "find", "查询数据出错&#xf…

Python 生成Android不同尺寸的图标

源代码 # -*- coding: utf-8 -*- import sys import os import shutil from PIL import Imagedef generateAndroidIcons():imageSource icon.pngicon Image.open(imageSource)sizes [(android/drawable,512),(android/drawable-hdpi,72),(android/drawable-ldpi,36),(andro…

C# 发送邮件

1.安装 NuGet 包 2.代码如下 SendMailUtil using MimeKit; using Srm.CMER.Application.Contracts.CmerInfo; namespace Srm.Mail { public class SendMailUtil { public async static Task<string> SendEmail(SendEmialDto sendEmialDto,List<strin…