前言
选择排序(Selection Sort)是一种简单直观的排序算法,其工作原理是每次从未排序的部分中选出最小(或最大)的元素,将其与当前的第一个元素交换位置,然后缩小未排序部分的范围。每一轮都会找到剩余部分中的最小元素,逐步构建一个有序的数组。选择排序的时间复杂度为 O(n²),不适合大数据集,但由于其实现简单,通常被用于教学和理解基本排序算法的入门。
选择排序
选择排序(Selection Sort)是一种简单的排序算法,其基本思想是每次从待排序的部分选择一个最小(或最大)元素,将其放到已排序部分的末尾。它通过不断选择剩余部分的最小元素,并将其放到当前位置,直到整个数组排序完成。
选择排序的过程
假设我们有一个数组 [64, 25, 12, 22, 11]
,使用选择排序对它进行升序排序。
-
初始数组:
[64, 25, 12, 22, 11]
- 初始时整个数组为待排序部分。
-
第1轮:
- 寻找最小值:在
[64, 25, 12, 22, 11]
中,最小的元素是11
。 - 交换位置:将
11
与第一个元素64
交换位置。
[11, 25, 12, 22, 64]
第1轮结果:
11
是已排序部分的第一个元素。 - 寻找最小值:在
-
第2轮:
- 寻找最小值:在
[25, 12, 22, 64]
中,最小的元素是12
。 - 交换位置:将
12
与第一个元素25
交换位置。
[11, 12, 25, 22, 64]
第2轮结果:
11
和12
是已排序部分。 - 寻找最小值:在
-
第3轮:
- 寻找最小值:在
[25, 22, 64]
中,最小的元素是22
。 - 交换位置:将
22
与第一个元素25
交换位置。
[11, 12, 22, 25, 64]
第3轮结果:
11, 12, 22
是已排序部分。 - 寻找最小值:在
-
第4轮:
- 寻找最小值:在
[25, 64]
中,最小的元素是25
,无需交换。 - 数组保持不变:
[11, 12, 22, 25, 64]
第4轮结果:
11, 12, 22, 25
是已排序部分。 - 寻找最小值:在
-
第5轮:
- 剩下的最后一个元素
64
已经是排序好的,不需要再进行操作。
第5轮结果:数组已完全排序为
[11, 12, 22, 25, 64]
。 - 剩下的最后一个元素
最终结果
经过选择排序,数组 [64, 25, 12, 22, 11]
被排序为 [11, 12, 22, 25, 64]
。
选择排序总结:
选择排序通过不断选择未排序部分的最小元素,并将其放到已排序部分的末尾,逐步构建出有序数组。尽管选择排序的时间复杂度为 O(n²),它在小规模数据集或对性能要求不高的场景下具有一定的实用性。其简单易实现的特性使其成为学习排序算法的基础,同时也为理解更复杂的排序算法提供了良好的起点。
编程实现选择排序
- 我们需要找到未排序序列中的最小值,然后记录其index
- 然后对最小值与末尾值进行交换
#include <stdio.h>
// 选择排序函数(带调试信息)
void selectionSort(int arr[], int n) {
int i, j, minIdx, temp;
// 逐步将最小元素移到已排序部分
for (i = 0; i < n - 1; i++) {
minIdx = i; // 假设当前元素为最小值
printf("\n第 %d 轮:\n", i + 1);
printf("初始数组: ");
for (int k = 0; k < n; k++) {
printf("%d ", arr[k]);
}
printf("\n");
// 找到从 i 到 n-1 范围内的最小值
for (j = i + 1; j < n; j++) {
if (arr[j] < arr[minIdx]) {
minIdx = j; // 更新最小值的索引
}
}
printf("找到的最小值是 %d(在索引 %d)\n", arr[minIdx], minIdx);
// 交换最小值和当前位置的值
if (minIdx != i) {
temp = arr[minIdx];
arr[minIdx] = arr[i];
arr[i] = temp;
printf("交换 %d 和 %d\n", arr[i], arr[minIdx]);
} else {
printf("当前元素已是最小值,无需交换\n");
}
// 输出交换后的数组状态
printf("交换后的数组: ");
for (int k = 0; k < n; k++) {
printf("%d ", arr[k]);
}
printf("\n");
}
}
// 打印数组函数
void printArray(int arr[], int n) {
for (int i = 0; i < n; i++) {
printf("%d ", arr[i]);
}
printf("\n");
}
int main() {
int arr[] = {64, 25, 12, 22, 11};
int n = sizeof(arr) / sizeof(arr[0]);
// 输出排序前的数组
printf("排序前的数组: ");
printArray(arr, n);
// 调用选择排序函数
selectionSort(arr, n);
// 输出排序后的数组
printf("\n排序后的数组: ");
printArray(arr, n);
return 0;
}
总结
选择排序通过每轮选择未排序部分中的最小元素并将其放到已排序部分末尾的方式完成排序。虽然选择排序的时间复杂度较高,在处理大数据集时效率不佳,但由于它的结构简单、便于实现,仍然是学习排序算法的基础之一。选择排序的每次比较和交换步骤都非常清晰,是理解其他复杂排序算法的有力工具。对于小数据集或对性能要求不高的场景,选择排序依然可以提供有效的解决方案。