OSDN Git Service

update sort-intro, selection-sort, bubble-sort and insertion sort
authorouuan <y___o___u@126.com>
Sat, 24 Aug 2019 06:47:30 +0000 (14:47 +0800)
committerouuan <y___o___u@126.com>
Sat, 24 Aug 2019 06:47:30 +0000 (14:47 +0800)
docs/basic/bubble-sort.md
docs/basic/insertion-sort.md
docs/basic/selection-sort.md
docs/basic/sort-intro.md

index d1705c4..84bb7b8 100644 (file)
@@ -2,22 +2,44 @@
 
 以升序为例,冒泡排序每次检查相邻两个元素,如果前面的元素大于后面的元素,就将相邻两个元素交换。当没有相邻的元素需要交换时,排序就完成了。
 
-不难发现,我们最多需要扫描 $n$ 遍数组才能完成排序。
+经过 $i$ 次扫描后,数列的末尾 $i$ 项必然有序,因此最多需要扫描 $n$ 遍数组才能完成排序。
+
+在序列完全有序时,该算法只需遍历一遍数组,不用执行任何交换操作,时间复杂度为 $O(n)$ 。在最坏情况下,冒泡排序要执行 $\frac{(n-1)n}{2}$ 次交换操作,时间复杂度为 $O(n^2)$ 。在平均情况下,冒泡排序的时间复杂度也是 $O(n^2)$ 。
+
+伪代码:
+
+$$
+\begin{array}{ll}
+1 & \textbf{Input. } \text{An array } A \text{ consisting of }n\text{ elements.} \\
+2 & \textbf{Output. } A\text{ will be sorted in nondecreasing order stably.} \\
+3 & \textbf{Method. }  \\
+4 & flag\gets True\\
+5 & \textbf{while }flag\\
+6 & \qquad flag\gets False\\
+7 & \qquad\textbf{for }i\gets1\textbf{ to }n-1\\
+8 & \qquad\qquad\textbf{if }A[i]>A[i + 1]\\
+9 & \qquad\qquad\qquad flag\gets True\\
+10 & \qquad\qquad\qquad \text{Swap } A[i]\text{ and }A[i + 1]
+\end{array}
+$$
+
+C++ 代码:
 
 ```cpp
-void bubble_sort() {
-  for (int i = 1; i <= n; i++) {
-    bool flag = false;
-    for (int j = 1; j < n; j++)
-      if (a[j] > a[j + 1]) {
-        flag = true;
-        int t = a[j];
-        a[j] = a[j + 1];
-        a[j + 1] = t;
-      }
-    if (!flag) break;  //如果没有执行交换操作,说明数列已经有序
-  }
+void bubble_sort(int *a, int n) {
+    flag = true;
+    while (flag)
+    {
+        flag = false;
+        for (int i = 1; i < n; ++i)
+        {
+            if (a[i] > a[i + 1]) {
+                flag = true;
+                int t = a[i];
+                a[i] = a[i + 1];
+                a[i + 1] = t;
+            }
+        }
+    }
 }
-```
-
-在序列完全有序时,该算法只需遍历一遍数组,不用执行任何交换操作,时间复杂度为 $O(n)$ 。在最坏情况下,冒泡排序要执行 $\frac{(n-1)n}{2}$ 次交换操作,时间复杂度为 $O(n^2)$ 。在平均情况下,冒泡排序的时间复杂度也是 $O(n^2)$ 。
+```
\ No newline at end of file
index 9eb8599..efee428 100644 (file)
@@ -1,3 +1,40 @@
-插入排序依次处理待排序的记录,每个记录和之前处理过的序列中的记录进行比较,然后插入到其中适当的位置。
+插入排序将数列划分为“已排序的”和“未排序的”两部分,每次从“未排序的”元素中选择一个插入到“已排序的”元素中的正确位置。
 
-时间复杂度是 $O(n^2)$ 。
+插入排序的最坏情况时间复杂度和平均情况时间复杂度都为 $O(n^2)$,但其在数列几乎有序时效率很高。
+
+插入排序是一个稳定排序。
+
+伪代码:
+$$
+\begin{array}{ll}
+1 & \textbf{Input. } \text{An array } A \text{ consisting of }n\text{ elements.} \\
+2 & \textbf{Output. } A\text{ will be sorted in nondecreasing order stably.} \\
+3 & \textbf{Method. }  \\
+4 & \textbf{for } i\gets 2\textbf{ to }n\\
+5 & \qquad key\gets A[i]\\
+6 & \qquad j\gets i-1\\
+7 & \qquad\textbf{while }j>0\textbf{ and }A[j]>key\\
+8 & \qquad\qquad A[j + 1]\gets A[j]\\
+9 & \qquad\qquad j\gets j - 1\\
+10 & \qquad A[j + 1]\gets key
+\end{array}
+$$
+
+C++ 代码:
+
+```cpp
+void insertion_sort(int* a, int n)
+{
+       for (int i = 2; i <= n; ++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;
+    }
+}
+```
\ No newline at end of file
index 7761ce3..2a369e2 100644 (file)
@@ -1,3 +1,43 @@
-每次找出第 i 小的元素,将这个元素与数组第 i 个位置上的元素交换。
+每次找出第 $i$ 小的元素(也就是 $A_{i..n}$ 中最小的元素),将这个元素与数组第 $i$ 个位置上的元素交换。
 
 时间复杂度为 $O(n^2)$ 。
+
+由于 swap(交换两个元素)操作的存在,选择排序是一个不稳定排序。
+
+伪代码:
+
+$$
+\begin{array}{ll}
+1 & \textbf{Input. } \text{An array } A \text{ consisting of }n\text{ elements.} \\
+2 & \textbf{Output. } A\text{ will be sorted in nondecreasing order.} \\
+3 & \textbf{Method. }  \\
+4 & \textbf{for } i\gets 1\textbf{ to }n-1\\
+5 & \qquad ith\gets i\\
+6 & \qquad \textbf{for }j\gets i+1\textbf{ to }n\\
+7 & \qquad\qquad\textbf{if }A[j]<A[ith]\\
+8 & \qquad\qquad\qquad ith\gets j\\
+9 & \qquad \text{swap }A[i]\text{ and }A[ith]\\
+\end{array}
+$$
+
+C++ 代码:
+
+```cpp
+void selection_sort(int* a, int n)
+{
+    for (int i = 1; i < n; ++i)
+    {
+        int ith = i;
+        for (int j = i + 1; j <= n; ++j)
+        {
+            if (a[j] < a[ith])
+            {
+                ith = j;
+            }
+        }
+        int t = a[i];
+        a[i] = a[ith];
+        a[ith] = t;
+    }
+}
+```
\ No newline at end of file
index 40036f7..60c2866 100644 (file)
@@ -4,7 +4,7 @@
 
 稳定性是指相等的元素经过排序之后相对顺序是否发生了改变。
 
-基数排序、计数排序(桶排序)、插入排序、冒泡排序、归并排序是稳定排序。
+基数排序、计数排序、插入排序、冒泡排序、归并排序是稳定排序。
 
 选择排序、堆排序、快速排序不是稳定排序。
 
@@ -18,6 +18,6 @@
 
 基于比较的排序算法的时间复杂度下限是 $O(n\log n)$ 的。
 
-当然也有不是 $O(n\log n)$ 的,桶排序的时间复杂度是 $O(n)$ ,但是它是在「用空间换时间」,它的空间复杂度是 $O($ 所排序的最大数 $)$ 
+当然也有不是 $O(n\log n)$ 的,计数排序的时间复杂度是 $O(n+w)$,其中 $w$ 代表输入数据的值域大小 。
 
 当待排序的关键码序列基本有序时,插入排序最快。