算法概述
选择排序 是一种简单直观的排序算法,它的基本思想是:每次从待排序的数据元素中选出 最小(或最大) 的一个元素,存放在序列的起始位置,然后,再从剩余未排序元素中继续寻找最小(大)元素,然后放到已排序序列的末尾。以此类推,直到全部待排序的数据元素排完。
选择排序是学习排序算法的入门级算法,虽然时间复杂度较高,但它的实现简单、逻辑清晰,非常适合初学者理解排序算法的基本思想。在实际应用中,选择排序适用于数据量较小(n < 100)的场景,或者内存空间受限的环境,因为它不需要额外的存储空间。
核心思路和原理
选择排序的核心思想可以概括为 " 逐个挑选,放到对应位置 "。算法将待排序数组分为两个区域:已排序区和未排序区。初始时,已排序区为空,未排序区包含所有元素。
算法执行步骤:
- 外层循环:从第一个元素开始,遍历到倒数第二个元素(共进行 n-1 轮)
- 假设最小值:假设当前元素是最小值,记录其索引
- 内层循环:从当前位置的下一个元素开始,遍历到数组末尾,寻找真正的最小值
- 更新最小值:如果找到更小的元素,更新最小值索引
- 交换位置:将找到的最小值与当前位置的元素交换
- 重复执行:直到所有元素都排好序
选择排序的特点是:无论输入数据的初始状态如何,比较次数都是固定的 n(n-1)/2 次,交换次数最多为 n-1 次。相比冒泡排序,选择排序的交换次数更少,因此在小规模数据排序时效率更高。
算法流程图
流程图说明:
- 外层循环控制排序轮数(i 从 0 到 n-2)
- 内层循环在未排序部分查找最小值位置
- 找到最小值后,如果不在当前位置则交换
- 重复执行直到所有元素排序完成
详细示例演示
让我们通过一个具体例子来理解选择排序的执行过程。假设我们要对数组 [64, 25, 12, 22, 11] 进行升序排序:
初始状态: [64, 25, 12, 22, 11]
第 1 轮排序:
- 在未排序部分 [64, 25, 12, 22, 11] 中找到最小值 11(索引 4)
- 将 11 与第一个元素 64 交换
- 结果: [11, 25, 12, 22, 64]
- 已排序区:[11],未排序区:[25, 12, 22, 64]
第 2 轮排序:
- 在未排序部分 [25, 12, 22, 64] 中找到最小值 12(索引 2)
- 将 12 与第二个元素 25 交换
- 结果: [11, 12, 25, 22, 64]
- 已排序区:[11, 12],未排序区:[25, 22, 64]
第 3 轮排序:
- 在未排序部分 [25, 22, 64] 中找到最小值 22(索引 3)
- 将 22 与第三个元素 25 交换
- 结果: [11, 12, 22, 25, 64]
- 已排序区:[11, 12, 22],未排序区:[25, 64]
第 4 轮排序:
- 在未排序部分 [25, 64] 中找到最小值 25(索引 3)
- 25 已经在正确位置,无需交换
最终结果: [11, 12, 22, 25, 64]
Python 代码实现
def selection_sort(arr):
n = len(arr)
# 外层循环:控制排序轮数(n-1轮)
for i in range(n - 1):
# 假设当前元素是最小值
min_index = i
# 内层循环:在未排序部分查找真正的最小值
for j in range(i + 1, n):
if arr[j] < arr[min_index]:
min_index = j
# 如果最小值不在当前位置,则交换
if min_index != i:
arr[i], arr[min_index] = arr[min_index], arr[i]
return arr
if __name__ == "__main__":
# 测试用例
test_array = [64, 25, 12, 22, 11]
print("排序前:", test_array)
# 调用选择排序
sorted_array = selection_sort(test_array)
print("排序后:", sorted_array)
# 输出结果:
# 排序前: [64, 25, 12, 22, 11]
# 排序后: [11, 12, 22, 25, 64]
代码说明:
- 外层循环从 0 到 n-2,共进行 n-1 轮排序
- 内层循环从 i+1 到 n-1,在未排序部分查找最小值
- 每次找到最小值后,如果不在当前位置则交换
- 算法是原地排序,不需要额外空间