选择排序的核心是每轮外层循环i精准定位未排序区极值下标并交换至目标位置i,内层j从i+1遍历至n,升序更新minIndex、降序更新maxIndex,循环结束后仅当极值不在i时才交换。
选择排序的核心不在“多比较”,而在“准定位”——每轮外层循环必须唯一确定一个极值的位置,并确保它被准确放到目标索引上。关键不是找得快,而是找得稳、放得对。
明确每轮的目标位置与极值方向
外层循环变量 i 不只是计数器,它直接对应本轮要固定的**目标位置**:升序时放最小值,降序时放最大值。该位置从左端开始逐轮右移。
- i = 0 → 把整个数组的极值(升序取最小,降序取最大)放到索引 0
- i = 1 → 在子数组 arr[1..n−1] 中找极值,放到索引 1
- 以此类推,直到 i = n−2(最后一轮只需比较最后两个元素)
内层扫描必须严格限定范围,避免越界或重扫
内层循环 j 的起始点必须是 i + 1,不能从 0 或 i 开始:
- 从 i 开始会重复比较已固定位置的元素,导致逻辑错误(如把已排好的最小值又拉回来)
- 从 0 开始则完全失去“未排序区”概念,变成无效遍历
- 终点始终为 n(C/Python 数组长度),不是 n−1 —— 因为 j 是用于比较的下标,需覆盖最后一个元素
极值索引的更新必须原子化且可验证
不能只记数值,必须记录下标 minIndex 或 maxIndex。初始化为 i,再在 j 循环中动态更新:
- 升序:if arr[j]
- 降序:if arr[j] > arr[maxIndex] → maxIndex = j
- 更新后不立即交换,等内层循环彻底结束再统一处理,避免中间状态干扰后续比较
交换前务必判断是否真需交换
若极值本就在目标位置(即 minIndex == i 或 maxIndex == i),跳过交换:
- 节省无谓赋值,提升缓存友好性
- 保持相同元素的相对顺序(稳定性的间接体现,虽选择排序本身不稳定)
- 避免对单元素子数组做无效操作(如 i = n−2 且只剩两个数时,若较大者已在左侧,不交换即完成)

















