diff --git a/codes/cpp/chapter_sorting/selection_sort.cpp b/codes/cpp/chapter_sorting/selection_sort.cpp new file mode 100644 index 000000000..a5d2e8950 --- /dev/null +++ b/codes/cpp/chapter_sorting/selection_sort.cpp @@ -0,0 +1,35 @@ +/** + * File: selection_sort.cpp + * Created Time: 2023-05-23 + * Author: Krahets (krahets@163.com) + */ + +#include "../utils/common.hpp" + +/* 选择排序 */ +void selectionSort(vector &nums) { + int n = nums.size(); + // 外循环:未排序区间为 [i, n-1] + for (int i = 0; i < n - 1; i++) { + // 内循环:找到未排序区间 [i, n-1] 中的最小元素 + int k = i; + for (int j = i + 1; j < n; j++) { + if (nums[j] < nums[k]) { + k = j; // 更新最小元素 + } + } + // 将该最小元素与未排序区间的首个元素交换 + swap(nums[i], nums[k]); + } +} + +/* Driver Code */ +int main() { + vector nums = {4, 1, 3, 1, 5, 2}; + selectionSort(nums); + + cout << "选择排序完成后 nums = "; + printVector(nums); + + return 0; +} diff --git a/codes/java/chapter_sorting/selection_sort.java b/codes/java/chapter_sorting/selection_sort.java new file mode 100644 index 000000000..be20efe82 --- /dev/null +++ b/codes/java/chapter_sorting/selection_sort.java @@ -0,0 +1,36 @@ +/** + * File: selection_sort.java + * Created Time: 2023-05-23 + * Author: Krahets (krahets@163.com) + */ + +package chapter_sorting; + +import java.util.Arrays; + +public class selection_sort { + /* 选择排序 */ + public static void selectionSort(int[] nums) { + int n = nums.length; + // 外循环:未排序区间为 [i, n-1] + for (int i = 0; i < n - 1; i++) { + // 内循环:找到未排序区间 [i, n-1] 中的最小元素 + int k = i; + for (int j = i + 1; j < n; j++) { + if (nums[j] < nums[k]) { + k = j; // 更新最小元素 + } + } + // 将该最小元素与未排序区间的首个元素交换 + int temp = nums[i]; + nums[i] = nums[k]; + nums[k] = temp; + } + } + + public static void main(String[] args) { + int[] nums = { 4, 1, 3, 1, 5, 2 }; + selectionSort(nums); + System.out.println("选择排序完成后 nums = " + Arrays.toString(nums)); + } +} diff --git a/codes/python/chapter_sorting/selection_sort.py b/codes/python/chapter_sorting/selection_sort.py new file mode 100644 index 000000000..3f0b038fb --- /dev/null +++ b/codes/python/chapter_sorting/selection_sort.py @@ -0,0 +1,26 @@ +""" +File: selection_sort.py +Created Time: 2023-05-22 +Author: Krahets (krahets@163.com) +""" + + +def selection_sort(nums: list[int]): + """选择排序""" + n = len(nums) + # 外循环:未排序区间为 [i, n-1] + for i in range(n - 1): + # 内循环:找到未排序区间 [i, n-1] 中的最小元素 + k = i + for j in range(i + 1, n): + if nums[j] < nums[k]: + k = j # 更新最小元素 + # 将该最小元素与未排序区间的首个元素交换 + nums[i], nums[k] = nums[k], nums[i] + + +"""Driver Code""" +if __name__ == "__main__": + nums = [4, 1, 3, 1, 5, 2] + selection_sort(nums) + print("选择排序完成后 nums =", nums) diff --git a/docs/chapter_sorting/selection_sort.assets/selection_sort_step1.png b/docs/chapter_sorting/selection_sort.assets/selection_sort_step1.png new file mode 100644 index 000000000..f884b631c Binary files /dev/null and b/docs/chapter_sorting/selection_sort.assets/selection_sort_step1.png differ diff --git a/docs/chapter_sorting/selection_sort.assets/selection_sort_step10.png b/docs/chapter_sorting/selection_sort.assets/selection_sort_step10.png new file mode 100644 index 000000000..60dfe309a Binary files /dev/null and b/docs/chapter_sorting/selection_sort.assets/selection_sort_step10.png differ diff --git a/docs/chapter_sorting/selection_sort.assets/selection_sort_step11.png b/docs/chapter_sorting/selection_sort.assets/selection_sort_step11.png new file mode 100644 index 000000000..ebf8a1967 Binary files /dev/null and b/docs/chapter_sorting/selection_sort.assets/selection_sort_step11.png differ diff --git a/docs/chapter_sorting/selection_sort.assets/selection_sort_step2.png b/docs/chapter_sorting/selection_sort.assets/selection_sort_step2.png new file mode 100644 index 000000000..207e388de Binary files /dev/null and b/docs/chapter_sorting/selection_sort.assets/selection_sort_step2.png differ diff --git a/docs/chapter_sorting/selection_sort.assets/selection_sort_step3.png b/docs/chapter_sorting/selection_sort.assets/selection_sort_step3.png new file mode 100644 index 000000000..394d997f0 Binary files /dev/null and b/docs/chapter_sorting/selection_sort.assets/selection_sort_step3.png differ diff --git a/docs/chapter_sorting/selection_sort.assets/selection_sort_step4.png b/docs/chapter_sorting/selection_sort.assets/selection_sort_step4.png new file mode 100644 index 000000000..33c279237 Binary files /dev/null and b/docs/chapter_sorting/selection_sort.assets/selection_sort_step4.png differ diff --git a/docs/chapter_sorting/selection_sort.assets/selection_sort_step5.png b/docs/chapter_sorting/selection_sort.assets/selection_sort_step5.png new file mode 100644 index 000000000..867d3172f Binary files /dev/null and b/docs/chapter_sorting/selection_sort.assets/selection_sort_step5.png differ diff --git a/docs/chapter_sorting/selection_sort.assets/selection_sort_step6.png b/docs/chapter_sorting/selection_sort.assets/selection_sort_step6.png new file mode 100644 index 000000000..0f18e5d55 Binary files /dev/null and b/docs/chapter_sorting/selection_sort.assets/selection_sort_step6.png differ diff --git a/docs/chapter_sorting/selection_sort.assets/selection_sort_step7.png b/docs/chapter_sorting/selection_sort.assets/selection_sort_step7.png new file mode 100644 index 000000000..49a93b5e1 Binary files /dev/null and b/docs/chapter_sorting/selection_sort.assets/selection_sort_step7.png differ diff --git a/docs/chapter_sorting/selection_sort.assets/selection_sort_step8.png b/docs/chapter_sorting/selection_sort.assets/selection_sort_step8.png new file mode 100644 index 000000000..0fdac8f30 Binary files /dev/null and b/docs/chapter_sorting/selection_sort.assets/selection_sort_step8.png differ diff --git a/docs/chapter_sorting/selection_sort.assets/selection_sort_step9.png b/docs/chapter_sorting/selection_sort.assets/selection_sort_step9.png new file mode 100644 index 000000000..88d145520 Binary files /dev/null and b/docs/chapter_sorting/selection_sort.assets/selection_sort_step9.png differ diff --git a/docs/chapter_sorting/selection_sort.assets/selection_sort_unstable.png b/docs/chapter_sorting/selection_sort.assets/selection_sort_unstable.png new file mode 100644 index 000000000..2cbe2275f Binary files /dev/null and b/docs/chapter_sorting/selection_sort.assets/selection_sort_unstable.png differ diff --git a/docs/chapter_sorting/selection_sort.md b/docs/chapter_sorting/selection_sort.md new file mode 100644 index 000000000..2abb07eb5 --- /dev/null +++ b/docs/chapter_sorting/selection_sort.md @@ -0,0 +1,112 @@ +# 选择排序 + +「选择排序 Insertion Sort」的工作原理非常直接:开启一个循环,每轮从未排序区间选择最小的元素,将其放到已排序区间的末尾。完整步骤如下: + +1. 初始状态下,所有元素未排序,即未排序(索引)区间为 $[0, n-1]$ 。 +2. 选取区间 $[0, n-1]$ 中的最小元素,将其与索引 $0$ 处元素交换。完成后,数组前 1 个元素已排序。 +3. 选取区间 $[1, n-1]$ 中的最小元素,将其与索引 $1$ 处元素交换。完成后,数组前 2 个元素已排序。 +4. 以此类推。经过 $n - 1$ 轮选择与交换后,数组前 $n - 1$ 个元素已排序。 +5. 仅剩的一个元素必定是最大元素,无需排序,因此数组排序完成。 + +=== "<1>" + ![选择排序步骤](selection_sort.assets/selection_sort_step1.png) + +=== "<2>" + ![selection_sort_step2](selection_sort.assets/selection_sort_step2.png) + +=== "<3>" + ![selection_sort_step3](selection_sort.assets/selection_sort_step3.png) + +=== "<4>" + ![selection_sort_step4](selection_sort.assets/selection_sort_step4.png) + +=== "<5>" + ![selection_sort_step5](selection_sort.assets/selection_sort_step5.png) + +=== "<6>" + ![selection_sort_step6](selection_sort.assets/selection_sort_step6.png) + +=== "<7>" + ![selection_sort_step7](selection_sort.assets/selection_sort_step7.png) + +=== "<8>" + ![selection_sort_step8](selection_sort.assets/selection_sort_step8.png) + +=== "<9>" + ![selection_sort_step9](selection_sort.assets/selection_sort_step9.png) + +=== "<10>" + ![selection_sort_step10](selection_sort.assets/selection_sort_step10.png) + +=== "<11>" + ![selection_sort_step11](selection_sort.assets/selection_sort_step11.png) + +在代码中,我们用 $k$ 来记录未排序区间内的最小元素。 + +=== "Java" + + ```java title="selection_sort.java" + [class]{selection_sort}-[func]{selectionSort} + ``` + +=== "C++" + + ```cpp title="selection_sort.cpp" + [class]{}-[func]{selectionSort} + ``` + +=== "Python" + + ```python title="selection_sort.py" + [class]{}-[func]{selection_sort} + ``` + +=== "Go" + + ```go title="selection_sort.go" + [class]{}-[func]{selectionSort} + ``` + +=== "JavaScript" + + ```javascript title="selection_sort.js" + [class]{}-[func]{selectionSort} + ``` + +=== "TypeScript" + + ```typescript title="selection_sort.ts" + [class]{}-[func]{selectionSort} + ``` + +=== "C" + + ```c title="selection_sort.c" + [class]{}-[func]{selectionSort} + ``` + +=== "C#" + + ```csharp title="selection_sort.cs" + [class]{selection_sort}-[func]{selectionSort} + ``` + +=== "Swift" + + ```swift title="selection_sort.swift" + [class]{}-[func]{selectionSort} + ``` + +=== "Zig" + + ```zig title="selection_sort.zig" + [class]{}-[func]{selectionSort} + ``` + +## 算法特性 + +- **时间复杂度为 $O(n^2)$ 、非自适应排序**:共有 $n - 1$ 轮外循环,分别包含 $n$ , $n - 1$ , $\cdots$ , $2$ , $2$ 轮内循环,求和为 $\frac{(n - 1)(n + 2)}{2}$ 。 +- **空间复杂度 $O(1)$ 、原地排序**:指针 $i$ , $j$ 使用常数大小的额外空间。 +- **非稳定排序**:在交换元素时,有可能将 `nums[i]` 交换至其相等元素的右边,导致两者的相对顺序发生改变。 + +![选择排序非稳定示例](selection_sort.assets/selection_sort_step11.png) diff --git a/mkdocs.yml b/mkdocs.yml index d0fc50e9b..6e49ea6c0 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -181,14 +181,15 @@ nav: - 10.5.   小结: chapter_searching/summary.md - 11.     排序算法: - 11.1.   排序算法: chapter_sorting/sorting_algorithm.md - - 11.2.   冒泡排序: chapter_sorting/bubble_sort.md - - 11.3.   插入排序: chapter_sorting/insertion_sort.md - - 11.4.   快速排序: chapter_sorting/quick_sort.md - - 11.5.   归并排序: chapter_sorting/merge_sort.md - - 11.6.   桶排序: chapter_sorting/bucket_sort.md - - 11.7.   计数排序: chapter_sorting/counting_sort.md - - 11.8.   基数排序: chapter_sorting/radix_sort.md - - 11.9.   小结: chapter_sorting/summary.md + - 11.2.   选择排序: chapter_sorting/selection_sort.md + - 11.3.   冒泡排序: chapter_sorting/bubble_sort.md + - 11.4.   插入排序: chapter_sorting/insertion_sort.md + - 11.5.   快速排序: chapter_sorting/quick_sort.md + - 11.6.   归并排序: chapter_sorting/merge_sort.md + - 11.7.   桶排序: chapter_sorting/bucket_sort.md + - 11.8.   计数排序: chapter_sorting/counting_sort.md + - 11.9.   基数排序: chapter_sorting/radix_sort.md + - 11.10.   小结: chapter_sorting/summary.md - 12.     回溯算法: - 12.1.   回溯算法(New): chapter_backtracking/backtracking_algorithm.md - 12.2.   全排列问题(New): chapter_backtracking/permutations_problem.md