考点频率 :★★★★☆(选择题常考,归并排序的复杂度与稳定性是重点,基数排序常考其适用场景)
难度 :⭐⭐⭐⭐(归并排序需理解分治与合并,基数排序需理解分配与收集过程)
建议:重点掌握归并排序的"分治+合并"思想及时间复杂度;重点掌握基数排序的LSD过程及适用场景
1️⃣ 为什么还有这两种排序?
前面我们学过了插入类(插入排序)、交换类(冒泡、快速)、选择类(简单选择、堆排序)。这些排序算法有一个共同特点:它们都基于"比较"------通过比较元素的大小来决定位置。
而归并排序和基数排序代表了两种完全不同的思路:
| 算法 | 核心策略 | 一句话概括 |
|---|---|---|
| 归并排序 | 分治:先分割成小块,排序后再合并 | "先分后合,分而治之" |
| 基数排序 | 不比较大小,按位分配 | "按位分配,逐位收集" |
打个比方 :归并排序像整理一份打乱的文件 ------先把文件分成两半,分别整理好,再把两半合并成一份有序的整体。基数排序像按电话号码排序------先按最后一位分到10个桶里,再按倒数第二位分......经过所有位数后自然就有序了,全程不需要比较大小。
2️⃣ 归并排序(Merge Sort)
2.1 核心思想
归并排序采用分治(Divide and Conquer) 策略:
- 分:将待排序序列从中间一分为二,递归地对左右两部分进行归并排序
- 治:当子序列长度为1时,递归返回
- 合:将两个已排序的子序列合并成一个有序序列
打个比方:你有一副打乱顺序的扑克牌。你把牌分成两堆,分别整理成有序的,然后再把两堆牌合并成一堆有序的牌。这个过程就像"分而治之"------先分后合。
2.2 合并两个有序数组(核心操作)
归并排序的核心操作是合并两个已经有序的子序列。
左子序列: [1, 3, 5, 7]
右子序列: [2, 4, 6, 8]
合并过程:
1. 比较1和2 → 取1
2. 比较3和2 → 取2
3. 比较3和4 → 取3
4. 比较5和4 → 取4
5. 比较5和6 → 取5
6. 比较7和6 → 取6
7. 比较7和8 → 取7
8. 取8
合并结果: [1, 2, 3, 4, 5, 6, 7, 8]
2.3 执行过程示例
对数组 [5, 3, 8, 1, 4, 7, 2, 6] 进行归并排序:
[5, 3, 8, 1, 4, 7, 2, 6]
/ \
[5, 3, 8, 1] [4, 7, 2, 6]
/ \ / \
[5, 3] [8, 1] [4, 7] [2, 6]
/ \ / \ / \ / \
[5] [3] [8] [1] [4] [7] [2] [6]
\ / \ / \ / \ /
[3, 5] [1, 8] [4, 7] [2, 6]
\ / \ /
[1, 3, 5, 8] [2, 4, 6, 7]
\ /
[1, 2, 3, 4, 5, 6, 7, 8]
2.4 复杂度与特点
| 情况 | 时间复杂度 | 说明 |
|---|---|---|
| 最好情况 | O(nlogn)O(n \log n)O(nlogn) | 与初始顺序无关 |
| 最坏情况 | O(nlogn)O(n \log n)O(nlogn) | 与初始顺序无关 |
| 平均情况 | O(nlogn)O(n \log n)O(nlogn) | 与初始顺序无关 |
空间复杂度 :O(n)O(n)O(n)(合并时需要额外的数组空间)
稳定性 :✅ 稳定(合并时相等元素保持原有顺序)
3️⃣ 基数排序(Radix Sort)
3.1 核心思想
基数排序不基于比较 ,而是基于分配和收集。它将整数按位数(个位、十位、百位......)进行多趟排序。
打个比方:你要按学号给同学排序。你不需要比较学号的大小,而是先按最后一位数字分到10个组里(分配),按顺序收集起来(收集);再按倒数第二位数字分组收集......经过所有位数后,学号自然就有序了。
两种实现方式:
| 方式 | 说明 | 软考重点 |
|---|---|---|
| 最高位优先(MSD) | 从最高位开始分配 | 较少考查 |
| 最低位优先(LSD) | 从最低位开始分配 | 软考重点 |
LSD的实现更简单,也是软考中最常考的方式。
3.2 基数排序的LSD过程
步骤:
- 确定最大数的位数 ddd
- 对 i=0i = 0i=0 到 d−1d-1d−1:
- 分配 :根据第 iii 位的数字(0-9),将元素放入对应的10个桶中
- 收集:按桶的顺序(0→1→2→...→9)依次取出元素
示例 :对 [329, 457, 657, 839, 436, 720, 355] 进行基数排序(LSD)
第1趟(按个位分配):
| 桶0 | 桶1 | 桶2 | 桶3 | 桶4 | 桶5 | 桶6 | 桶7 | 桶8 | 桶9 |
|---|---|---|---|---|---|---|---|---|---|
| 720 | --- | --- | --- | --- | 355 | 436 | 457,657 | --- | 329,839 |
收集后:[720, 355, 436, 457, 657, 329, 839]
第2趟(按十位分配):
| 桶0 | 桶1 | 桶2 | 桶3 | 桶4 | 桶5 | 桶6 | 桶7 | 桶8 | 桶9 |
|---|---|---|---|---|---|---|---|---|---|
| --- | --- | 329 | 436 | --- | 457,657 | --- | --- | --- | --- |
| 720 | --- | --- | --- | 839 | --- | --- | --- | --- | --- |
收集后:[720, 329, 436, 839, 355, 457, 657]
第3趟(按百位分配):
| 桶0 | 桶1 | 桶2 | 桶3 | 桶4 | 桶5 | 桶6 | 桶7 | 桶8 | 桶9 |
|---|---|---|---|---|---|---|---|---|---|
| --- | --- | --- | 329,355 | 436,457 | --- | 657 | 720 | --- | --- |
收集后:[329, 355, 436, 457, 657, 720, 839]
3.3 复杂度与特点
| 情况 | 时间复杂度 | 说明 |
|---|---|---|
| 最好情况 | O(d×(n+r))O(d \times (n + r))O(d×(n+r)) | ddd 为位数,rrr 为基数(通常为10) |
| 最坏情况 | O(d×(n+r))O(d \times (n + r))O(d×(n+r)) | 与初始顺序无关 |
| 平均情况 | O(d×(n+r))O(d \times (n + r))O(d×(n+r)) | 与初始顺序无关 |
空间复杂度 :O(n+r)O(n + r)O(n+r)(需要桶的空间)
稳定性 :✅ 稳定(分配收集不改变同值元素的顺序)
关键特点:
- 基数排序的复杂度与初始序列是否有序无关
- 适用于整数、字符串等固定位数的数据
- 当 ddd 较小时效率很高(如身份证号、学号)
4️⃣ 八大排序算法全景对比(必背总结表)
| 算法 | 最好 | 最坏 | 平均 | 空间 | 稳定性 | 是否原地 |
|---|---|---|---|---|---|---|
| 插入排序 | O(n)O(n)O(n) | O(n2)O(n^2)O(n2) | O(n2)O(n^2)O(n2) | O(1)O(1)O(1) | ✅ 稳定 | ✅ 是 |
| 冒泡排序 | O(n)O(n)O(n) | O(n2)O(n^2)O(n2) | O(n2)O(n^2)O(n2) | O(1)O(1)O(1) | ✅ 稳定 | ✅ 是 |
| 简单选择 | O(n2)O(n^2)O(n2) | O(n2)O(n^2)O(n2) | O(n2)O(n^2)O(n2) | O(1)O(1)O(1) | ❌ 不稳定 | ✅ 是 |
| 快速排序 | O(nlogn)O(n \log n)O(nlogn) | O(n2)O(n^2)O(n2) | O(nlogn)O(n \log n)O(nlogn) | O(logn)O(\log n)O(logn) | ❌ 不稳定 | ✅ 是 |
| 堆排序 | O(nlogn)O(n \log n)O(nlogn) | O(nlogn)O(n \log n)O(nlogn) | O(nlogn)O(n \log n)O(nlogn) | O(1)O(1)O(1) | ❌ 不稳定 | ✅ 是 |
| 归并排序 | O(nlogn)O(n \log n)O(nlogn) | O(nlogn)O(n \log n)O(nlogn) | O(nlogn)O(n \log n)O(nlogn) | O(n)O(n)O(n) | ✅ 稳定 | ❌ 否 |
| 希尔排序 | O(n1.3)O(n^{1.3})O(n1.3) | O(n2)O(n^2)O(n2) | O(nlogn)O(n \log n)O(nlogn)~O(n2)O(n^2)O(n2) | O(1)O(1)O(1) | ❌ 不稳定 | ✅ 是 |
| 基数排序 | O(d(n+r))O(d(n+r))O(d(n+r)) | O(d(n+r))O(d(n+r))O(d(n+r)) | O(d(n+r))O(d(n+r))O(d(n+r)) | O(n+r)O(n+r)O(n+r) | ✅ 稳定 | ❌ 否 |
5️⃣ 经典例题
例题1 (归并排序过程):对序列 [6, 2, 8, 1, 5, 3] 进行归并排序,写出第一次合并后的结果。
解析:
- 分:
[6, 2, 8]和[1, 5, 3] - 继续分:
[6] [2, 8]和[1] [5, 3] - 继续分:
[6] [2] [8]和[1] [5] [3] - 合并相邻:
[2, 6] [1, 8]和[1, 5] [3] - 再合并:
[1, 2, 6, 8]和[1, 3, 5] - 最终合并:
[1, 1, 2, 3, 5, 6, 8]
第一次合并后的结果是 [2, 6] [1, 8] [1, 5] [3]。
答案 :[2, 6, 1, 8, 1, 5, 3]
例题2(基数排序适用场景):以下哪种数据最适合用基数排序?
A. 100个随机浮点数
B. 10000个学生的学号(8位数字)
C. 10000个随机字符串(长度不等)
D. 100个结构体对象
解析 :基数排序适合固定长度 的数据(如学号、身份证号、IP地址)。A浮点数处理复杂;C长度不等需要特殊处理;D结构体需按特定关键字排序。B学号是固定8位数字,最适合基数排序。选 B。
例题3 (判断):归并排序的平均时间复杂度为 O(n2)O(n^2)O(n2)。( )
解析 :错误。归并排序的平均时间复杂度为 O(nlogn)O(n \log n)O(nlogn)。
6️⃣ 记忆口诀
归并排序分治精,先分后合两路行。
O(nlogn)O(n \log n)O(nlogn) 稳定排,空间 O(n)O(n)O(n) 要记清。
基数排序不比较,按位分配逐位收。
ddd 趟收集 n+rn+rn+r,固定长度最优解。
7️⃣ 小测验(评论区对答案)
对序列
[4, 2, 7, 1, 9, 5]进行归并排序,合并过程中最后一轮合并时,左右两个子序列分别是( )。A.
[2, 4, 7]和[1, 5, 9]B.
[1, 2, 4, 7]和[5, 9]C.
[2, 4, 7]和[1, 5, 9]D.
[1, 2, 4, 5, 7, 9]
🔔 本专栏日更,点击头像 → 专栏《软考中级高频考点》订阅,第一时间接收新内容
#软考中级 #软件设计师 #归并排序 #基数排序 #排序算法 #数据结构 #软考备考