当前位置: 首页 > article >正文

算法 -排序 -插入,选择

博客主页:【夜泉_ly】
本文专栏:【算法】
欢迎点赞👍收藏⭐关注❤️

在这里插入图片描述

文章目录

  • 💡插入排序
    • 1. ➡️直接插入排序
      • 📖简介
      • 💡实现思路
      • 📝具体示例
      • 🖼️示意图
      • 💻代码实现
    • 2. ⬆️希尔排序
      • 📖简介
      • 💡实现思路
      • 🖼️示意图
      • 💻代码实现
  • 💡选择排序
    • 1. 🔄选择排序
      • 📖简介
      • 💡实现思路
      • 🖼️示意图
      • 💻代码实现
    • 2. 🏰堆排序
      • 🖼️示意图

💡插入排序

插入排序可以分为直接插入排序和希尔排序。

1. ➡️直接插入排序

📖简介

直接插入排序常用于处理数据量较小的情况,其思想和打牌类似,都是将新元素插入到有序数组。
时间复杂度为 O ( N 2 ) O(N^2) O(N2) 。如果数据量过大,直接插入排序会因频繁的挪动数据降低效率。

💡实现思路

实现的思路:

  • 定义一个指针 end ,初始为0,表示已排序数组的结束位置。
  • 取牌,用一个临时变量 tmp 存储 end + 1处的值,表示待插入的值。
  • 挪牌,将已排序的数组中小于 tmp 的向后挪动一个位置。(这里 end + 1 的值已被保存,可以直接覆盖)
    • 定义 cur 指向 end
    • 如果 cur 处的值大于 tmp,将该值向后挪动一位,然后cur--
    • 结束条件为 cur <= -1 或者 cur 处的值小于等于 tmp
  • 插入,将 tmp 插入 cur + 1处,然后 end++
  • 结束条件为 end >= size - 1 ,即所有元素都已排序。

📝具体示例

下面是具体示例:
待排序数组:
在这里插入图片描述
首先,定义一个指针 end ,指向 0 处,表示已排序手牌:
在这里插入图片描述
取牌,用一个临时变量 tmp 存储 end + 1处的值,表示待插入的手牌:
在这里插入图片描述
挪牌:(当cur == -1,停止挪牌)
在这里插入图片描述
插入:(将tmp插入cur + 1处)
在这里插入图片描述

第二轮取牌加挪牌:(当cur处的值小于 tmp,也停止挪牌)
在这里插入图片描述
插入:
在这里插入图片描述
之后,重复上述过程即可。


🖼️示意图

插入排序 − 示意图 插入排序 -示意图 插入排序示意图

在这里插入图片描述)


💻代码实现

最后是代码实现:

void InsertSort(int* arr, int size)
{
	int end = 0;
	while (end != size - 1)
	{
		int tmp = arr[end + 1];
		int cur = end;
		while (cur > -1 && arr[cur] > tmp)
		{
			arr[cur + 1] = arr[cur];
			cur--;
		}
		arr[cur + 1] = tmp;
		end++;
	}
}

2. ⬆️希尔排序

📖简介

希尔排序是插入排序的升级版,本质是通过分组进行插入排序,可以将较大的数据尽快的挪到数组后面,从而减少挪动数据的次数,提高了效率。
时间复杂度大约为 O(N ^ 1.3),具体时间复杂度会随分组的标准而变。

💡实现思路

实现的思路:

  • 定义 gap ,初始值为 size/3 + 1,间隔为 gap 的数被分到一组。
  • 对每组进行插入排序
    • 定义一个指针 end ,初始为0,表示已排序数组的结束位置。
    • 取牌,用一个临时变量 tmp 存储 end + gap处的值,表示待插入的值。
    • 挪牌,将已排序的数组中小于 tmp 的向后挪动一个位置。(这里 end + gap 的值已被保存,可以直接覆盖)
      • 定义 cur 指向 end
      • 如果 cur 处的值大于 tmp,将该值向后挪动一位,然后cur -= gap
      • 结束条件为 cur <= -1 或者 cur 处的值小于等于 tmp
    • 插入,将 tmp 插入 cur + gap处,然后 end++
    • 结束条件为 end >= size - gap ,即所有元素都已排序。
  • gap = gap/3 + 1
  • gap == 1 为最后一次排序,此时变为直接插入排序。(经过了预处理,此时的直接插入排序效率大大提高)

🖼️示意图

希尔排序 − 示意图 希尔排序 -示意图 希尔排序示意图
在这里插入图片描述


💻代码实现

下面是代码实现:

void ShellSort(int* arr, int size)
{
	int gap = size;
	while (gap != 1)
	{
		gap = gap / 3 + 1;
		int end = 0;
		while (end < size - gap)
		{
			int tmp = arr[end + gap];
			int cur = end;
			while (cur > -1 && arr[cur] > tmp)
			{
				arr[cur + gap] = arr[cur];
				cur -= gap;
			}
			arr[cur + gap] = tmp;
			end++;
		}
	}
}

💡选择排序

选择排序分为选择排序和堆排序。

1. 🔄选择排序

📖简介

选择排序是一种比较简单直观的排序,其思想就是不断从待排序的数组中选出符合要求的数据。

由于每次选数要遍历一遍数组,而重复次数为数组长度,因此时间复杂度为 O ( N 2 ) O(N^2) O(N2)。实际用处不大,因为它不会管数据长什么样,都会从头遍历到尾,不如直接插入排序。这也给了我们一个启示:斗地主发牌时,要边拿牌边排序(插入排序),不能拿到一把牌后再排序(选择排序)。

💡实现思路

实现的思路:

  • 定义一个指针 end ,初始为-1,表示已排序数组的结束位置。(最开始还没有选出最小值,所以是 -1)
  • 选择,用一个指针 curend + 1遍历到尾,用另一个指针 min 记录最小值的位置。
  • 交换,将 end + 1 处的值与 min 处的值交换。
  • end++,继续下一轮。
  • 结束条件为 end >= size - 1 ,即所有元素都已排序。

🖼️示意图

选择排序 − 示意图 选择排序 -示意图 选择排序示意图
在这里插入图片描述


💻代码实现

下面是代码实现:

void SelectSort(int* arr, int size)
{
	int end = -1;
	while (end < size - 1)
	{
		int cur = end + 1;
		int min = cur;
		while (cur < size)
		{
			if (arr[cur] < arr[min])min = cur;
			cur++;
		}
		swap(arr[end + 1], arr[min]);
		end++;
	}
}

当然,还可以稍微优化一下,即将 end 改为 left ,同时增加一个指针 right
实现思路:

  • 定义一个指针 left ,初始为-1,表示选出最小元素的结束位置。
  • 定义一个指针 right ,初始为size,表示选出最大元素的结束位置。
  • 选择,用一个指针 curleft + 1遍历到 right - 1,用两个指针 minmax 记录最小、大值的位置。
    • 交换时,如果 left + 1处的值为最大值,即left + 1 == max,交换left + 1min后,left + 1处变为最小值,min处变为最大值。因此,为了保证交换的正确性,在这种情况下可以让 max = min
  • 交换,将 left + 1 处的值与 min 处的值交换,将 right - 1 处的值与 max 处的值交换。
  • left++,right--,继续下一轮。
  • 结束条件为 left >= right ,即所有元素都已排序。

下面是代码实现:

void SelectSort2(int* arr, int size)
{
	int left = -1, right = size;
	while (left < right)
	{
		int cur = left + 1;
		int max = cur, min = cur;
		while (cur < right)
		{
			if (arr[cur] > arr[max])max = cur;
			if (arr[cur] < arr[min])min = cur;
			cur++;
		}
		if (max == left + 1)max = min;
		swap(arr[left + 1], arr[min]);
		swap(arr[right - 1], arr[max]);
		left++, right--;
	}
}

2. 🏰堆排序

堆排序,这个我在数据结构-堆-详解中讲过了,此处略。


🖼️示意图

堆排序 − 示意图 堆排序 -示意图 堆排序示意图
在这里插入图片描述


在这里插入图片描述


希望本篇文章对你有所帮助!并激发你进一步探索编程的兴趣!
本人仅是个C语言初学者,如果你有任何疑问或建议,欢迎随时留言讨论!让我们一起学习,共同进步!


http://www.kler.cn/a/384880.html

相关文章:

  • OpenCV视觉分析之目标跟踪(10)估计两个点集之间的刚性变换函数estimateRigidTransform的使用
  • 如何使用 SSH 连接并管理你的 WordPress 网站
  • Java智慧养老养老护理帮忙代办陪诊陪护平台系统小程序源码
  • HTML第二次作业
  • 计算机体系结构知识(一)
  • ARM-8 定位发布版本 pstree 程序的 main 地址
  • ModuleNotFoundError: No module named ‘paddle.fluid‘
  • 在分布式光伏电站如何进行电能质量的治理?
  • 『Django』APIView视图扩展,实现不同的请求方式
  • 【赵渝强老师】Redis的RDB数据持久化
  • 从分析Vue实例生命周期开始,剖析Vue页面跳转背后执行过程
  • 《JavaEE进阶》----20.<基于Spring图书管理系统(登录+添加图书)>
  • sass @mixin @extend
  • 善用Git LFS来降低模型文件对磁盘的占用
  • 可视化建模与UML《顺序图实验报告》
  • 前后端交互通用排序策略
  • 基于TRIZ的教育机器人功能创新
  • 若依未分离版集成达梦数据库
  • C++异常:基本语法
  • 深入浅出 Spring Boot 与 Shiro:构建安全认证与权限管理框架
  • 基于STM32的智能充电桩:集成RTOS、MQTT与SQLite的先进管理系统设计思路
  • [linux]docker基础
  • uniapp 下拉选择器picker
  • 从配置anaconda到配置pycharm
  • C#笔记 —— 事件
  • 第3章 CentOS系统管理