排序算法如何实现升序/降序?数据“听话”指南¶
一、数据为什么要“听话”?——排序的意义¶
想象一下,你有一堆杂乱的扑克牌(比如[3, 1, 4, 2]),想快速找到“最小的牌”或者“最大的牌”,怎么办?直接翻找太麻烦了!这时候就需要排序算法——让数据像“听话的孩子”一样,按你想要的顺序排列(升序或降序)。
简单来说:
- 升序:从小到大排列(比如[1, 2, 3, 4]);
- 降序:从大到小排列(比如[4, 3, 2, 1]);
- 排序算法就是让数据“听话”的规则,不同算法让数据移动的方式不同,但最终都会排成你想要的顺序。
二、冒泡排序:像“气泡”一样让数据“上浮”或“下沉”¶
原理¶
冒泡排序就像水中的气泡:大的气泡会“上浮”(大的数往后排),小的气泡会“下沉”(小的数往前排)。每一轮都会把当前最大的数“冒泡”到末尾,直到所有数排好序。
升序实现(从小到大)¶
以数组[3, 1, 4, 2]为例,步骤如下:
1. 第一轮:从第一个数开始,比较相邻两个数,若前一个比后一个大,交换位置。
- 比较3和1:3>1 → 交换 → [1, 3, 4, 2]
- 比较3和4:3<4 → 不交换
- 比较4和2:4>2 → 交换 → [1, 3, 2, 4]
- 此时最大的数4已“冒泡”到末尾,数组变为[1, 3, 2, 4]
- 第二轮:忽略已排好的末尾数4,继续比较前3个数。
- 比较1和3:1<3 → 不交换
- 比较3和2:3>2 → 交换 → [1, 2, 3, 4]
- 此时次大的数3已“冒泡”到倒数第二位,数组排好序。
核心规则:升序时,只要前一个数 > 后一个数,就交换位置,让大数往后“冒”。
降序实现(从大到小)¶
只需调整交换条件:前一个数 < 后一个数时交换,让小数往后“沉”。
仍以[3, 1, 4, 2]为例:
1. 第一轮:
- 比较3和1:3>1 → 不交换(降序要大的在前)
- 比较3和4:3<4 → 交换 → [4, 1, 3, 2]
- 比较3和2:3>2 → 不交换
- 此时最小的数1已“沉”到倒数第二位,数组变为[4, 1, 3, 2]
- 第二轮:忽略末尾的3和2(已排好?不对,这里可能需要更仔细的步骤,正确逻辑是每轮确定当前最小的数在正确位置?)
修正:降序的每轮是找当前最小的数,让它“沉”到末尾。正确步骤:
- 第一轮:从第一个数开始,比较相邻数,若前一个 < 后一个交换(让小的数“沉”后)。- [3,1,4,2] → 比较3和1(3>1不交换)→ 比较1和4(1<4交换→[3,4,1,2])→ 比较1和2(1<2交换→[3,4,2,1])
- 此时最小的数1已“沉”到末尾,数组变为[3,4,2,1]
- 第二轮:忽略末尾1,比较前3个数,继续找最小的数“沉”到倒数第二位:
- [3,4,2,1] → 比较3和4(3<4交换→[4,3,2,1])→ 比较3和2(3>2不交换)
- 此时次小数2已“沉”到倒数第二位,数组变为[4,3,2,1]
核心规则:降序时,前一个数 < 后一个数就交换,让小数往后“沉”。
三、选择排序:像“选班长”一样固定位置¶
原理¶
选择排序就像“选最小的数当班长,放到第一个位置”“选第二小的当副班长,放到第二个位置”……直到所有数排好。
升序实现(从小到大)¶
以数组[3, 1, 4, 2]为例:
1. 找最小数:遍历数组,找到最小的数(1),和第一个位置的数(3)交换 → [1, 3, 4, 2]
2. 找次小数:从第二个位置开始遍历,找到最小的数(2),和第二个位置的数(3)交换 → [1, 2, 4, 3]
3. 找第三小数:从第三个位置开始遍历,找到最小的数(3),和第三个位置的数(4)交换 → [1, 2, 3, 4]
核心逻辑:每轮确定一个数的位置,升序时把当前最小的数放到“正确位置”。
降序实现(从大到小)¶
只需把“找最小数”改成“找最大数”,然后放到“正确位置”:
以数组[3, 1, 4, 2]为例:
1. 找最大数:遍历数组,找到最大的数(4),和第一个位置的数(3)交换 → [4, 1, 3, 2]
2. 找次大数:从第二个位置开始遍历,找到最大的数(3),和第二个位置的数(1)交换 → [4, 3, 1, 2]
3. 找第三大数:从第三个位置开始遍历,找到最大的数(2),和第三个位置的数(1)交换 → [4, 3, 2, 1]
核心规则:降序时,每轮找当前最大的数,放到“正确位置”(从左到右,从小到大排就是从右到左从大到小?对!)
四、插入排序:像“整理扑克牌”一样逐个插入¶
原理¶
插入排序就像打扑克牌时,每次摸一张新牌,把它插入到手中已有牌的正确位置。比如手里已有[1, 3],摸到2,就把2插入到1和3之间,变成[1, 2, 3]。
升序实现(从小到大)¶
以数组[3, 1, 4, 2]为例:
1. 初始已有牌:只有第一个数3,数组[3]
2. 插入第二个数1:比较1和已有牌3 → 1<3,插入到3前面 → [1, 3]
3. 插入第三个数4:4>3,直接放到末尾 → [1, 3, 4]
4. 插入第四个数2:比较2和4 → 2<4,插入到4前面;再比较2和3 → 2<3,插入到3前面 → [1, 2, 3, 4]
核心逻辑:把数组分成“已排序”和“未排序”两部分,每次从“未排序”中取一个数,插入到“已排序”的正确位置。
降序实现(从大到小)¶
只需把“插入到比自己大的数前面”改成“插入到比自己小的数前面”:
以数组[3, 1, 4, 2]为例:
1. 初始已有牌:[3]
2. 插入1:1<3,直接放到末尾 → [3, 1]
3. 插入4:4>3,插入到最前面 → [4, 3, 1]
4. 插入2:比较2和1 → 2>1,插入到1前面;比较2和3 → 2<3,插入到3后面 → [4, 3, 2, 1]
核心规则:降序时,新数插入到“已排序”中比自己小的数前面(即保持已排序部分从大到小)。
五、数据“听话”的关键:算法的“交换/插入规则”¶
| 算法 | 升序核心规则 | 降序核心规则 | 比喻(数据“听话”方式) |
|---|---|---|---|
| 冒泡排序 | 大的数往后“冒”(前>后交换) | 小的数往后“沉”(前<后交换) | 气泡从下往上浮(升)/下沉(降) |
| 选择排序 | 每轮选最小数放左边 | 每轮选最大数放左边 | 选最小的当“排头”,依次类推 |
| 插入排序 | 逐个插入到已排序部分的正确位置 | 逐个插入到已排序部分的正确位置(从大到小) | 整理扑克牌,新牌按大小插队 |
六、初学者小建议¶
- 先掌握基础算法:冒泡、选择、插入排序是入门“基本功”,理解它们的“移动逻辑”后,再学更复杂的算法(如快速排序、归并排序)会更轻松。
- 用例子“盯”数据:每学一个算法,用简单数组(比如[5,3,8,1])手动模拟步骤,看数据如何一步步被“指挥”到正确位置。
- 数据“听话”=算法逻辑清晰:不管升序还是降序,本质是让算法中的“比较规则”(>或<)决定数据的移动方向,记住规则就能让数据“乖乖听话”!
排序算法是编程的“基本功”,就像走路需要先学会迈腿、转弯一样。多动手写几个例子,数据自然就“听话”啦!