【排序算法】三、选择排序(C/C++)

「前言」文章内容是排序算法之选择排序的讲解。(所有文章已经分类好,放心食用)

「归属专栏」排序算法

「主页链接」个人主页

「笔者」枫叶先生(fy)

目录

  • 选择排序
    • [1.1 原理](#1.1 原理)
    • [1.2 代码实现(C/C++)](#1.2 代码实现(C/C++))
    • [1.3 优化](#1.3 优化)
    • [1.3 特性总结](#1.3 特性总结)

选择排序

1.1 原理

选择排序是一种简单直观的排序算法

它的工作原理是:

  • 每一次从待排序的数据元素中选出最小(或最大)的一个元素,存放在序列的起始位置
  • 然后再从剩余的未排序元素中继续寻找最小(或最大)的元素,依次类推,直到所有元素排序完毕

选择排序:基于数组(顺序表)的结构进行排序

例如

原始数组如下,使用选择排序进行排序,选最小元素进行交换(升序)

遍历第一趟数组,找出数组的最小值,与第一个数据交换

遍历第二趟数组,继续找出最小值,与第二个数据交换

重复上述动作,直到数组有序

动图演示:(下列是选最小)

1.2 代码实现(C/C++)

C语言代码如下:(升序)

cpp 复制代码
void Swap(int* p1, int* p2)
{
	int tmp = *p1;
	*p1 = *p2;
	*p2 = tmp;
}

// 选择排序(以下代码是选最小)
void SelectSort(int* arr, int n)
{
	for (int i = 0; i < n; ++i)
	{
		int min = i; // 记录最小值元素的下标
		int start = i + 1;
		while (start < n)
		{
			if (arr[start] < arr[min]) min = start; // 最小值的下标更新
			++start;
		}
		Swap(&arr[i], &arr[min]); // 交换两个元素
	}
}

C++代码:(升序)

cpp 复制代码
// 选择排序(以下代码是选最小)
void SelectSort(vector<int>& arr)
{
	int n = arr.size();
	for (int i = 0; i < n; ++i)
	{
		int min = i; // 记录最小值元素的下标
		int start = i + 1;
		while (start < n)
		{
			if (arr[start] < arr[min]) min = start; // 最小值的下标更新
			++start;
		}
		swap(arr[i], arr[min]); // 交换
	}
}

1.3 优化

实际上,我们可以一趟选出两个值,一个最大值一个最小值,然后将其放在序列开头和末尾,这样可以使选择排序的效率快一倍

例如

原始数组如下,使用选择排序进行排序,一趟选出最小和最大元素进行交换

变量left和变量right是数组的两端,minimaxi分别代表最小和最大元素的下标

重复上述动作,直到数组有序

优化后的问题

如果maxi的位置与left重合,则left先与mini的位置交换,此时maxi位置的最大值被交换走,导致riightmaxi交换的数值是错误的(图中的0是10,打少了一个1)

left先与mini的位置交换数据,此时maxi位置的已经不是最大值了(图中的0是10,打少了一个1)

接着maxi再与right位置交换数据,排序就发生了错误

解决

​当maxileft重合时,leftmini交换后导致maxi指向的不再是最大值,所以当我们对left交换后,就要对maxi进行一个修正,让maxi指向最大值,然后完成right的交换,如下:

maxileft重合,并且left此时完成了交换,此时最大值已经交换到了mini所指向的位置

然后对maxi进行修正后,maxi = mini,再完成与right的交换

此时便解决了该问题

C++代码如下:

cpp 复制代码
// 选择排序(选两个: 最小和最大)
void SelectSort(vector<int>& arr)
{
	int n = arr.size();
	int left = 0, right = n - 1; // 保存单趟排序的第一个数和最后一个数下标
	while (left < right)
	{
		int mini = left, maxi = left; // 保存最小值和最大值的下标
		// 选出最小值和最大值的下标
		for (int i = left + 1; i <= right; i++)
		{
			if (arr[mini] > arr[i]) mini = i;

			if (arr[i] > arr[maxi]) maxi = i;
		}
		// 最小值放在 arr[left]
		swap(arr[left], arr[mini]);
		// left 和 maxi 重叠的时候, 上一步已经把最大值换到 arr[mini] 中去了, 修正一下最大值 maxi 位置即可
		if (left == maxi) maxi = mini;
		// 最大值放在 arr[end] 
		swap(arr[right], arr[maxi]);
		left++;
		right--;
	}
}

1.3 特性总结

选择排序特性总结

  • 选择排序思考非常好理解,但是效率不是很好,实际中很少使用
  • 时间复杂度:O(N^2)
  • 空间复杂度:O(1)
  • 稳定性:不稳定
  • 适用范围:选择排序适用于小规模数据的排序,对于大规模数据效率较低

--------------------- END ----------------------

cpp 复制代码
「 作者 」 枫叶先生
「 更新 」 2024.1.11
「 声明 」 余之才疏学浅,故所撰文疏漏难免,
          或有谬误或不准确之处,敬请读者批评指正。
相关推荐
Jm_洋洋20 分钟前
【Linux系统编程】程序替换:execve(execl、execlp、execle、execv、execvp、execvpe)
linux·运维·c语言·开发语言·程序人生
小莞尔37 分钟前
【51单片机】【protues仿真】基于51单片机秒表计时器系统(带存储)
c语言·stm32·单片机·嵌入式硬件·物联网·51单片机
冯诺依曼的锦鲤42 分钟前
算法练习:前缀和专题
开发语言·c++·算法
闭着眼睛学算法1 小时前
【双机位A卷】华为OD笔试之【哈希表】双机位A-跳房子I【Py/Java/C++/C/JS/Go六种语言】【欧弟算法】全网注释最详细分类最全的华子OD真题题解
java·c语言·c++·python·算法·华为od·散列表
代码改善世界1 小时前
C语言内存机制深度解析:指针运算、数组与字符串实战指南
c语言
开发者驿站1 小时前
2025年保姆级C++环境配置教程(Windows/macOS双平台)
c++·windows·macos
辰尘_星启1 小时前
『CMake』关于使用CMake构建项目时的现代/传统指令
c++·架构·系统·cmake·项目·构建
自信150413057592 小时前
初学者小白复盘15之指针(4)
c语言·数据结构·算法
GilgameshJSS2 小时前
STM32H743-ARM27例程-TCP_Server
c语言·arm开发·stm32·单片机·tcp/ip
AA陈超2 小时前
虚幻引擎5 GAS开发俯视角RPG游戏 P06-13 属性菜单 - 边框值
c++·游戏·ue5·游戏引擎·虚幻