【数据结构】插入排序 (直接插入排序 希尔排序)

文章目录

  • 直接插入排序
  • 希尔排序


直接插入排序

把待排序的记录按其关键码值的大小逐个插入到一个已经排好序的有序序列中,直到所有的记录插入完为止,得到一个新的有序序列。

如果tmp比end的数大或者相等,就继续放在end后面。
如果比end的数小,就让end的数往后挪一位,将3覆盖掉了。
在这里插入图片描述
下面看更复杂的情况,当tmp = 1时,end要减到-1结束。
在这里插入图片描述

void InsertSort(int* a, int n)
{
	for (int i = 0; i < n-1; i++)
	{
		int end = i;
		int tmp = a[end + 1];
		while (end >= 0)
		{
			if (a[end] > tmp)
			{
				a[end + 1] = a[end];
				--end;
			}
			else
			{
				break;
			}
		}

		a[end + 1] = tmp;
	}
}

插入排序的时间复杂度最坏为O(N^2^),最好为O(N)

下面我们测试一下堆排序和插入排序的性能:

堆排序:

void Swap(int* p1, int* p2)
{
	int tmp = *p1;
	*p1 = *p2;
	*p2 = tmp;
}

void AdjustDown(int* a, int n, int parent)
{
	int minChild = parent * 2 + 1;
	while (minChild < n)
	{
		// 找出小的那个孩子
		if (minChild + 1 < n && a[minChild + 1] > a[minChild])
		{
			minChild++;
		}

		if (a[minChild] > a[parent])
		{
			Swap(&a[minChild], &a[parent]);
			parent = minChild;
			minChild = parent * 2 + 1;
		}
		else
		{
			break;
		}
	}
}

// O(N*logN)
void HeapSort(int* a, int n)
{
	// 大思路:选择排序,依次选数,从后往前排
	// 升序 -- 大堆
	// 降序 -- 小堆
	// 建堆 -- 向下调整建堆 - O(N)
	for (int i = (n - 1 - 1) / 2; i >= 0; --i)
	{
		AdjustDown(a, n, i);
	}

	// 选数
	int i = 1;
	while (i < n)
	{
		Swap(&a[0], &a[n - i]);
		AdjustDown(a, n - i, 0);
		++i;
	}
}

测试用例:

void TestOP()
{
	srand(time(0));
	const int N = 1000000;
	int* a1 = (int*)malloc(sizeof(int) * N);
	int* a4 = (int*)malloc(sizeof(int) * N);
;


	for (int i = 0; i < N; ++i)
	{
		a1[i] = rand();
		a4[i] = a1[i];

	}

	int begin1 = clock();
	InsertSort(a1, N);
	int end1 = clock();
	int begin4 = clock();
	HeapSort(a4, N);
	int end4 = clock();


	printf("InsertSort:%d\n", end1 - begin1);
	printf("HeapSort:%d\n", end4 - begin4);

	free(a1);
	free(a4);
}

int main()
{
	TestOP();
	return 0;
}

排完取时间:单位是毫秒

在这里插入图片描述

希尔排序

希尔排序又称缩小增量法。希尔排序法的基本思想是:先进行预排序,再进行最后的一个插入排序。
1.预排序目的:接近排序。
2.直接插入排序。

预排序:间隔为gap的数据分为一组进行插入排序。

针对升序,gap越大,大的数据可以越快跳到后面,小的数据可以更快的跳到前面。gap越小,跳的越慢,越接近有序。
在这里插入图片描述

排完之后的数据也是没有序的,但是相比于原数据,小的数据偏前面,大的数据偏后面,小的数据往前面挪相对快一点,大的也是。一次跳跃挪gap步。

gap > 1 预排序
gap == 1 直接插入排序

希尔排序:

void PrintArray(int* a, int n)
{
	for (int i = 0; i < n; i++)
	{
		printf("%d ", a[i]);
	}
	printf("\n");

}
void ShellSort(int* a, int n)
{
	//gap > 1 预排序
	//gap == 1 直接插入排序
	int gap = n;
	while (gap > 1)
	{
		gap = (gap / 3) + 1;
		for (int i = 0; i < n - gap; i++)
		{
			//[0,end] 插入 end+gap [0,end+gap]有序 --间隔为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;
		}
	}
}

void TestShellSort()
{
	int a[] = {9,8,7,6,5,4,3,2,1,0};
	ShellSort(a, sizeof(a) / sizeof(int));
	PrintArray(a, sizeof(a) / sizeof(int));
}

int main()
{
	TestShellSort();
	return 0;
}

在这里插入图片描述

在这里插入图片描述

我们测试看看希尔排序的效率:

void TestOP()
{
	srand(time(0));
	const int N = 10000;
	
	int* a1 = (int*)malloc(sizeof(int) * N); 
	int* a2 = (int*)malloc(sizeof(int) * N);


	for (int i = 0; i < N; ++i)
	{
		a1[i] = rand();
		a2[i] = a1[i];

	}

	int begin1 = clock();
	InsertSort(a1, N);
	int end1 = clock();

	int begin2 = clock();
	ShellSort(a2, N);
	int end2 = clock();



	printf("InsertSort:%d\n", end1 - begin1);
	printf("ShellSort:%d\n", end2 - begin2);


	free(a1);
	free(a2);
	free(a3);
	free(a4);
	free(a5);
	free(a6);
}

int main()
{
	TestOP();
	return 0;
}

10000个数据:
在这里插入图片描述
100000个数据:

在这里插入图片描述

堆排序、插入排序、希尔排序相比较,堆排序和希尔排序属于同一量级的。

在这里插入图片描述

总结:

  1. 希尔排序是对直接插入排序的优化。
  2. 当gap > 1时都是预排序,目的是让数组更接近于有序。当gap == 1时,数组已经接近有序的了,这样就会很快。这样整体而言,可以达到优化的效果。
  3. 希尔排序的时间复杂度不好计算,因为gap的取值方法很多,导致很难去计算。

在这里插入图片描述

我们可以看看一些书中的解释;
在这里插入图片描述

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

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

相关文章

Elasticsearch基本安全加上安全的 HTTPS 流量

基本安全加上安全的 HTTPS 流量 在生产环境中&#xff0c;除非您在 HTTP 层启用 TLS&#xff0c;否则某些 Elasticsearch 功能&#xff08;例如令牌和 API 密钥&#xff09;将被禁用。这个额外的安全层确保进出集群的所有通信都是安全的。 当您在模式下运行该elasticsearch-ce…

初始React

一.React的诞生1.什么是React?React是一个讲数据渲染为HTML视图的来源Js库&#xff0c;用于构建用户界面的JS库。在以前的学习中构建用户界面的常用操作步骤&#xff1a;发送请求获取数据处理数据&#xff08;过滤&#xff0c;整理格式等&#xff09;操作DOM呈现页面2.React诞…

《SpringBoot》第02章 自动配置机制(一) 项目启动

前言 关于SpringBoot&#xff0c;最大的特点就是开箱即用&#xff0c;通过自动配置机制&#xff0c;遵守约定大于配置这个准则&#xff0c;那么这个是如何实现的呢&#xff1f; 本章首先会介绍SpringBoot的启动执行 一、启动第一步&#xff1a;初始化 1.本章概述 当启动Sp…

【论文精读(李沐老师)】Attention Is All You Need

Abstract 在主流的序列转录&#xff08;给你一个序列&#xff0c;生成另外一个序列&#xff09;模型中主要是依赖复杂的RNN和CNN&#xff0c;一般包括encoder和decoder两个结构。在性能最好的模型里&#xff0c;通常使用注意力机制连接encoder和decoder。 &#xff08;本文想做…

HTTP API接口设计规范

1. 所有请求使用POST方法 使用post&#xff0c;相对于get的query string&#xff0c;可以支持复杂类型的请求参数。例如日常项目中碰到get请求参数为数组类型的情况。 便于对请求和响应统一做签名、加密、日志等处理 2. URL规则 URL中只能含有英文&#xff0c;使用英文单词或…

爱玩飞飞加速实现与分析

一步一步找数据。然后根据游戏数据找游戏基址&#xff0c;游戏基址可以遍历所有数据。想学的可以看看。第一步找基础数据&#xff0c;我们用的ce7.1.当然你们也可以用其他版本。网上随便下一个就行。 第一步。打开ce7.1附加游戏进程。 然后看下自己的血量是多少。我们这里是5…

HTML5支持的视频文件格式和音频文件格式有哪些?

在 HTML5 标准中, 我们有了新的 和 标签, 分别可以引入视频和音频文件的标签 那么这些标签又可以支持哪些文件格式呢 ? 格式支持 视频文件格式 MP4&#xff1a;MPEG-4 Part 14&#xff0c;支持H.264编码。几乎所有的浏览器都支持该格式。 WebM&#xff1a;谷歌开发的格式&a…

【最短路算法】第三弹:一文学懂spfa 算法(队列优化的Bellman-Ford算法)

博主简介&#xff1a;努力学习的大一在校计算机专业学生&#xff0c;热爱学习和创作。目前在学习和分享&#xff1a;算法、数据结构、Java等相关知识。博主主页&#xff1a; 是瑶瑶子啦所属专栏: 算法 &#xff1b;该专栏专注于蓝桥杯和ACM等算法竞赛&#x1f525;近期目标&…

Java Script

一.初识js 1.与css html的关系 HTML 网页的结构(骨CSS:网页的表现(皮JavaScript :网页的行为2.运行过程 编写的代码是保存在文件上,也就是存储到硬盘(外存zhong)双击以后,html文件浏览器(引用程序)就会读取文件,将文件内容加载到内存中,(数据流向:硬盘->内存)浏览器会解析用…

Linux——基本指令

目录 01. ls 指令 02. pwd命令 03. cd 指令 04. touch指令 05.mkdir指令&#xff08;重要&#xff09; 06.rmdir指令 && rm 指令&#xff08;重要&#xff09; 07.man指令&#xff08;重要&#xff09; 08.cp指令&#xff08;重要&#xff09; 09.mv指令&…

react使用craco.config.js完成rem移动端适配(sass)

环境&#xff1a; "react": "^18.2.0", "react-dom": "^18.2.0", "react-router-dom": "^6.8.2", "sass": "^1.58.3", yarn add craco/craco postcss-pxtorem lib-flexible 1、创建 craco.…

Java入门知识(超详细讲解)

&#x1f648;作者简介&#xff1a;练习时长两年半的Java up主 &#x1f649;个人主页&#xff1a;老茶icon &#x1f64a; ps:点赞&#x1f44d;是免费的&#xff0c;却可以让写博客的作者开兴好久好久&#x1f60e; &#x1f4da;系列专栏&#xff1a;Java全栈&#xff0c;计…

REDIS19_zipList压缩列表详解、快递列表 - QuickList、跳表 - SkipList

文章目录①. 压缩列表 - zipList②. 快递列表 - QuickList③. 跳表 - SkipList①. 压缩列表 - zipList ①. ZipList是一种特殊的"双端链表",由一系列特殊编码的连续内存块组成。可以在任意一端进行压入/弹出操作,并且该操作的时间复杂度为O(1) (oxff:11111111) type…

BI界的ChatGPT,它有什么厉害之处

​ChatGPT火了&#xff0c;注册用户从0到1亿&#xff0c;仅用了2个月时间。ChatGPT的背后是大数据、大模型、大算力&#xff0c;是AI的能力集中化的典型场景。那么在BI界&#xff0c;是否也有一款像ChatGPT一样智能BI软件&#xff0c;只要告诉它我们想看啥数据&#xff0c;它噔…

使用 Jpom 自动构建和部署项目

比 Jenkins 简单的项目构建和部署工具。 前端项目自动构建部署 我有几个自用的前端项目&#xff0c;每次修改代码后都需要本地打包再上传到服务器进行部署&#xff0c;感觉有点麻烦&#xff0c;不够自动化&#xff0c;所以一直想找个能够实现自动构建和部署的工具。 这时候可…

智能灯泡灯一Homekit智能家居

传统的灯泡是通过手动打开和关闭开关来工作。有时&#xff0c;它们可以通过声控、触控、红外等方式进行控制&#xff0c;或者带有调光开关&#xff0c;让用户调暗或调亮灯光。 智能灯泡内置有芯片和通信模块&#xff0c;可与手机、家庭智能助手、或其他智能硬件进行通信&#…

Camtasia Studio2023非常好用的电脑录屏软件

如果你需要制作视频教程、游戏直播或其他视频内容&#xff0c;那么一个好的录屏软件就是必不可少的。Camtasia Studio是非常好用的录屏软件&#xff0c;它们可以记录计算机屏幕上发生的所有活动&#xff0c;并可捕捉声音。这些软件还提供了一些视频编辑功能&#xff0c;如裁剪、…

【Python学习笔记(七)】queue队列模块的使用

queue队列模块的使用 前言 为了解决多线程之间共享数据的问题&#xff0c;需要对线程进行加锁或者是线程等待&#xff1b; 更简单的解决这一问题&#xff0c;就需要引入队列的概念&#xff1a; 队列是一种特殊的线性表&#xff0c;是一种先进先出 (FIFO) 的数据结构&#xff…

代码随想录第二十七天(669、108、538、回溯算法介绍)

669. 修剪二叉搜索树 不能简单地通过递归实现代码&#xff0c;比如&#xff1a; class Solution { public:TreeNode* trimBST(TreeNode* root, int low, int high) {if (root nullptr || root->val < low || root->val > high) return nullptr;root->left t…

Altium Designer 2023版本安装过程

1、解压下载好的文件。 2、双击打开Setup文件夹。 3、找到installer文件&#xff0c;右键点击&#xff0c;并且以管理员身份运行。 4、点解next。 5、选择语言位&#xff1a;Chinese&#xff0c;点击我同意&#xff0c;接着next。 6、勾选前面两个&#xff0c;点击next。 7、选…
最新文章