ARTICLE · 1271653
Python练习(一):排序专题
只会 sort() 就完了?
Python 排序专题冒泡 · 选择 · key 排序
先想清楚,再看答案
懂原理,也要会优雅写法
这篇从手写冒泡讲到 key 自定义。
问题
输入 n 个整数,用冒泡排序升序排列后输出(自己实现,不用 sort)。
请输入 5 个整数:64 34 25 12 22
排序后:[12, 22, 25, 34, 64]
引导思考
先想清楚冒泡的三个要点(和 C 语言版完全一致,因为算法是通用的):
一轮做什么? 从头比较相邻元素,前大后小就交换。走完一轮,最大的必然到末尾;
总共几轮? n 个数需要 n-1 轮;
内层边界? 第 i 轮后末尾 i 个已排好,所以内层到 n-1-i。
Python 特有的便利:交换不用临时变量,a[j], a[j+1] = a[j+1], a[j] 一行搞定。这是元组赋值,右边先求值再分别赋给左边,非常优雅。
参考答案
# 读入:把一行输入拆成整数列表
a = list(map(int, input("请输入若干整数(空格分隔):").split()))
n = len(a)
# 冒泡排序:共 n-1 轮
for i in range(n - 1):
# 末尾已有 i 个排好,所以只比较到 n-1-i
for j in range(n - 1 - i):
if a[j] > a[j + 1]:
# Python 特有:元组赋值,一行完成交换,不需要临时变量
a[j], a[j + 1] = a[j + 1], a[j]
print("排序后:", a)
小结与易错点
range(n-1-i) 不含末尾,和 C 的 j < n-1-i 等价;
交换用元组赋值,是 Python 最优雅的语法之一;
复杂度 O(n²),但 Python 写起来比 C 短一大截。
问题
对一组整数完成三种排序:升序、降序、按绝对值升序。
原始数据:[-10, 3, -2, 8, -5]
升序: [-10, -5, -2, 3, 8]
降序: [8, 3, -2, -5, -10]
绝对值升序: [-2, 3, -5, 8, -10]
引导思考
Python 的 sorted() 有个极其好用的参数 key,想清楚它的含义:
key 是一个函数,它把每个元素“映射”成一个用来比较的值。比如 key=abs 表示“比较时按绝对值比,但返回的还是原元素”;
reverse=True 表示降序;
关键区别:list.sort() 是原地修改(返回 None),sorted() 是返回新列表(原列表不变)。
这就是新手最常踩的坑:a = a.sort() 会让 a 变成 None!记住 sort 原地改,sorted 返回新列表。
参考答案
nums = [-10, 3, -2, 8, -5]
print("原始数据:", nums)
# 1) 升序:sorted 返回新列表,原列表不变
print("升序:", sorted(nums))
# 2) 降序:reverse=True
print("降序:", sorted(nums, reverse=True))
# 3) 按绝对值升序:key=abs 表示"按绝对值比较"
# 注意返回的是原元素,不是绝对值
print("绝对值升序:", sorted(nums, key=abs))
# 4) sort() 是原地排序,返回 None
nums_copy = nums[:] # 先复制一份
result = nums_copy.sort()
print("sort 的返回值:", result) # None!
print("原地排序后:", nums_copy)
小结与易错点
a.sort() 返回 None,千万别写 a = a.sort();
key=abs 只影响比较依据,不改变返回的元素本身;
想按“字符串长度”“元组的第二个元素”排序,都靠 key,例如 key=lambda x: x[1]。
key 的威力:任何“按某种规则排序”的需求,都能用一个 lambda 塞进 key。这是 Python 排序最灵活的地方。
问题
有若干学生记录(姓名 + 成绩),要求按成绩降序排;成绩相同的按姓名升序。
1. 小红 92
2. 小刚 85
3. 小明 85
引导思考
多条件排序在 Python 里有个特别巧妙的解法:
key 返回一个元组:key=lambda s: (-s[1], s[0]);
为什么成绩前面加负号? 因为默认升序,而成绩要降序——取负号后“92 变成 -92”,升序排列时 -92 最小排最前,正好等价于成绩高的排前面;
元组比较是逐项比较:先比第一项(负成绩),相等再比第二项(姓名)。
这个“取负号实现降序”的技巧非常实用,比写复杂比较函数简洁得多。
参考答案
# 学生记录:每个是 (姓名, 成绩) 的元组
students = [("小明", 85), ("小红", 92), ("小刚", 85)]
# 多条件排序:
# -s[1] 表示成绩取负(实现降序),s[0] 是姓名(升序)
# 元组比较会先比第一项,相等再比第二项
ranked = sorted(students, key=lambda s: (-s[1], s[0]))
print("排名:")
for i, (name, score) in enumerate(ranked, 1):
print(f"{i}. {name} {score}")
小结与易错点
取负号是让数值型降序的最简做法;字符串没法取负,那时用 reverse=True 或分两步排;
元组作为 key 时,比较是逐项进行的,天然支持多条件;
enumerate(ranked, 1) 让编号从 1 开始。
写在最后
Python 排序的核心就两条:懂原理(会写冒泡) + 会偷懒(用 sorted 和 key)。真正写代码时当然用 sorted,但面试和打基础时,冒泡那几行必须能徒手写出来。
✦ 练习建议
用 key 实现“按字符串长度排序”“按列表中元素出现次数排序”,体会 key 的灵活性。
我是顾然c语言,热衷于把c语言讲成段子















































































