基数排序是将待排序的元素拆分为 $k$ 个关键字(比较两个元素时,先比较第一关键字,如果相同再比较第二关键字……),然后先对第 $k$ 关键字进行稳定排序,再对第 $k-1$ 关键字进行稳定排序,再对第 $k-2$ 关键字进行稳定排序……最后对第一关键字进行稳定排序,这样就完成了对整个待排序序列的稳定排序。
-基数排序的正确性可以自己感性理解一下,也可以参考 https://walkccc.github.io/CLRS/Chap08/8.3/#83-3 。
+基数排序的正确性可以自己感性理解一下,也可以参考 <https://walkccc.github.io/CLRS/Chap08/8.3/#83-3> 。
-一般来说,每个关键字的值域都不大,就可以使用 [计数排序](./counting-sort.md) 作为内层排序,复杂度为 $O(nk+\sum\limits_{i=1}^k w_i)$,其中 $w_i$ 为第 $i$ 关键字的值域大小。
+一般来说,每个关键字的值域都不大,就可以使用 [计数排序](./counting-sort.md) 作为内层排序,复杂度为 $O(nk+\sum\limits_{i=1}^k w_i)$ ,其中 $w_i$ 为第 $i$ 关键字的值域大小。
(如果关键字值域很大,就可以直接使用基于比较的 $O(nk\log n)$ 排序而无需使用基数排序了。)
5 & \qquad\text{sort }A\text{ into nondecreasing order by the }i\text{-th key stably}
\end{array}
$$
+
C++ 代码:
```cpp
int n, w[K], k, cnt[W];
-struct Element
-{
- int key[K];
- bool operator<(const Element& y) const // shows how two elements are compared
- {
- for (int i = 1; i <= k; ++i)
- {
- if (key[i] == y.key[i]) continue;
- return key[i] < y.key[i];
- }
- return false;
+struct Element {
+ int key[K];
+ bool operator<(const Element& y) const // shows how two elements are compared
+ {
+ for (int i = 1; i <= k; ++i) {
+ if (key[i] == y.key[i]) continue;
+ return key[i] < y.key[i];
}
+ return false;
+ }
} a[N], b[N];
-void counting_sort(int p)
-{
- memset(cnt, 0, sizeof(cnt));
- for (int i = 1; i <= n; ++i) ++cnt[a[i].key[p]];
- for (int i = 1; i <= w[p]; ++i) cnt[i] += cnt[i - 1];
- for (int i = 1; i <= n; ++i) b[cnt[a[i].key[p]]--] = a[i];
- memcpy(a, b, sizeof(a));
+void counting_sort(int p) {
+ memset(cnt, 0, sizeof(cnt));
+ for (int i = 1; i <= n; ++i) ++cnt[a[i].key[p]];
+ for (int i = 1; i <= w[p]; ++i) cnt[i] += cnt[i - 1];
+ for (int i = 1; i <= n; ++i) b[cnt[a[i].key[p]]--] = a[i];
+ memcpy(a, b, sizeof(a));
}
-void radix_sort()
-{
- for (int i = k; i >= 1; --i)
- {
- counting_sort(i);
- }
+void radix_sort() {
+ for (int i = k; i >= 1; --i) {
+ counting_sort(i);
+ }
}
```
-
```cpp
// a[0] .. a[n - 1] 为需要排序的数列
-std::sort(a, a + n); // 这句代码直接修改 a 数组里的元素顺序,使得现在它是从小到大排列的
-std::sort(a, a + n, cmp); // cmp 为自定义的比较函数
+std::sort(
+ a,
+ a + n); // 这句代码直接修改 a 数组里的元素顺序,使得现在它是从小到大排列的
+std::sort(a, a + n, cmp); // cmp 为自定义的比较函数
```
## nth_element
int a[1009], n = 10;
// ......
std::sort(a + 1, a + 1 + n); // 不重载,从小到大排序。
-std::sort(a + 1, a + 1 + n, greater<int>()); // 重载小于运算符为大于,从大到小排序。
+std::sort(a + 1, a + 1 + n,
+ greater<int>()); // 重载小于运算符为大于,从大到小排序。
```
```cpp
严格弱序的要求:
-1. $x \not< x$ (非自反性)
+1. $x \not< x$ (非自反性)
2. 若 $x < y$ ,则 $y \not< x$ (非对称性)
3. 若 $x < y, y < z$ ,则 $x < z$ (传递性)
4. 若 $x \not< y, y \not< x, y \not< z, z \not< y$ ,则 $x \not< z, z \not< x$ (不可比性的传递性)
- 使用 `<=` 来定义排序中的小于运算符。
- 在调用排序运算符时,读取外部数值可能会改变的数组。(常见于最短路算法)
-- 将多个数的最大最小值进行比较的结果作为排序运算符。(如,皇后游戏 / 加工生产调度 中的经典错误,可以参考文章 [浅谈邻项交换排序的应用以及需要注意的问题](https://ouuan.github.io/浅谈邻项交换排序的应用以及需要注意的问题/) )。
\ No newline at end of file
+- 将多个数的最大最小值进行比较的结果作为排序运算符。(如,皇后游戏/加工生产调度 中的经典错误,可以参考文章 [浅谈邻项交换排序的应用以及需要注意的问题](https://ouuan.github.io/浅谈邻项交换排序的应用以及需要注意的问题/) )。