数据结构:选择排序

上一篇我们讲了插入排序,这一篇我们来讲选择排序。因为堆排序之前我们有详细讲过,所以这里只给出堆排序的思路,有兴趣的可以看一看。# 选择排序

选择排序就是从数组中选出最小值和最大值,最小值放在第一个位置,最大值放在最后一个位置,依次执行,直到排成有序数组为止。

直接选择排序

直接选择排序就是从 begin 到 end 范围中获取最大值和最小值,将最小值放到 begin 位置,最大值放到 end 位置。依次执行直到排成有序数组为止。

思路

比如说我们有以下数组:

我们把数组起始位置作为begin,末尾作为end,从中找出最小值mini和最大值maxi。

我们将最小值mini位置和begin位置数据交换一下,然后将最大值maxi位置和end位置数据交换一下,使得最小值放到begin位置,最大值放到end位置。

然后begin++,end- -,再从beign到end范围中找出最小值mini和最大值maxi。

将mini和begin数据交换,maxi和end数据交换。

然后begin++,end- -,继续从begin到end范围中找最小值和最大值。

此时我们发现maxi在begin位置,如果我们继续直接交换mini和begin,maxi和end就会发生这样一件事。

我们发现最小值没有来到begin位置,最大值也没有到end位置,这是为什么呢?

maxi在begin位置的时候,我们先交换的是begin和mini位置的数据,这会导致maxi被交换到了mini的位置。

因此,当begin == maxi的时候,我们要让maxi = mini,这步的意义是存储begin被交换后maxi当前所处的位置,这样end和maxi交换才不会出错。## 代码实现

综上所述,我们排序的循环条件是begin < end,当end >= begin的时候则说明排序结束了。然后初始情况下begin = 0,end = n - 1;每次找到最小值最大值并放到begin,end位置后,begin++,end--。

接下来我们定义mini和maxi,我们让它们一开始等于begin,然后从begin + 1到end位置遍历一遍找最大值和最小值。

因为我们是先将最小值放到begin处,所以要判断begin == maxi是否成立,如果成立则让maxi = mini,记录交换后最大值的位置。

如果我们是先将最大值放到end处,则需要判断end == mini,成立则让mini = maxi。

然后将mini处数据和begin处交换,maxi处数据和end处交换。

这个代码就写好了。

我们来简单测试一下。

结果符合预期,说明代码没什么问题。

时间复杂度

该算法嵌套了两层循环,外层因为是两边同时查找,循环次数缩短到了 n/2,内层循环总次数也相当于一个公差为 -2 的等差数列之和,总的来说无论什么情况,该算法时间复杂度为 O(n2)。

堆排序

如果有兴趣的可以看看这篇文章,详细内容不再赘述。

数据结构:堆排序

堆排序是利用堆的思想来进行排序的算法,将原数组通过向上/向下调整算法调整成一个大堆,然后堆顶和堆底元素(数组开头和末尾)进行交换,数组大小 size--,再调整前 size 个元素保证成为一个大堆结构,循环往复直到 size == 0,排序结束。

c 复制代码
void Swap(int* x, int* y)
{
	int tmp = *x;
	*x = *y;
	*y = tmp;
}
//向下调整算法
void AdjustDown(int* arr, int parent, int n)
{
	int child = parent * 2 + 1;//左孩子
	while (child < n)
	{
		if (child + 1 < n && arr[child + 1] > arr[child])
			child++;
		if (arr[parent] < arr[child])
		{
			Swap(&arr[parent], &arr[child]);
			parent = child;
			child = parent * 2 + 1;
		}
		else
			break;
	}
}
//向上调整算法
AdjustUp(int* arr,int child)
{
	int parent = (child - 1) / 2;
	while (child > 0)
	{
		if (arr[parent] < arr[child])
		{
			Swap(&arr[parent], &arr[child]);
			child = parent;
			parent = (child - 1) / 2;
		}
		else
			break;
	}
}
//堆排序
void HeapSort(int* arr, int n)
{
	//建大堆
	for (int i = (n - 1 - 1) / 2;i--;i >= 0)
	{
		AdjustDown(arr, i, n);
	}
	//排序
	while (n > 0)
	{
		//交换堆顶和堆底元素
		Swap(&arr[0], &arr[n - 1]);
		n--;
		AdjustDown(arr, 0, n);
	}
}
相关推荐
Code_Solitude4 小时前
C语言动态内存 + 柔性数组 + 数组名退化
c语言·算法·柔性数组
上海潭龙东海科技有限公司4 小时前
客运站管控之动态孪生技术方案(新增一屏管控模块
数据仓库·人工智能·算法·重构·动态规划
YLCHUP6 小时前
【思维&图论建模】题解:债权(debt)_图论_建模_思路转化_思维题目_C++算法竞赛
c++·笔记·算法·数学建模·贪心算法·深度优先·图论
思麟呀7 小时前
背包DP(01背包+完全背包)
c++·算法
笑容掩饰我的失落8 小时前
区块链从小白到精通(七):Solidity 语法精讲——数据类型、函数、修饰器与事件
算法·区块链·php·智能合约·哈希算法
Pniubi9 小时前
力扣24. 两两交换链表中的节点(递归)
算法·leetcode·链表
nice_lcj5209 小时前
LRU 缓存入门:它是什么、怎么用、面试怎么手写
java·数据结构·缓存·面试·lru
꧁细听勿语情꧂9 小时前
直接选择排序,堆排序,冒泡排序,递归快速排序、hoare版本、挖坑法、lomuto前后指针,非递归快速排序
c语言·开发语言·数据结构·算法
俊俊几年的10 小时前
动态规划(Dynamic Programming)详解:从入门到 LeetCode Hot 100
linux·c++·算法·leetcode·嵌入式·动态规划·c