每天一个知识点,带你自学NOAI,加入我们吧~
前面学了用模块调用现成的工具。但有些东西光会调用不够——NOAI考试会考你排序算法的原理。这节课先手写一个最基础的排序,再学Python自带的排序工具。
为什么要学排序
想想生活中哪些地方需要排序:考试成绩从高到低排名、找最大值最小值、数据去重……很多算法的第一步就是先排序。
NOAI考试不只考你会不会用Python排序,还会考排序算法的原理。所以我们先手写一个最经典的排序算法——冒泡排序。
冒泡排序
冒泡排序的思路很简单:从头到尾,两两比较相邻的元素,如果前面的比后面大,就交换。一轮下来,最大的数就"浮"到了最后面。再跑一轮,第二大的也归位了。重复几轮,整个列表就排好了。
冒泡排序就像排队——每一轮从头到尾两两比较,高的往后站。跑完一轮,最高的就到了最后面。再跑一轮,第二高的也归位了。
完整代码:
nums = [64, 34, 25, 12, 22, 11, 90]n = len(nums)foriinrange(n - 1):forjinrange(n - 1 - i):ifnums[j] > nums[j + 1]:nums[j], nums[j + 1] = nums[j + 1], nums[j]print(nums) |
[11, 12, 22, 25, 34, 64, 90]
拆开看:
•外层循环for i in range(n - 1) — 总共跑 n-1 轮。7个数只需要6轮就能排好
•内层循环for j in range(n - 1 - i) — 每一轮两两比较相邻的数。因为每跑一轮,最后面就多一个已经排好的数,所以内层循环每轮可以少比一次
•nums[j], nums[j+1] = nums[j+1], nums[j] — 交换两个元素。这是第10课学过的元组解包,一行搞定交换
•if nums[j] > nums[j + 1] — 前面比后面大才交换,这样每轮最大的就"冒泡"到最后
用 sorted() 排序
手写冒泡排序是为了理解原理。实际写代码时,Python有现成的排序工具,一行搞定。
sorted() 接收一个列表,返回一个新的排好序的列表,原列表不变:
nums = [3, 1, 4, 1, 5, 9]result = sorted(nums)print(result) # 新列表,排好了print(nums) # 原列表,没变 |
[1, 1, 3, 4, 5, 9][3, 1, 4, 1, 5, 9]
想从大到小排?加一个参数 reverse=True:
nums = [3, 1, 4, 1, 5, 9]print(sorted(nums, reverse=True)) |
[9, 5, 4, 3, 1, 1]
用 .sort() 排序
列表还有一个方法 .sort(),它直接修改原列表,不会创建新列表,返回值是 None:
nums = [3, 1, 4, 1, 5, 9]nums.sort()print(nums) |
[1, 1, 3, 4, 5, 9]
对比一下:
•sorted(nums) — 返回新列表,原列表不动
•nums.sort() — 改原列表,返回 None
这两个的区别是NOAI常考的知识点,必须记牢。
自定义排序
有时候不是简单地比大小。比如有一组学生成绩,想按分数排序:
students = [("小明", 88), ("小红", 95), ("小刚", 72)]result = sorted(students, key=lambdax: x[1])print(result) |
[('小刚', 72), ('小明', 88), ('小红', 95)]
key=lambda x: x[1] 的意思是:排序时按每个元素的第1个位置(也就是分数)来比大小。lambda 是一种写简单函数的快捷方式,现在知道怎么用就行,后面会详细讲。
易错点
错误1搞混 sort() 和 sorted()
sort() 改原列表,返回 None。sorted() 不改原列表,返回新列表。最容易踩的坑:
nums = [3, 1, 2]result = nums.sort() # sort()返回None!print(result) |
None
列表确实排好了,但 result 拿到的是 None。想拿排好的结果,要么直接用 nums,要么用 sorted()。
错误2冒泡排序的范围搞错
内层循环是 range(n - 1 - i),不是 range(n - 1)。写成 range(n - 1) 也能排对,但每一轮都会去比较已经排好的元素,浪费时间。考试时写 range(n - 1 - i) 更规范。
动手试试
自己先想,想完了去香农平台上写代码跑一遍验证。
练习1:预测输出 下面这段代码运行后,屏幕上会输出什么?
提示:sorted() 返回新列表,sort() 改原列表。两个互不影响。 |
练习2:找bug 小明想把列表排好序后打印,但结果还是乱的。哪里出了问题?
提示:sorted() 不改原列表,返回的新列表去哪了? |
练习3:写代码 有一组学生成绩:
把他们按分数从高到低排序,然后逐行打印每个人的名字和分数。 提示:用 sorted() + key= + reverse=True,然后用 for 循环打印。 |
去平台上手写代码
排序是算法的基础,也是考试的重点。回顾一下:
•冒泡排序 — 两两比较、交换,手动实现排序
•sorted(列表) — 返回新的排好序的列表,原列表不变
•列表.sort() — 原地排序,直接改原列表
•reverse=True — 降序排列
•key= — 自定义排序规则
这篇文章讲的是香农NOAI学习平台"Python基础"模块的第十三课。平台上有更多的练习题,写完代码点运行,对不对立刻就知道。
香农NOAI学习平台地址:shannon.arpa.school微信扫码登录就能用,免费。找到「Python基础」→「排序」,从第一道题开始写。
下一篇讲查找——在一堆数据里快速找到你要的东西。学完线性查找和二分查找,Python基础就全部过完了。

