算法:选择排序(以排队为例)

news/2025/2/22 20:45:16

举个栗子🌰:体育课排队

假设体育老师要按身高从高到矮给10个同学排队(降序排序),老师会这样做:

  1. 第1轮:找全班最高的同学,让他站在第1个位置
  2. 第2轮:在剩下的9人中找最高的,站到第2个位置
  3. 第3轮:在剩下的8人中找最高的,站到第3个位置
    ......
    直到所有人排好队

代码对应的现实操作

①形参是数组名

void sort(int x[], int n) {
    int i, j, k, t;
    for (i=0; i<n-1; i++) {       // 老师指挥排第i个位置
        k = i;                    // 老师用手指着当前最左边同学:"假设你是现在最高的"
        for (j=i+1; j<n; j++)     // 从下一个同学开始比较
            if (x[j] > x[k])      // 发现更高的同学
                k = j;            // 老师立刻改指这个更高的同学:"你才是最高的!"
        if (k != i) {             // 如果最高同学不在当前位置
            t = x[i];             // 让最高同学和当前位置的同学
            x[i] = x[k];          // 交换位置(矮的去后面)
            x[k] = t;             
        }
    }
}

动画演示:数组 [5,3,8,1] 的排序过程

轮次当前操作数组状态变化
初始[5, 3, 8, 1]
第1轮找最大8(下标2),换到0位****,3,5,1
第2轮找剩余最大5(下标2),换到1位[8,5],3,1
第3轮找剩余最大3(下标2),换到2位[8,5,3,1]
结果[8,5,3,1]

关键比喻解释

  • 变量k:老师手里的激光笔,专门指着当前找到的最高同学
  • 外层循环i:老师正在安排第几个位置(从第1个到倒数第2个)
  • 内层循环j:老师挨个检查后面的同学有没有更高的
  • 交换操作:让更高的同学和当前位置的同学换位置

为什么叫选择排序?

因为每一轮都在 选择 当前未排序部分的最大值(就像老师选最高的同学),放到已排序部分的末尾。


常见疑问解答

Q1:为什么外层循环到n-1就停止?

因为排好前n-1个后,最后一个位置自然就确定了,不需要再处理。

Q2:k变量有什么用?

k像书签一样标记着当前找到的最大值位置,避免频繁交换。

Q3:时间复杂度为什么是O(n²)?

假设有n个元素:

  • 第1轮比较n-1次
  • 第2轮比较n-2次
  • ...
  • 总比较次数 = (n-1)+(n-2)+...+1 = n(n-1)/2 ≈ n²

②形参是指针变量 

终极比喻:排队游戏

假设你有一队学生 [4, 2, 7, 1](数字代表身高),你要按身高从高到低重新排队。选择排序的玩法是:


第1轮:选全场最高的当排头
  1. 你站在队伍最前面(位置0),喊:“谁比我高?出列!”
    • 第1个学生(4)自己先当排头。
    • 第2个学生(2)没他高 → 不动。
    • 第3个学生(7)更高 → 排头换成他!
    • 第4个学生(1)更矮 → 不动。
  2. 交换位置:把7和4的位置交换 → 队伍变成 [7, 2, 4, 1]

第2轮:在剩下的人里选最高的

现在前1个位置(7)已经固定,不管了。你站到第2个位置(位置1),喊:“剩下的人里谁比我高?”

  • 当前排头是位置1的2。
  • 位置2的4更高 → 排头换成他!
  • 位置3的1更矮 → 不动。
  • 交换位置:4和2交换 → 队伍变成 [7, 4, 2, 1]

第3轮:继续缩小范围

现在前2个位置(7,4)固定。你站到第3个位置(位置2),喊:“剩下的人里谁比我高?”

  • 当前位置2的值是2,剩下的只有位置3的1 → 没人更高。
  • 不用交换,保持不动。

代码对应关系

  • i:你当前站的位置(从0开始)。
  • k:临时记录的“最高者位置”。
  • j:用来遍历剩下的人,找更高的。
  • t:交换时的临时工具人(比如一张椅子,用来暂时放人)。

再拆解代码关键行

c复制代码

if (*(x + j) > *(x + k)) k = j;  // 发现更高的人,更新k

👉 等价于:
“如果第j个人的身高 > 当前记录的k位置的身高,就让k记住j的位置!”


终极总结

代码的每一轮都在做三件事:
1️⃣ 定位:确定当前要排的位置 i
2️⃣ 找人:在剩下的范围里找到最大值的下标 k
3️⃣ 交换:把最大值扔到 i 的位置。


http://www.niftyadmin.cn/n/5862744.html

相关文章

使用Hardhat实现ERC20 代币合约详解

ERC20 代币合约详解 &#x1f4b0; 1. 合约概览 // SPDX-License-Identifier: MIT pragma solidity ^0.8.20;import "openzeppelin/contracts/token/ERC20/ERC20.sol";contract MyToken is ERC20 {constructor() ERC20("MyToken", "MTK") {_min…

【进阶】redis篇

redis是什么 nosql not only sql(不仅仅是sql) 泛指非关系型数据库 一般把非关系型数据库称为nosql数据库. redis mongodb redis是一个nosql类型的数据库(非关系型数据库),数据在内存中以键值对形式存储. 读写速度快,也提供数据持久化方式. 一般最常用的场景就是把redis用…

基于机器学习的人脸识别方法探讨

机器学习在人脸识别领域的应用是计算机视觉中最成功的案例之一。通过机器学习算法,尤其是深度学习技术,人脸识别的准确率和效率得到了显著提升。以下是机器学习在人脸识别中的应用、关键技术、流程及挑战的详细说明。 1. 机器学习在人脸识别中的应用 (1) 人脸检测 任务:从…

第三章 STM32 IIC驱动

1、IIC的速度&#xff1a;标准模式100Kbit/s、快速模式下400Kbit/s、高速模式下3.4Mbit/s 2、理论上IIC地址是8位&#xff0c;其中1位广播地址&#xff0c;7位地址&#xff0c;2^7128&#xff0c;理论上IIC可以挂载128个器件。但IIC总线上可挂接的设备数量受总线的最大电容400p…

C++ Primer string流

欢迎阅读我的 【CPrimer】专栏 专栏简介&#xff1a;本专栏主要面向C初学者&#xff0c;解释C的一些基本概念和基础语言特性&#xff0c;涉及C标准库的用法&#xff0c;面向对象特性&#xff0c;泛型特性高级用法。通过使用标准库中定义的抽象设施&#xff0c;使你更加适应高级…

资本资产定价模型(CAPM, Capital Asset Pricing Model)通俗解析

现代资产定价理论&#xff1a;CAPM模型通俗解析 &#x1f4c9;&#x1f4ca;&#x1f4a1; 在金融领域&#xff0c;如何定价一个资产&#xff08;如股票、债券等&#xff09;是一个至关重要的问题。而 资本资产定价模型&#xff08;CAPM, Capital Asset Pricing Model&#xf…

leetcode_位运算 191.位1的个数

191. 位1的个数 给定一个正整数 n&#xff0c;编写一个函数&#xff0c;获取一个正整数的二进制形式并返回其二进制表达式中设置位 (set bit&#xff0c;指在某数的二进制表示中值为 1 的二进制位)的个数&#xff08;也被称为汉明重量&#xff09;。 1. 字符串 列表 class …

工业路由器和工业交换机,打造高效稳定的工业网络?

工业路由器和工业交换机各有千秋&#xff0c;但如何将它们完美结合&#xff0c;构建稳定高效的工业网络&#xff1f;答案就在这里&#xff01; 工业物联网&#xff08;IIoT&#xff09;是高效、稳定的工业网络成为智慧工厂、工业自动化和远程监控等场景的基础支撑。工业路由器…