【数据结构】插入排序、选择排序、冒泡排序、希尔排序、堆排序

news2024/11/29 14:55:45

前言:生活中我们总是会碰到各种各样的排序,今天我们就对部分常用的排序进行总结和学习,今天的内容还是相对比较简单的一部分,各位一起加油哦!

💖 博主CSDN主页:卫卫卫的个人主页 💞
👉 专栏分类:数据结构 👈
💯代码仓库:卫卫周大胖的学习日记💫
💪关注博主和博主一起学习!一起努力!
在这里插入图片描述


插入排序

插入排序:我们可以通俗的理解成将一个数记录下来按其数值的大小逐个插入到一个已经排好序的有序序列中,直到所有的记录插入完为止,得到一个新的有序序列。(由于动图画的实在太过于繁琐博主就画了一半,请见谅)
请添加图片描述

代码思路:由此图我们可以知道,我们用一个tmp记录后面一个元素,如果后面的比前面的小,就让前面的元素逐一和他比较并往后走,如果碰到比他小的就停下来插入到此位置。(不理解的话可以理解成我们平常玩的斗地主的牌,拿一张牌插到应该有的位置)。


代码实现

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 (tmp < a[end])//前一个大于后一个,让大的全部往后走
			{
				a[end + 1] = a[end];
				end--;
			}
			else
			{
				break;	
			}
		}
		a[end + 1] = tmp;//在把小的放在此时的位置
	}
}

测试函数:

void Test_InsertSort()
{
	int a[] = { 1,2,30,0,99,1,7,8,2,11,0,3,13 };
	InsertSort(a, sizeof(a) / sizeof(a[0]));
	PrintArray(a, sizeof(a) / sizeof(a[0]));
}

排序结果:
在这里插入图片描述


希尔排序

希尔排序:我们可以通俗的把待排的序列看成若干个子序列,然后对其分别进行直接插入排序,最后在对全部进行一次排序即可。(如下图所示)
在这里插入图片描述


我们可以理解成gap>1是预排序,目的是让它接近有序
gap == 1是直接插入排序,目的是让它有序。但是记住最后一定要让gap最后一次排序为1
代码思路:我们可以把每次排序写成一次插入排序,然后最后一让其间距不断的变化直到最后一次全部排序完成。
代码实现:

void ShellSort(int* a, int n)//希尔排序 
{
	int gap = n;
	while (gap)
	{
		gap = gap / 2 ;
		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 = end -gap;
				}
				else
				{
					break;
				}
			}
			a[end + gap] = tmp;//在把小的放在此时的位置
		}
	}
}


函数测试

void Test_ShellSort()
{
	int a[] = { 1,2,30,0,99,1,7,8,2,11,0,3,13 };
	ShellSort(a, sizeof(a) / sizeof(a[0]));
	PrintArray(a, sizeof(a) / sizeof(a[0]));
}

运行结果:
在这里插入图片描述


冒泡排序

冒泡排序:也是我们所碰到的最简单的一种排序,这种排序的思想是十分简单的,我们可以理解成每一趟找到序列中最大的一个或最小的元素,排序到序列的最左边(右边),然后排序序列的有效次数趟即可排序完成(如下图)。
请添加图片描述

代码实现:

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

void BubbleSort(int* a, int n)//冒泡排序
{
	int i = 0;
	for (int j = 0; j < n - 1; j++)
	{
		for (i = 0; i < n - j -1; i++)//每一趟找到一个最大的
		{
			if (a[i] < a[i + 1])
			{
				Swap(&a[i], &a[i + 1]);
			}
		}
	}
}


函数测试:

void Test_BubbleSort()
{
	int a[] = { 1,2,30,0,99,1,7,8,2,11,0,3,13 };
	BubbleSort(a, sizeof(a) / sizeof(a[0]));
	PrintArray(a, sizeof(a) / sizeof(a[0]));
}

运行结果
在这里插入图片描述


选择排序

选择排序:我们现在一组有序序列中找到最大(最小)和第一个位置交换,然后再找次大的和第二个交换以此类推,最后我们即可得到一个有序序列。(如下图所示)
请添加图片描述


代码实现

void SelectSort(int*a ,int n)//选择排序
{
	//现在数组中找到最小的,然后和第一个位置交换
	//再找到次小的,和第二个位置交换
	int min = 0;
	for (int i = 0; i < n - 1 ; i++)
	{
		min = i;//最小的数的下标
		for (int j = i; j < n; j++)
		{
			if (a[min] > a[j])//找到最小位置的下标
			{
				min = j;
			}
		}
		if(min != i)
			Swap(&a[i], &a[min]);
	}
}


测试函数

void Test_SelectSort()
{
	//int a[] = { 1,2,30,0,99,1,7,8,2,11,0,3,13 };
	int a[] = { 1,0,0,0,99,1,7,8,2,9,0,3,0 };

	SelectSort(a, sizeof(a) / sizeof(a[0]));
	PrintArray(a, sizeof(a) / sizeof(a[0]));

}

运行结果:
在这里插入图片描述


但是上面这种方法我们一共要找n-1次,我们思考一下每一次查找的过程中,如果我们每次一起查找最大的和最小的,那我们不就提高了一倍的效率。所以我们只需要再引入一个max变量来帮助我们再记录一下这个值即可。
代码实现

void SelectSort_best(int* a, int n)//选择排序
{
	int begin = 0;
	int end = n - 1;
	while (begin < end)
	{
		int max = begin;
		int min = begin;
		int i = 0;
		for (i = begin + 1; i <= end; i++)//找最小的和最大的
		{
			if (a[i] < a[min])
			{
				min = i;
			}
			if (a[i] > a[max])
			{
				max = i;
			}
		}
		Swap(&a[begin], &a[min]);
		if (begin == max)//防止最大的和最小的是相同的
		{
			max = min;
		}
		Swap(&a[end], &a[max]);
		begin++;
		end--;
	}
}

运行结果依然和前面的相同,这里就不做更多的阐述了。


堆排序

堆排序:前面我们讲了的模拟实现,我们知道堆的父亲结点一定比它的孩子结点大(小),因此我们可以充分的利用这一点来进行排序。

  1. 首先我们们将数组中的元素,想象成一个堆,将其中的父亲结点全部向下调整。(如下图)在这里插入图片描述
  2. 根据我们模拟建立的大堆或者小堆,将其堆顶元素和堆尾进行交换,因此我们可以得到一个最大(最小的元素)再堆底,然后再通过一个end记录尾部,交换一次减减一次,以此循环到end为0的时候即堆中所有元素也排序完成。(如下图所示)
    在这里插入图片描述

代码实现:

void AdjustDown(int* a, int size, int parent)//向下调整
{
	assert(a);
	int child = parent * 2 + 1;//找到第一个孩子
	while (child < size)
	{
		//看俩个孩子谁更小,交小的那个与父亲去比较
		if (a[child] < a[child + 1] && (child + 1) < size)
		{
			child += 1;
		}
		if (a[parent] < a[child])
		{
			Swap(&a[parent], &a[child]);
			parent = child;//让父亲和儿子往下走
			child = child * 2 + 1;
		}
		else
		{
			break;
		}
	}
}

void HeapSort(int* a, int n)//堆排序
{
	int i = 0;
	for (i = (n - 1 - 1) / 2; i >= 0; i--)//建堆,只有父亲结点需要调整
	{
		AdjustDown(a, n, i);
	}
	int end = n - 1;
	while (end > 0)
	{
		Swap(&a[0], &a[end]);
		AdjustDown(a, end, 0);
		end--;
	}
}

函数测试:


void Test_HeapSort()
{
	int a[] = { 20,10,8,2,1,2,7 };
	HeapSort(a, sizeof(a) / sizeof(a[0]));
	PrintArray(a, sizeof(a) / sizeof(a[0]));
}

运行结果:
在这里插入图片描述


好啦,今天的内容就到这里啦,下期内容预告【快速排序的模拟实现】-- 四种方式


结语:今天的内容就到这里吧,谢谢各位的观看,如果有讲的不好的地方也请各位多多指出,作者每一条评论都会读的,谢谢各位。


🫵🫵🫵 祝各位接下来好运连连 💞

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

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

相关文章

Python经典游戏 唤醒你童年记忆

这些游戏你玩过几个&#xff1f; 1.贪吃蛇2.吃豆人3.加农炮4.四子棋5. Fly Bird<font color #f3704ab>6.记忆&#xff1a;数字对拼图游戏&#xff08;欢迎挑战&#xff01;用时&#xff1a;2min&#xff09;7.乒乓球8.上课划水必备-井字游戏&#xff08;我敢说100%的人都…

verilog rs232串口模块

前面发了个发送模块&#xff0c;这次补齐&#xff0c;完整。 串口计数器&#xff0c;波特率适配 uart_clk.v module uart_clk(input wire clk,input wire rst_n,input wire tx_clk_en,input wire rx_clk_en,input wire[1:0] baud_sel,output wire tx_clk,output wire rx_clk )…

spring、springmvc、springboot、springcloud简介

spring简介 spring是什么&#xff1f; spring: 春天spring: 轻量级的控制反转和面向切面编程的框架 历史 2002年&#xff0c;首次推出spring雏形&#xff0c;interface 21框架2004年&#xff0c;发布1.0版本Rod Johnson: 创始人&#xff0c;悉尼大学&#xff0c;音乐学博士…

什么是 NLP (自然语言处理)

NLP&#xff08;自然语言处理&#xff09;到底是做什么&#xff1f; NLP 的全称是 Natural Language Processing&#xff0c;翻译成中文称作&#xff1a;自然语言处理。它是计算机和人工智能的一个重要领域。顾名思义&#xff0c;该领域研究如何处理自然语言。 自然语言就是我…

企业如何购买腾讯云服务器?(详细指南)

腾讯云服务器购买流程直接在官方秒杀活动上购买比较划算&#xff0c;在云服务器CVM或轻量应用服务器页面自定义购买价格比较贵&#xff0c;但是自定义购买云服务器CPU内存带宽配置选择范围广&#xff0c;活动上购买只能选择固定的活动机&#xff0c;选择范围窄&#xff0c;但是…

如何本地部署Nextcloud结合cpolar搭建专属私有云盘远程访问(内网穿透)

文章目录 摘要1. 环境搭建2. 测试局域网访问3. 内网穿透3.1 ubuntu本地安装cpolar3.2 创建隧道3.3 测试公网访问 4 配置固定http公网地址4.1 保留一个二级子域名4.1 配置固定二级子域名4.3 测试访问公网固定二级子域名 摘要 Nextcloud,它是ownCloud的一个分支,是一个文件共享服…

前端基本性能指标及lighthouse使用

文章目录 1、基本指标介绍2、Performace分析2.1 performance属性2.2 使用performace计算2.3 Resource Timing API2.4 不重复的耗时时段区分2.5 其他组合分析2.6 JS 总加载耗时2.7 CSS 总加载耗时 3、lighthouse基本使用3.1 使用Chrome插件lighthouse3.2 使用Chrome浏览器开发者…

SQL server使用profiler工具跟踪语句

1.打开SQL server工具&#xff0c;在工具点击SQL server Profiler : 2.流程&#xff1a;暂停——清空———点击接口——启用&#xff1a; 3.找到对应的sql语句&#xff0c;复制到查询界面&#xff0c;开始查询数据&#xff1a;

QML —— ProgressBar示例(附完整源码)

示例 - 效果 实例 - 源码 import QtQuick 2.12 import QtQuick.Window 2.12import QtQuick.Layouts 1.12 import QtQuick.Controls 2.5Window {id: rootIdvisible: truewidth: 640height: 480title: qsTr("Hello World")Column{spacing: 40anchors.centerIn: parent…

UG NX二次开发(C++)-通过两点和高度创建长方体

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 1、前言2、采用UFun函数来创建长方体3、采用NXOpen方法实现两点和高度创建长方体4、验证1、前言 在UG NX二次开发时,我们通常会采用ufun函数来完成功能的开发,但是有些功能在ufun函数中不能找到…

电子握力器改造

toy_hand_game 介绍 消耗体力玩具&#xff0c;使用握力器(Grip Strengthener)控制舵机旋转。 开始设想是控制丝杆电机滑动&#xff0c;两套设备就可以控制两个丝杆电机进行“模拟拔河”&#xff0c;后续发现硬件设计错误&#xff0c;ULN2003不能控制两相四线电机&#xff0c;…

大数据Doris(四十三):创建物化视图

文章目录 创建物化视图 一、首先你需要有一个Base表

1933年地级市民国铁路开通数据(地级市工具变量)

1933年地级市民国铁路开通数据&#xff08;地级市工具变量&#xff09; 1、时间&#xff1a;1933年 2、指标&#xff1a;是否开通铁路 3、来源&#xff1a;来源于《中国铁道便览》和《中国铁道便览》 4、方法说明&#xff1a;参考田坤&#xff08;2023&#xff09;参考章元…

绝缘电阻测试仪的读数方法有哪些?

绝缘电阻测试仪主要用于测量设备的绝缘电阻&#xff0c;电力工人经常使用它来测试电力设备&#xff0c;从来没有维护过电力设备的正常运行状态。在测试电力设备时&#xff0c;往往需要读取测试结果。绝缘电阻测试仪常用的读数方法有哪些&#xff1f;我一起来盘点一下。 常用的绝…

15 Sequence-Driver-Sequencer communication in UVM

我们分别讨论了sequece_item、sequence、sequencer和driver。在本节中&#xff0c;我们将讨论他们如何相互talk&#xff0c;sequencer如何给driver提供从sequence里的sequence item。在开始阅读本节之前&#xff0c;请确保您了解sequencer和driver中使用的所有方法。&#xff0…

idea Spring Boot项目使用JPA创建与数据库链接

1.pom.xml文件中添加依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-jpa</artifactId></dependency><dependency><groupId>com.mysql</groupId><artifactId>…

Python+OpenCV 零基础学习笔记(4-5):计算机图形基础+Python相对文件路径+OpenCV图像+OpenCV视频

文章目录 相关链接运行环境前言计算机图形OpenCV简单使用图形读取文件读取可能会出现的问题&#xff1a;路径不对解决方案其它路径问题解决方案 图像显示保存OpenCV视频视频素材如何获取&#xff1f;简单视频读取 相关链接 【2022B站最好的OpenCV课程推荐】OpenCV从入门到实战 …

Jackson通过自定义序列化器给URL拼接访问域名

1、需求 在存储文件访问路径时&#xff0c;一般不会存储域名地址&#xff0c;若文件服务域名和当前应用域名不一致时&#xff0c;就需要在返回数据库的图片路径给前端时&#xff0c;拼接文件服务的域名。 2、处理方式 因为Spring Boot默认使用的是Jackson作为序列化工具&…

redis的搭建及应用(二)-redis的持久化策略

Redis的持久化策略 RDB RDB持久化是指在指定的时间间隔内将redis内存中的数据集快照写入磁盘&#xff0c;实现原理是redis服务在指定的时间间隔内先fork一个子进程&#xff0c;由子进程将数据集写入临时文件&#xff0c;写入成功后&#xff0c;再替换之前的文件&#xff0c;用二…

【力扣】20.有效的括号

家人们&#xff0c;看这排序&#xff0c;一看就很简单&#xff0c;对吧&#xff1f;不对&#xff0c;我觉得还挺不是很容易的&#xff0c;哈哈哈。 题解&#xff1a; 在看题目的时候&#xff0c;我一开始的解题思路就挺复杂的。题目说了”左括号必须以正确的顺序闭合“&#x…