V

算法可视化

ZHEN
分享到微博分享到 XGitHub 仓库个人主页
学习工具算法复杂度速查算法学习路径
数据结构数组链表栈队列树堆哈希表图字典树并查集LRU 缓存跳表线段树B+ 树布隆过滤器树状数组
经典排序算法冒泡排序鸡尾酒排序双调排序选择排序插入排序二分插入排序希尔排序归并排序自顶向下归并快速排序三路快排双轴快排堆排序计数排序基数排序桶排序
图算法Dijkstra 最短路Kruskal 最小生成树Prim 最小生成树Bellman-Ford 最短路拓扑排序Floyd 多源最短路强连通分量2-SAT最大流二分图匹配LCA 倍增欧拉路径
动态规划编辑距离0-1 背包完全背包最长公共子序列最长递增子序列硬币找零方案数石子合并旅行商 TSP树形 DP数位 DP换根 DP
回溯与搜索N 皇后子集生成全排列组合总和迷宫寻路岛屿数量单词搜索数独A* 寻路
字符串KMP 字符串匹配Rabin-KarpBoyer-MooreManacher后缀数组LCP / height 数组AC 自动机Z 函数
数学与数论埃氏筛线性筛欧几里得算法快速幂扩展欧几里得中国剩余定理欧拉函数米勒-拉宾FFTPollard's Rho
计算几何凸包旋转卡壳最近点对线段相交扫描线求交
查找二分查找二分边界旋转数组搜索二分答案三分查找

基数排序 Radix Sort

非比较排序 · 按位一轮轮排

什么是基数排序

计数排序适合小值域,可数字一大(比如三位数)桶就爆了。基数排序的巧思是按位处理:先只看个位把数分到 0~9 十个桶再收集,接着看十位、再百位……每一位都用一次稳定的分配收集。因为每轮都稳定,靠后处理的高位「盖过」低位,几轮下来整体就有序了——只用 10 个桶,就排好了任意位数的整数。

它怎么做

LSD(从最低位起):第 d 轮,按每个数的第 d 位数字(0~9)分配到 10 个桶,再按桶 0→9 顺序收集回数组,作为下一轮的输入。点「下一步」看 [42, 7, 25, 63, 18, 31, 56, 9]:桶轨显示当前位的 0~9 分布,先按个位收集成一个序列,再按十位收集——第二轮结束就完全有序。

42
7
25
63
18
31
56
9
0
0
0
1
0
2
0
3
0
4
0
5
0
6
0
7
0
8
0
9

第 1 轮:按个位把 8 个数分配到 0–9 共 10 个桶

1function radixSort(a: number[]): number[] {
2 const maxVal = Math.max(...a);
3 const passes = String(maxVal).length;
4 for (let d = 0; d < passes; d++) {
5 const buckets: number[][] = Array.from({ length: 10 }, () => []);
6 const div = 10 ** d;
7 for (const x of a) buckets[Math.floor(x / div) % 10].push(x);
8 let w = 0;
9 for (const bucket of buckets)
10 for (const x of bucket) a[w++] = x;
11 }
12 return a;
13}
n8
轮1/2
位个位
阶段开始
i-
w-
1 / 35

复杂度与适用

时间 O(d·(n + k))(d 位、每位 k=10 个桶)、额外空间 O(n + k)、稳定。当位数 d 远小于 log n 时,它比 O(n log n) 的比较排序更快——常用于定长整数、定长字符串、日期等键。前提是「每轮分配必须稳定」,否则低位的排序结果会被打乱。

每轮的桶 = 一次计数排序:基数排序本质是「对每一位做稳定计数排序」。
三种非比较排序:计数(桶=单个值)、基数(桶=一位数字 0-9,多轮)、桶排序(桶=一段值域)。

建议先看计数排序理解「稳定分配收集」,再回来体会基数怎么用它逐位攻克大值域;桶排序则是另一种分桶粒度。三页构成非比较线性排序的完整拼图。