排序算法(2)--- 选择排序

大家好,今天我将通过一篇博客,带领大家学习选择排序。

选择排序分为两种:直接选择排序堆排序

废话不多说,我们直接开始:

一:直接选择排序

1. 算法思想

直接选择排序的思想非常简单,就是每一次都从待排序数据中选出最小(或最大)的数据,放在序列的起始位置,直到全部待排序数据排完

类比直接插入排序:

直接插入排序可以看作是打扑克牌时一张一张摸牌的过程,直接选择排序就是一次性摸出好几张排,然后让手中的牌变有序,这时候不就是每次挑出最大的牌往后放直至有序吗?

2. 动图

接下来通过一张动图让大家直观感受一下直接选择排序的流程:

step1. 选最小值 step2. 和最前面的元素交换 step. 重复前两个步骤

3. 代码实现

++建议:任何排序算法的实现,都先写其中的一趟排序,运行结果正确,然后再套上最外层的循环。++

这里因为直接插入排序比较简单,就直接写了:

cpp 复制代码
void SelectSort(int* a, int n)
{
	// 一共执行 n - 1 轮选数操作
	for (int i = 0; i < n; i++) 
	{
		// 每一次选出最小的数
		int tmp = a[i];
		int id = i;

		for (int j = i + 1; j < n; j++)
		{
			if (a[j] < tmp)
			{
				tmp = a[j];
				id = j;
			}
		}

		// 和待排序序列最前面的数交换
		Swap(&a[i], &a[id]);
	}
}

4. 扩展

我们可不可以加快一下速度(优化一下),每一次在待排序序列中既选出最小的数,又选出最大的数,然后分别放到最前面和最后面???

这样的话当然可以,但是代码逻辑不太好控制,很容易写出 bug:(比如下面的代码)

这就锻炼我们调试代码的能力了~~~

cpp 复制代码
void SelectSort(int* a, int n)
{
	int left = 0, right = n - 1;

	while (left < right)
	{
		int mini = left, maxi = left;
		for (int i = left + 1; i <= right; i++)
		{
			if (a[i] < a[mini])
			{
				mini = i;
			}
			if (a[i] > a[maxi])
			{
				maxi = i;
			}
		}

		Swap(&a[left], &a[mini]);
		Swap(&a[right], &a[maxi]);
	
		++left;
		--right;
	}
}

大家先不要往下看,先看看自己能不能调出这个 bug !!!

由于这一期的主题不是调试,我就不带大家分析了。

如果这里 maxi 和 left 重叠,第一个 Swap 就会把 maxi 换走,导致第二个 Swap 交换就会出错。

解决方案:特殊判断处理一下就 OK 了。

修正后的代码:

cpp 复制代码
void SelectSort(int* a, int n)
{
	int left = 0, right = n - 1;

	while (left < right)
	{
		int mini = left, maxi = left;
		for (int i = left + 1; i <= right; i++)
		{
			if (a[i] < a[mini])
			{
				mini = i;
			}
			if (a[i] > a[maxi])
			{
				maxi = i;
			}
		}

		Swap(&a[left], &a[mini]);
		// 如果 left 和 maxi 重叠,交换后要修正一下
		if (left == maxi)
		{
			maxi = mini;
		}

		Swap(&a[right], &a[maxi]);
	
		++left;
		--right;
	}
}

5. 时间复杂度分析

直接选择排序算法基本上是最差的排序算法。

即使进行了优化,时间复杂度依旧是 O(n ^ 2),直接选择排序时间复杂度最好的情况和最坏的情况都是 O(n ^ 2)**因为无论是否有序,都要遍历待排序元素一遍,这也是直接选择排序慢的原因。它的唯一优点就是代码很好写,并且无视数据特征(不挑食)**。

所以打牌时是一张一张摸更快呢,还是你直接拿一把再调整更快呢?????

二:堆排序

1. 算法思想

堆排序的思想和直接选择排序一样,也是**每一次都从待排序数据中选出最小(或最大)的数据,放在序列的起始位置,直到全部待排序数据排完,**只不过直接选择排序是暴力选择,堆在选最小值(最大值)时更快。

堆排序是指利用堆积树(堆)这种数据结构所设计的一种排序算法,它也是选择排序的一种。它是通过堆来进行选择数据,这样的选法相比于暴力选法更快。

利用堆这一数据结构,快速选择数据

2. 过程

++需要注意的是:排升序要建大根堆,排降序建小根堆++

相关推荐
NAGNIP8 小时前
一文搞懂深度学习中的通用逼近定理!
人工智能·算法·面试
颜酱17 小时前
单调栈:从模板到实战
javascript·后端·算法
是希燃亚19 小时前
📚 十大经典排序算法 C语言笔记(一看就会版)
排序算法
CoovallyAIHub20 小时前
仿生学突破:SILD模型如何让无人机在电力线迷宫中发现“隐形威胁”
深度学习·算法·计算机视觉
CoovallyAIHub20 小时前
从春晚机器人到零样本革命:YOLO26-Pose姿态估计实战指南
深度学习·算法·计算机视觉
CoovallyAIHub20 小时前
Le-DETR:省80%预训练数据,这个实时检测Transformer刷新SOTA|Georgia Tech & 北交大
深度学习·算法·计算机视觉
CoovallyAIHub20 小时前
强化学习凭什么比监督学习更聪明?RL的“聪明”并非来自算法,而是因为它学会了“挑食”
深度学习·算法·计算机视觉
CoovallyAIHub21 小时前
YOLO-IOD深度解析:打破实时增量目标检测的三重知识冲突
深度学习·算法·计算机视觉
NAGNIP1 天前
轻松搞懂全连接神经网络结构!
人工智能·算法·面试
NAGNIP1 天前
一文搞懂激活函数!
算法·面试