OSDN Git Service

bucket-sort and counting-sort
authorouuan <y___o___u@126.com>
Sun, 25 Aug 2019 03:11:37 +0000 (11:11 +0800)
committerouuan <y___o___u@126.com>
Sun, 25 Aug 2019 03:11:37 +0000 (11:11 +0800)
docs/basic/bucket-sort.md
docs/basic/counting-sort.md [new file with mode: 0644]
mkdocs.yml

index ef617d8..c2f3fc1 100644 (file)
@@ -1,10 +1,49 @@
-计数排序也称桶排序,可以在 $O(n)$ 的时间复杂度内对数组进行排序,但是它的空间复杂度与需要排序的数组的值域相关
+桶排序适用于待排序数据值域较大但分布比较均匀的情况,是一个期望时间复杂度为 $O(n)$ 的排序算法
 
-但实际操作时,由于时空同阶,时间复杂度应为 $O(\max\left(n,U\right))$ ,其中 $U$ 代表数组元素的值域大小
+其大致思想是对值域进行分块,每块分别排序。由于每块元素不多,一般使用插入排序。如果使用稳定的内层排序,并且将元素插入桶中时不改变相对顺序,那么桶排序就是稳定的
 
-!!! warning "注"
-    注意区分 **基数排序** 与 **桶排序** 
+如果待排序数据是随机生成的,将值域平均分成 $n$ 块的期望时间复杂度是 $O(n)$,证明可以参考算法导论或 [维基百科](https://en.wikipedia.org/wiki/Bucket_sort)。
 
-算法流程就是记录每一个数出现了多少次,然后从小到大依次输出。
+C++ 代码:
+
+```cpp
+const int N = 100010;
+
+int n, w, a[N];
+vector<int> bucket[N];
+
+void insertion_sort(vector<int> A) {
+  for (int i = 1; i < A.size(); ++i) {
+    int key = A[i];
+    int j = i - 1;
+    while (j >= 0 && A[j] > key) {
+      A[j + 1] = A[j];
+      --j;
+    }
+    A[j + 1] = key;
+  }
+}
+
+void bucket_sort()
+{
+    int bucket_size = w / n + 1;
+    for (int i = 0; i < n; ++i)
+    {
+        bucket[i].clear();
+    }
+    for (int i = 1; i <= n; ++i)
+    {
+        bucket[a[i] / bucket_size].push_back(a[i]);
+    }
+    int p = 0;
+    for (int i = 0; i < n; ++i)
+    {
+        insertion_sort(bucket[i]);
+        for (int j = 0; j < bucket[i].size(); ++j)
+        {
+            a[++p] = bucket[i][j];
+        }
+    }
+}
+```
 
-一般考虑的是某一范围内的整数,但是计数排序也可以和 [离散化](/misc/discrete) 一起使用,来对浮点数、大整数进行排序。
diff --git a/docs/basic/counting-sort.md b/docs/basic/counting-sort.md
new file mode 100644 (file)
index 0000000..5a02c6f
--- /dev/null
@@ -0,0 +1,42 @@
+计数排序是一种复杂度为 $O(n+w)$ 的稳定排序,其中 $w$ 代表待排序数据的值域大小。
+
+计数排序分为三个步骤:
+
+1. 计算每个数出现了几次。
+2. 求出每个数出现次数的前缀和。
+3. 利用出现次数的前缀和,从右至左计算每个数的排名。
+
+伪代码:
+$$
+\begin{array}{ll}
+1 & \textbf{Input. } \text{An array } A \text{ consisting of }n\text{ positive integers no greater than } w. \\
+2 & \textbf{Output. } \text{Array }A\text{ after sorting in nondecreasing order stably.} \\
+3 & \textbf{Method. }  \\
+4 & \textbf{for }i\gets0\textbf{ to }w\\
+5 & \qquad cnt[i]\gets0\\
+6 & \textbf{for }i\gets1\textbf{ to }n\\
+7 & \qquad cnt[A[i]]\gets cnt[A[i]]+1\\
+8 & \textbf{for }i\gets1\textbf{ to }w\\
+9 & \qquad cnt[i]\gets cnt[i]+cnt[i-1]\\
+10 & \textbf{for }i\gets n\textbf{ downto }1\\
+11 & \qquad B[cnt[A[i]]]\gets A[i]\\
+12 & \qquad cnt[A[i]]\gets cnt[A[i]]-1\\
+13 & \textbf{return } B
+\end{array}
+$$
+C++ 代码:
+
+```cpp
+const int N = 100010;
+const int W = 100010;
+
+int n, w, a[N], cnt[W], b[N];
+
+void counting_sort()
+{
+    memset(cnt, 0, sizeof(cnt));
+    for (int i = 1; i <= n; ++i) ++cnt[a[i]];
+    for (int i = 1; i <= w; ++i) cnt[i] += cnt[i - 1];
+    for (int i = n; i >= 1; --i) b[cnt[a[i]]--] = a[i];
+}
+```
\ No newline at end of file
index fd83e11..9c038a3 100644 (file)
@@ -99,11 +99,12 @@ nav:
       - 选择排序: basic/selection-sort.md
       - 冒泡排序: basic/bubble-sort.md
       - 插入排序: basic/insertion-sort.md
-      - 计数排序: basic/bucket-sort.md
+      - 计数排序: basic/counting-sort.md
+      - 基数排序: basic/radix-sort.md
       - 快速排序: basic/quick-sort.md
       - 归并排序: basic/merge-sort.md
       - 堆排序: basic/heap-sort.md
-      - 基数排序: basic/radix-sort.md
+      - 桶排序: basic/bucket-sort.md
       - 希尔排序: basic/shell-sort.md
       - 排序相关 STL: basic/stl-sort.md
       - 排序应用: basic/use-of-sort.md