一轮排序就是从头到尾扫过一遍列表,比较相邻的项,并在顺序不对时交换它们。题目可能要你写出一轮之后的列表、数交换次数,或解释某一行代码的作用。
本课属于搜索、排序与文件。请查看你所考年份的 Cambridge 课程大纲,确认排序算法要求到什么程度。追踪这项技能本身可以迁移,它建立在追踪线性搜索之上。
一轮里发生了什么?
取前两项。如果左边的更大,就交换。然后向右移一格,比较下一对。继续到最后一对。
较大的值不断被带向右边,就像气泡上升。所以,一轮之后,最大的值在最后一个位置。
怎样交换两个值?
交换需要第三个位置来存放一个值,因为直接赋值会把它覆盖掉:
Temp ← Data[I]
Data[I] ← Data[I + 1]
Data[I + 1] ← Temp
下面是对五项列表做一轮的伪代码:
Swapped ← FALSE
FOR I ← 1 TO 4
IF Data[I] > Data[I + 1] THEN
Temp ← Data[I]
Data[I] ← Data[I + 1]
Data[I + 1] ← Temp
Swapped ← TRUE
ENDIF
NEXT I
循环只到 4,因为最后一次比较是位置 4 与位置 5。
例题
Data = [6, 2, 9, 4, 1]。追踪第一轮。
| I | 比较的一对 | 顺序不对? | 之后的列表 | Swapped |
|---|---|---|---|---|
| 开始 | 6, 2, 9, 4, 1 | FALSE | ||
| 1 | 6 与 2 | 是,交换 | 2, 6, 9, 4, 1 | TRUE |
| 2 | 6 与 9 | 否 | 2, 6, 9, 4, 1 | TRUE |
| 3 | 9 与 4 | 是,交换 | 2, 6, 4, 9, 1 | TRUE |
| 4 | 9 与 1 | 是,交换 | 2, 6, 4, 1, 9 | TRUE |
一轮之后列表是 [2, 6, 4, 1, 9],共交换三次。最大的值 9 现在在位置 5,但列表还没排好,所以还需要再来一轮。
第二轮得到 [2, 4, 1, 6, 9],第三轮得到 [2, 1, 4, 6, 9],第四轮得到 [1, 2, 4, 6, 9]。第五轮没有交换,Swapped 保持 FALSE,排序停止。
要留意的错误
常见的失误是交换时不用临时变量:
Data[I] ← Data[I + 1]
Data[I + 1] ← Data[I]
设 Data = [6, 2],I = 1。第一行把 Data[1] 设为 2,得到 [2, 2]。第二行再复制 Data[1](现在是 2)到 Data[2]。结果是 [2, 2],6 丢失了。
改正方法是在覆盖之前先把第一个值存进 Temp。追踪交换时,把 Temp 的值单独写一列,丢失的值就看得见了。
自我检测
1. 在 [3, 1, 2] 上追踪一轮。之后的列表是什么?交换了几次?
Show answer
比较 3 和 1:交换,得到 1, 3, 2。比较 3 和 2:交换,得到 1, 2, 3。结果 [1, 2, 3],共 2 次交换。
2. 在 [4, 5, 6] 上做一轮后,Swapped 是 FALSE。这说明什么?
Show answer
没有任何一对顺序不对,所以列表已经排好,不需要再做一轮。
3. A = 4,B = 9。写出交换它们的三行,并给出最终的值。
Show answer
Temp ← A(Temp = 4),A ← B(A = 9),B ← Temp(B = 4)。最终:A = 9,B = 4。
接下来学什么
下一步,看存储的数据如何拆成几部分:读取记录而不弄乱字段边界。受限伪代码追踪训练器可以逐步运行一轮,让你把每个列表状态和自己的表对照。
如果你的答案里交换或标志仍然出现意外,我们的老师可以通过一对一线上计算机科学补习陪你理清。