【算法基础】直接插入排序 + 希尔排序

news2024/11/25 2:30:10

在这里插入图片描述

👦个人主页:Weraphael
✍🏻作者简介:目前正在学习c++和算法
✈️专栏:【C/C++】算法
🐋 希望大家多多支持,咱一起进步!😁
如果文章有啥瑕疵
希望大佬指点一二
如果文章对你有帮助的话
欢迎 评论💬 点赞👍🏻 收藏 📂 加关注😍


目录

  • 一、直接插入排序
    • 1.1 基本思想
    • 1.2 算法思路
    • 1.3 代码实现
    • 1.4 特性总结
  • 二、希尔排序
    • 2.1 希尔排序的由来
    • 2.2 算法思路
    • 2.3 如何选择gap
    • 2.4 希尔排序效率问题
    • 2.5 代码实现
    • 2.6 希尔排序的特性总结

一、直接插入排序

1.1 基本思想

直接插入排序是一种简单的插入排序法,其基本思想是:把待排序的记录按其关键码值的大小逐个插入到一个已经排好序的有序序列中,直到所有的记录插入完为止,得到一个新的有序序列

实际中,玩扑克牌时,整理一副牌从小到大或者从大到小就用到了插入排序的思想

在这里插入图片描述

1.2 算法思路

在这里插入图片描述

首先数据内的第一个元素(下标为0)是不需要排序的。因此,当插入第i(i ≥ 1)个元素时,可以拿a[i]与当前数组内的最后一个元素进行比较,若a[i] < 数组最后一个元素,则将原来的位置上的元素向后移;若满足条件,则直接插入。

1.3 代码实现

#include <stdio.h>
// n - 数组元素个数
void InsertSort(int* a, int n)
{
	//数组第一个元素不需要参与排序
	for (int i = 1; i < n; i++)
	{
		// end - 每一次数组最后一个元素的下标
		int end = i - 1; 
		//InsertNum - 要插入的元素
		int InsertNum = a[i];
		while (end >= 0)
		{
			if (a[end] > InsertNum)
			{
				a[end + 1] = a[end];
				end--;
			}
			else
			{
				break;
			}
		}
		//当循环来到此处有两种可能性
		//1.break跳出来的
		//2.头插
		a[end + 1] = InsertNum;
	}
}

int main()
{
	int a[] = { 9,4,2,3,10,8,6,1,7,5 };
	int ArraySize = sizeof(a) / sizeof(a[0]);

	InsertSort(a, ArraySize);

	for (int i = 0; i < ArraySize; i++)
		printf("%d ", a[i]);

	return 0;
}

【运行结果】

在这里插入图片描述

1.4 特性总结

  1. 时间复杂度
    最好:原数组已经是按需求有序了,每趟只需与前面的有序元素序列的最后一个元素进行比较,总比较次数为n - 1,时间复杂度为 O(N);
    最坏:假设要排升序,原数组是逆序的情况下,O(N2)
    综上,直接插入排序的时间复杂度为O(N2)
  2. 空间复杂度:O(1)
  3. 稳定性:插入排序是在一个已经有序的小序列的基础上,一次插入一个元素。如果碰见一个和插入元素相等的,那么将会把待插入元素放在相等元素的后面。所以,相等元素的相对的前后顺序没有改变,所以插入排序是稳定的。

二、希尔排序

2.1 希尔排序的由来

从直接插入排序中,(目标数组是升序)我们总结了:当原数组是降序的时候,时间复杂度为O(N2),效率极低;当原数组是接近升序的,那么时间复杂度就是O(N),效率最高。因此,又一位名叫希尔的大佬发现,如果一开始就让数组内的元素接近有序的话,插入排序的效率不就大大提升了吗?所以,希尔排序是直接插入排序的优化

2.2 算法思路

  • 首先,预排序,目的:让数组内的元素接近有序

如何使数组接近有序?
先选定一个间隔gap的整数,然后以距离为gap数进行分组排序,其分组排序还是运用到直接插入排序

  • 最后对有序数组进行插入排序即可

当间隔gap == 1时,也就是说,距离为1的分为一组,那不就是插入排序

【演示】

(数据来源于后面的代码)

在这里插入图片描述

通过以上图片,我们还可以总结一个规律:gap为几,就代表有几组

2.3 如何选择gap

gap的取法有多种。最初希尔大佬提出取gap = n / 2gap =gap / 2,直到gap =1,后来 Knuth提出取gap = gap / 3 + 1,还有人提出取奇数好,也有人提出gap互质好。但无论哪一种主张都没有得到证明。但是在算法思路中,图中的gap取值是根据希尔大佬来的,而我在代码实现中给定的是Knuth的方法

2.4 希尔排序效率问题

有人想:希尔排序在预排序的时候不是运用到很多的插入排序,为什么其效率还是比插入排序高?
原因是:其实gap的取值决定数组内的元素是否接近有序,gap越大,排的也越快,但越不接近有序;gap越小,排的也就越慢,但越接近有序。所以一开始gap的值可以设为数组元素个数(gap一定不可能超过数组元素个数),每次进行/2,不断缩小gap,其实最后发现,希尔排序的插入排序的次数其实是小于直接排序的插入次数的

2.5 代码实现

#include <stdio.h>
//n - 数组元素个数
void ShellSort(int* a, int n)
{
	//gap最大也只能取到数组元素个数
	int gap = n;
	while (gap > 1)
	{
		//gap的取值无论是多少,最后结果一定是1
		//那么当gap=1时,就是最后的插入排序
		gap = gap / 3 + 1;
		//gap为几,就代表有几组
		for (int i = 0; i < gap; i++)
		{
		    //以下代码和插入排序差不多
			for (int j = i; j < n - gap; j += gap)
			{
				int end = j;
				int InsertNum = a[end + gap];
				while (end >= 0)
				{
					if (a[end] > InsertNum)
					{
						a[end + gap] = a[end];
						end -= gap;
					}
					else
					{
						break;
					}
				}
				a[end + gap] = InsertNum;
			}
		}
	}
}

int main()
{
	int a[] = { 9,4,2,3,10,8,6,1,7,5 };
	int ArraySize = sizeof(a) / sizeof(a[0]);

	ShellSort(a, ArraySize);

	for (int i = 0; i < ArraySize; i++)
		printf("%d ", a[i]);

	printf("\n");
	return 0;
}

【结果展示】

在这里插入图片描述

2.6 希尔排序的特性总结

1. 希尔排序是对直接插入排序的优化
2. 希尔排序的时间复杂度不好计算,因为gap的取值方法很多,导致很难去计算。但是我们可以用代码进行性能测试的对比
在这里插入图片描述
如图,当数据个数由10w时,性能结构如下图所示
在这里插入图片描述

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

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

相关文章

基于人类反馈的强化学习(RLHF)在LLM领域是如何运作的?

基于人类反馈的强化学习在LLM领域是如何运作的&#xff1f; 为什么需要强化学习RLHFPre-training modelReward ModelFine-tune with RL 参考 为什么需要强化学习 指标无法衡量。在过去的nlp任务中&#xff0c;词性标注、机器翻译、语义判别等任务是nlp任务的主力军&#xff0c…

Hytrix原理

这里写目录标题 Hytrix容错机制熔断资源隔离线程池隔离信号量隔离 服务降级请求缓存请求合并 Hystrix流程图 Hytrix容错机制 熔断 在一个统计时间窗口&#xff08;HYST rixCommandProperties.metricsRollingStatisticalWindowInMilliseconds()&#xff09;内&#xff0c;处理…

转化率双倍暴涨——客户自助服务门户

近年来&#xff0c;社交媒体的兴起使客户负责品牌对话。随着电子商务和在线帮助需求的扩大&#xff0c;公司必须满足并超越新的期望&#xff0c;以保持客户满意度。 通过SaleSmartly&#xff08;ss客服&#xff09;自动化流程功能建立客户自助服务是一种双赢的决策&#xff0c…

Ajax XHR响应

文章目录 AJAX 服务器 响应服务器响应responseText 属性responseXML 属性 AJAX 服务器 响应 服务器响应 如需获得来自服务器的响应&#xff0c;请使用 XMLHttpRequest 对象的 responseText 或 responseXML 属性。 属性描述responseText获得字符串形式的响应数据。responseXML…

2015年下半年软件设计师下午试题

试题一 【说明】 某慕课教育平台欲添加在线作业批改系统&#xff0c;以实现高效的作业提交与批改&#xff0c;并进行统计。学生和讲师的基本信息已经初始化为数据库中的学生表和讲师表。系统的主要功能如下&#xff1a; 提交作业。验证学生标识后&#xff0c;学生将电子作业通…

Ajax 数据库

文章目录 AJAX Database 实例AJAX 数据库实例实例解释 showCustomer() 函数AJAX 服务器页面 AJAX Database 实例 AJAX 可用来与数据库进行动态通信。 AJAX 数据库实例 下面的例子将演示网页如何通过 AJAX 从数据库读取信息&#xff1a; 请在下面的下拉列表中选择一个客户&…

【wpf】转换器 Converter

今天积攒了一个转换器的用法&#xff0c;分享给各位。 我们经常会有这种需求&#xff1a; 某些控件有时需要显示&#xff0c;有时需要隐藏&#xff0c;比如&#xff1a; 那&#xff0c;我就想通过一个bool变量和是否显示绑定。 但是我们知道&#xff0c;是否显示&#xff0c;…

nssctf web

[BJDCTF 2020]easy_md5 测试发现输入的内容会通过get传递但是没有其他内容 观察一下响应头 我们看到了 select * from admin where passwordmd5($pass,true) 这里的md5(string,raw) 这里的string应该清楚就是字符串&#xff0c;是必选参数 raw是可选参数 默认不写为FA…

08 - Linux终端与进程

---- 整理自狄泰软件唐佐林老师课程 查看所有文章链接&#xff1a;&#xff08;更新中&#xff09;Linux系统编程训练营 - 目录 文章目录 1. 详解控制台与终端1.1 问题1.2 历史回顾1.2.1 控制台(Console)1.2.2 终端&#xff08;Terminal&#xff09; 1.3 历史发展进程1.4 终端与…

【Springboot系列】项目启动时怎么给mongo表加自动过期索引

1、前言 在之前操作mongo的过程中&#xff0c;都是自动创建&#xff0c;几乎没有手动创建过表。 这次开发中有张表数据量大&#xff0c;并且不是特别重要&#xff0c;数据表维护一个常见的问题是过期数据没有被及时清理&#xff0c;导致数据量过大&#xff0c;查询变得缓慢。…

【操作系统】CPU 缓存一致性、MESI 协议

【操作系统】CPU 缓存一致性、MESI 协议 参考资料&#xff1a; CPU缓存一致性协议(MESI) 【JUC】Java并发机制的底层实现原理 CPU 缓存一致性 文章目录 【操作系统】CPU 缓存一致性、MESI 协议CPU Cache 的数据写入写直达写回 缓存一致性问题总线嗅探MESI 协议总结 CPU Cache …

电感知识大全

目录 一、电感的种类 1、共模电感 2、差模电感 3、工字电感 功率电感 4、磁珠 5、变压器 6、R棒电感、棒形电感、差模电感 二、电感符号 三、电感特性 前面在学习电容的时候&#xff0c;为了让大家更形象&#xff0c;更通俗的去理解这个元器件&#xff0c;都是拿水缸去…

IO多路复用——select函数

1.select函数原型和fd_set结构体说明 1.1 select函数原型 ​ 使用 select 这种 IO 多路转接方式需要调用一个同名函数 select&#xff0c;这个函数是跨平台的&#xff0c;Linux、Mac、Windows 都是支持的。程序员通过调用这个函数可以委托内核帮助我们检测若干个文件描述符的…

mybatisPlus·入门·贰

文章目录 1 简单CRUD接口1.1 根据id查询&#xff08;{id传参&#xff09;1.1.1 接口类直接继承IService1.1.2 controller直接调用方法 1.2 根据ids查询1.3 新增1.3.1 接口类直接继承IService1.3.2 controller直接调用方法 1.4 修改状态&#xff08;Query传参&#xff09;1.4.1 …

GPT-4 IDEA神仙插件亲测帮助亿万用户解决痛点!

最近&#xff0c;Intellij IDEA的插件商店推出了一款新的插件——Bito&#xff0c;据说使用了GPT-4和ChatGPT来帮助开发人员编写代码&#xff0c;并且下载量已经达到了65K以上。 这款插件可以将GPT-4和ChatGPT引入IDE来大大提高开发人员的效率。它使用了OpenAI的模型&#xff0…

ESP32设备驱动-BMM150数字地磁传感器驱动

BMM150数字地磁传感器驱动 文章目录 BMM150数字地磁传感器驱动1、BMM150介绍2、硬件准备3、软件准备4、驱动实现1、BMM150介绍 BMM150 是一款低功耗、低噪声的 3 轴数字地磁传感器,用于罗盘应用。 具有 1.56 x 1.56 mm 和 0.60 mm 高度的 12 引脚晶圆级芯片级封装 (WLCSP) 为…

JavaEE 2(4/24)

目录 1.线程 2.前台线程和后台线程 3.run和start的区别 4.线程的终止 5.线程等待 6.获取当前线程的引用 1.线程 创建线程需要继承Thread方法 调用start方法就会生成一个新的线程,调用run方法会在老的线程继续跑 main也是个线程,他是自动调用的.线程休息了先唤醒main和thre…

【文章学习系列之模型】Informer

本章内容 文章概况总体结构重点结构self-attention distilling operation&#xff08;自注意蒸馏操作&#xff09;generative style decoder&#xff08;生成式解码器&#xff09;ProbSparse self-attention mechanism&#xff08;概率稀疏自注意机制&#xff09; 实验结果主要…

双向沟通写作法: 用妙记多 Mojidoc 快速写作的实践

在妙记多 Mojidoc&#xff0c;我们希望能够为用户提供快速开始生产力的工具&#xff0c;为此我们一直在加快完善用户使用中的需求和功能迭代&#xff0c;请查看妙记多更新日志&#xff0c;看看我们产品改进速度。 妙记多 Mojidoc 如何实践双向沟通写作法以及在双向写作的文档中…

自称是资深Android程序员的面试现场,结果被面试官吊打~

1背景 牛哥工作五年了&#xff0c;是一名“资深”程序员&#xff08;嗯…至少他自己是这么认为的&#xff09; 牛哥所在的公司已经两年没有涨过工资了&#xff08;嗯…至少他是两年没涨过了&#xff09; 牛哥坐不住了&#xff0c;这位“资深”程序员打算去“外面的世界”看看…