排序算法 —— 希尔排序

目录

1.希尔排序的由来

2.希尔排序的思想

3.希尔排序的实现

实现分析

实现代码

代码优化

4.希尔排序的总结


1.希尔排序的由来

希尔排序是对直接插入排序的优化。在直接插入排序算法中,如果数据是有序or接近有序的时候,直接插入排序算法的时间复杂度是O(N),因为每次选取的待排序元素不需要经过太多次的比较,就能插入到有序序列中。

所以希尔排序的发明者就想,如果能把待排序序列快速的变得接近有序,那么直接插入排序不就能得到优化了吗? 

2.希尔排序的思想

希尔排序的思想就是先对序列中的元素进行间距分组,先把分出来的这些组进行插入排序,然后缩小间距,再进行分组,在进行插入排序,当间距缩小为1的时候,此时就是直接插入排序。所以,希尔排序又叫缩小增量排序。

希尔排序分为两步:预排序直接插入排序。在间距大于1的时候所进行的排序叫做预排序,当间距等于1的时候进行的排序就是直接插入排序。

预排序的意义:

大的数据越快的跳到后面去,小的数据越快的跳到前面去。

间距越大,数据跳的越快,数据越不接近有序。

间距越小,数据跳的越慢,数据越接近有序。 

 值得注意的是:当间距为几的时候,数据就被分成了几组。

3.希尔排序的实现

实现分析

想要实现希尔排序,我们先分析清楚如何实现一趟排序,就拿下面这个例子来说,我们先看红色的这一组。

红色的这一组之间的间距是3,我们类比直接插入排序,直接插入排序可以看做间距为1,所以我们只需要对直接插入排序稍微修改即可得出单趟排序的代码。

在上面右侧的代码中最外围的变量 i 控制的是一组中的元素下标,当这层循环走完之后,说明完成了一组数据的排序,但是我们需要完成的是分出的所有组的排序。在讨论希尔排序的思想的时候,我们发现,数据之间的间距是多少,数据就被分成了几组,所以,还需要在外面再加一层循环控制排序的数据是第几组的数据。

代码如下:

在前面我们也讨论过,希尔排序的间距是需要变化的,并且是变小的,而且,间距最后必须为1,所以,我们先将间距设置为待排序数据个数的一半,然后逐渐缩小一半。 所以还需要再加一层循环控制间距。

代码如下:

实现代码

#include <stdio.h>

void ShellSort(int* a, int n)
{
	int gap = n;

	while(gap > 1) // 控制间距 
	{
		gap /=2;
		for (int j = 0; j < gap; j++)  //控制排第几组的数据 
		{
			// 枚举一组中待排序的数据 
			for (int i = 0; i < n - gap; i += gap) 
			{
				int end = i;
				int tmp = a[end + gap];
				while (end >= 0)
				{
					if (tmp < a[end])
					{
						a[end + gap] = a[end];
						end -= gap;
					}
					else
					{
						break;
					}
				}
				a[end + gap] = tmp;
			}
		}
	}
}

int main()
{
	int nums[] = {5,1,2,4,6,3,8,9,7,0};
	ShellSort(nums,10);
	
	int i = 0;
	while(i < sizeof(nums)/sizeof(int))
	{
		printf("%d ",nums[i]);
		i++;
	}
	
	
	return 0;
}

代码优化

在上面的代码中,我们是将数据分成多组之后,然后一组排完之后再排另一组。其实,这多组数据是可以同时排的,也就是多组并排。

优化方案:1.去掉控制排第几组数据的循环。2.将枚举一组中待排序的数据修改为枚举所有组中待排序的数据。

代码示例如下:

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 (tmp < a[end])
				{
					a[end + gap] = a[end];
					end -= gap;
				}
				else
				{
					break;
				}
			}
			a[end + gap] = tmp;
		}
	}
}

4.希尔排序的总结

  •  希尔排序是对直接插入排序的优化。
  • 当gap > 1时都是预排序,目的是让数组更接近于有序。当gap == 1时,数组已经接近有序的了,这样就会很快。这样整体而言,可以达到优化的效果。
  • 希尔排序的时间复杂度不好计算,因为gap的取值方法很多,导致很难去计算,因此在好些树中给出的希尔排序的时间复杂度都不固定,我们一半去O(N^1.3)。
  • 希尔排序并没有开辟额外的空间,空间复杂度为O(1)。
  • 希尔排序是不稳定的,如下图:经过希尔排序之后,红色的5在蓝色的5后面了。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

跨时钟域处理(单bit)_2024年10月21日

慢时钟域同步到快时钟域&#xff1a;打两拍 在快时钟域clk下对慢时钟域信号进行打两拍&#xff08;亚稳态概率很低&#xff09; 脉冲宽度改变&#xff0c;但不影响同步结果 快时钟域同步到慢时钟域&#xff08;两种方法&#xff09; ① 脉冲展宽同步 在快时钟域clk下对快时…

LeetCode199. 二叉树的右视图(2024秋季每日一题 47)

给定一个二叉树的 根节点 root&#xff0c;想象自己站在它的右侧&#xff0c;按照从顶部到底部的顺序&#xff0c;返回从右侧所能看到的节点值。 示例 1: 输入: [1,2,3,null,5,null,4] 输出: [1,3,4] 示例 2: 输入: [1,null,3] 输出: [1,3] 示例 3: 输入: [] 输出: [] 提示:…

软件压力测试如何进行?深圳软件测试机构分享

软件压力测试是每个重要软件测试工作的一部分&#xff0c;是一种基本的软件质量保证行为。压力测试不是在常规条件下运行手动或自动测试&#xff0c;而是在计算机数量较少或系统资源匮乏的条件下运行测试。通常要进行软件压力测试的资源包括内部内存、CPU 可用性、磁盘空间和网…

Libevent源码剖析-event

1 简介 本文来重点介绍下libevent中的event事件&#xff0c;在类unix系统中编写网络程序时&#xff0c;我们经常需要处理3类事件-IO事件&signal事件&timer事件&#xff0c;libevent通过reactor来注册&调度&处理IO事件&#xff0c;并且也将signal和timer事件借助…

ESP32开发__ESP-IDF, ESP-ADF官网下载,安装及环境配置

前言 不说废话&#xff0c;直面“干货”。最近公司项目涉及基于 ESP32 系列芯片开发&#xff0c;那我们新手小白如何准备相关工作及快速入门&#xff0c;本篇文章旨在&#xff1a;介绍ESP32&#xff0c;指导用户搭建 ESP32 硬件开发的软件环境&#xff08; ESP-IDF V5.2.1 和 …

解码专业术语——应用系统开发项目中的专业词汇解读

文章目录 引言站点设置管理具体要求包括&#xff1a; Footer管理基于URL的权限控制利用数据连接池优化数据库操作什么是数据连接池&#xff1f;优化的优势 利用反射改造后端代码&#xff0c;AJAX反射的作用及其在后端代码中的应用AJAX 实现前后端无刷新交互 引言 创新实践项目二…

Bash 中的 ${} 和 $() 有什么区别 ?

Bash (Bourne-Again SHell) 是一种流行的 Unix SHell&#xff0c;用于编写脚本。如果您使用 Bash 脚本&#xff0c;那么了解不同的语法元素对于提高脚本的效率和避免错误是很重要的。 在本文中&#xff0c;我们将解释 Bash 中 ${} 和 $() 语法之间的区别&#xff0c;并向您展示…

「iOS」——AFNetworking的简单使用

iOS学习 前言原生网络请求使用AFNetworking库进行网络请求具体使用 单例创建的原因单例使用 总结 前言 我们之前学习了通过OC原生内容进行网络申请&#xff0c;AFNetworkikng第三方库的使用&#xff0c;可以极大地简化网络申请的代码量。 原生网络请求 网络请求主要分为上面五…

JAVA单列集合

List系列集合:添加的元素是 有序、可重复、有索引 Set系列集合:添加的元素是 无序、不重复、无索引 Collection Collection是单列集合的接口&#xff0c;它的功能是全部单列集合都可以继承使用的 public boolean add(E e) 把给定的对象添加到当前集合中 public void …

【大数据学习 | Zookeeper】Zookeeper的选举机制

zookeeper的选举机制分为第一次启动和非第一次启动两种情况。 1. 选举机制 - > 第一次启动 (1)服务器1启动&#xff0c;发起一次选举。服务器1投自己一票。此时服务器1票数一票&#xff0c;不够半数以上(3票)&#xff0c;选举无法完成&#xff0c;服务器1状态保持为 LOOKIN…

docker run 命令解析

docker run 命令解析 docker run 命令用于从给定的镜像启动一个新的容器。这个命令可以包含许多选项&#xff0c;下面是一些常用的选项&#xff1a; -d&#xff1a;后台运行容器&#xff0c;并返回容器ID&#xff1b;-i&#xff1a;以交互模式运行容器&#xff0c;通常与 -t …

中国信通院联合中国电促会开展电力行业企业开源典型实践案例征集

自2021年被首次写入国家“十四五”规划以来&#xff0c;开源技术发展凭借其平等、开放、协作、共享的优秀创作模式&#xff0c;正持续成为推动数字技术创新、优化软件生产模式、赋能传统行业转型升级、助力企业降本增效的重要引擎。电力是国民经济的重要基础性产业&#xff0c;…

Atlassian Team ‘24 Europe:推出Rovo、开发人员AI助手、新版Jira等多款AI创新,重塑团队协作

过去一周&#xff0c;Atlassian Team 24 Europe在巴塞罗那盛大举行&#xff01;展示了Atlassian在推动团队协作和业务发展方面的最新成果与前沿见解。 本文&#xff0c;Atlassian联合创始人兼首席执行官Mike Cannon-Brookes为我们分享了Atlassian在AI创新和系统化工作两项关键任…

2019年计算机网络408真题解析

第一题&#xff1a; 解析&#xff1a;OSI参考模型第5层完成的功能 首先&#xff0c;我们需要对OSI参考模型很熟悉&#xff1a;从下到上依次是&#xff1a;物理层-数据链路层-网络层- 运输层-会话层-表示层-应用层&#xff0c;由此可知&#xff0c;题目要问的是会话层的主要功能…

python 爬虫 入门 二、数据解析(正则、bs4、xpath)

目录 一、待匹配数据获取 二、正则 三、bs4 &#xff08;一&#xff09;、访问属性 &#xff08;二&#xff09;、获取标签的值 &#xff08;三&#xff09;、查询方法 四、xpath 后续&#xff1a;登录和代理 上一节我们已经知道了如何向服务器发送请求以获得数据&#x…

三周精通FastAPI:10 Cookie 参数 和Cookie 参数模型

官方文档&#xff1a;Cookie 参数 - FastAPI Cookie 参数 定义 Cookie 参数与定义 Query 和 Path 参数一样。 源码&#xff1a; from typing import Annotatedfrom fastapi import Cookie, FastAPIapp FastAPI()app.get("/items/") async def read_items(ads_id…

PHP泵的比例流量控制阀放大器

01 PHP 05 PCS005、01 PHP 1 PCS005、01 PHP 2 PCS005、01 PHP 3 PCS005&#xff0c;01 FCV 2 M、01 FCV 3 M、01 PHP 05 PCLS005、01 PHP 1 PCLS005、01 PHP 2 PCLS005、01 PHP 3 PCLS005&#xff0c;FCV比例流量控制阀旨在与Berarma的PHP2和PHP3泵最佳集成&#xff0c;但由于…

戴尔电脑win11找不到D盘的解决办法

新公司给配的戴尔电脑&#xff0c;系统是win11&#xff0c;第一天用的好好地&#xff0c;第二天不知道什么原因&#xff0c;D盘找不到了&#xff0c;在网上搜了好多教程也没用&#xff0c;最后咨询客服&#xff0c;找到了解决办法 若【磁盘管理】界面看不到硬盘分区或无法进入…

比亚迪车机安装第三方应用教程

比亚迪车机安装第三方应用教程 比亚迪车机U盘安装APP&#xff0c; 无论是dlink3.0还是4.0都是安卓系统&#xff0c;因此理论上安卓应用是都可以安装的&#xff0c;主要就是横屏和竖屏的区别。在比亚迪上安装软件我主要推荐两种方法。 第一种&#xff0c;直接从电脑端下载安装布…

《计算机视觉》—— 基于dlib库的人检检测

文章目录 一、dlib库的安装1. 通过PyCharm的Settings安装2. 通过Anaconda安装&#xff08;适用于Windows等操作系统&#xff09;3. 通过命令行安装4.懒人安装 二、基于dlib库的人检测1.对图像进行人脸检测2.打开电脑摄像头&#xff0c;检测人脸 一、dlib库的安装 在PyCharm中&…