From e8dc4736a2300e5a2a9a9ae864dbbf570a86b27b Mon Sep 17 00:00:00 2001 From: Yudong Jin Date: Thu, 10 Jul 2025 06:32:25 +0800 Subject: [PATCH] Bug fixes and improvements. (#1780) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Fix the "尾递归优化" to "递归深度优化" in quick_sort. * Update landing pages. * Sync zh and zh-hant versions. * Sync zh and zh-hant versions. --- codes/c/chapter_sorting/quick_sort.c | 8 +-- codes/cpp/chapter_sorting/quick_sort.cpp | 8 +-- codes/csharp/chapter_sorting/quick_sort.cs | 8 +-- codes/dart/chapter_sorting/quick_sort.dart | 8 +-- codes/go/chapter_sorting/quick_sort.go | 4 +- codes/go/chapter_sorting/quick_sort_test.go | 4 +- codes/java/chapter_sorting/quick_sort.java | 8 +-- .../javascript/chapter_sorting/quick_sort.js | 8 +-- codes/kotlin/chapter_sorting/quick_sort.kt | 6 +- codes/python/chapter_sorting/quick_sort.py | 8 +-- codes/ruby/chapter_sorting/quick_sort.rb | 8 +-- codes/rust/chapter_sorting/quick_sort.rs | 8 +-- codes/swift/chapter_sorting/quick_sort.swift | 6 +- .../typescript/chapter_sorting/quick_sort.ts | 8 +-- codes/zig/chapter_sorting/quick_sort.zig | 8 +-- docs/chapter_sorting/quick_sort.md | 2 +- docs/chapter_sorting/summary.md | 8 +-- docs/index.html | 2 +- en/docs/index.html | 2 +- zh-hant/codes/c/chapter_sorting/quick_sort.c | 8 +-- .../codes/cpp/chapter_sorting/quick_sort.cpp | 8 +-- .../csharp/chapter_sorting/quick_sort.cs | 8 +-- .../dart/chapter_sorting/quick_sort.dart | 8 +-- .../codes/go/chapter_sorting/quick_sort.go | 4 +- .../go/chapter_sorting/quick_sort_test.go | 4 +- .../java/chapter_sorting/quick_sort.java | 8 +-- .../javascript/chapter_sorting/quick_sort.js | 8 +-- .../kotlin/chapter_sorting/quick_sort.kt | 6 +- .../python/chapter_sorting/quick_sort.py | 8 +-- .../codes/ruby/chapter_sorting/quick_sort.rb | 8 +-- zh-hant/codes/rust/chapter_heap/heap.rs | 56 +++++++++++-------- .../codes/rust/chapter_sorting/quick_sort.rs | 8 +-- .../swift/chapter_sorting/quick_sort.swift | 6 +- .../typescript/chapter_sorting/quick_sort.ts | 8 +-- .../codes/zig/chapter_sorting/quick_sort.zig | 8 +-- .../docs/chapter_array_and_linkedlist/list.md | 2 +- .../subset_sum_problem.md | 2 +- .../character_encoding.md | 30 +++++----- .../docs/chapter_data_structure/summary.md | 2 +- .../max_product_cutting_problem.md | 4 +- zh-hant/docs/chapter_sorting/quick_sort.md | 2 +- zh-hant/docs/chapter_sorting/summary.md | 8 +-- zh-hant/docs/index.html | 2 +- 43 files changed, 173 insertions(+), 165 deletions(-) diff --git a/codes/c/chapter_sorting/quick_sort.c b/codes/c/chapter_sorting/quick_sort.c index 6d3986ee5..a8a2ad0a9 100644 --- a/codes/c/chapter_sorting/quick_sort.c +++ b/codes/c/chapter_sorting/quick_sort.c @@ -89,9 +89,9 @@ void quickSortMedian(int nums[], int left, int right) { quickSortMedian(nums, pivot + 1, right); } -// 以下为尾递归优化的快速排序 +// 以下为递归深度优化的快速排序 -/* 快速排序(尾递归优化) */ +/* 快速排序(递归深度优化) */ void quickSortTailCall(int nums[], int left, int right) { // 子数组长度为 1 时终止 while (left < right) { @@ -127,10 +127,10 @@ int main() { printf("快速排序(中位基准数优化)完成后 nums = "); printArray(nums1, size); - /* 快速排序(尾递归优化) */ + /* 快速排序(递归深度优化) */ int nums2[] = {2, 4, 1, 0, 3, 5}; quickSortTailCall(nums2, 0, size - 1); - printf("快速排序(尾递归优化)完成后 nums = "); + printf("快速排序(递归深度优化)完成后 nums = "); printArray(nums1, size); return 0; diff --git a/codes/cpp/chapter_sorting/quick_sort.cpp b/codes/cpp/chapter_sorting/quick_sort.cpp index 90d677542..91b927a6e 100644 --- a/codes/cpp/chapter_sorting/quick_sort.cpp +++ b/codes/cpp/chapter_sorting/quick_sort.cpp @@ -84,7 +84,7 @@ class QuickSortMedian { } }; -/* 快速排序类(尾递归优化) */ +/* 快速排序类(递归深度优化) */ class QuickSortTailCall { private: /* 哨兵划分 */ @@ -103,7 +103,7 @@ class QuickSortTailCall { } public: - /* 快速排序(尾递归优化) */ + /* 快速排序(递归深度优化) */ static void quickSort(vector &nums, int left, int right) { // 子数组长度为 1 时终止 while (left < right) { @@ -135,10 +135,10 @@ int main() { cout << "快速排序(中位基准数优化)完成后 nums = "; printVector(nums1); - /* 快速排序(尾递归优化) */ + /* 快速排序(递归深度优化) */ vector nums2 = {2, 4, 1, 0, 3, 5}; QuickSortTailCall::quickSort(nums2, 0, nums2.size() - 1); - cout << "快速排序(尾递归优化)完成后 nums = "; + cout << "快速排序(递归深度优化)完成后 nums = "; printVector(nums2); return 0; diff --git a/codes/csharp/chapter_sorting/quick_sort.cs b/codes/csharp/chapter_sorting/quick_sort.cs index 055c553b7..4307bc60c 100644 --- a/codes/csharp/chapter_sorting/quick_sort.cs +++ b/codes/csharp/chapter_sorting/quick_sort.cs @@ -89,7 +89,7 @@ class QuickSortMedian { } } -/* 快速排序类(尾递归优化) */ +/* 快速排序类(递归深度优化) */ class QuickSortTailCall { /* 元素交换 */ static void Swap(int[] nums, int i, int j) { @@ -111,7 +111,7 @@ class QuickSortTailCall { return i; // 返回基准数的索引 } - /* 快速排序(尾递归优化) */ + /* 快速排序(递归深度优化) */ public static void QuickSort(int[] nums, int left, int right) { // 子数组长度为 1 时终止 while (left < right) { @@ -142,9 +142,9 @@ public class quick_sort { QuickSortMedian.QuickSort(nums1, 0, nums1.Length - 1); Console.WriteLine("快速排序(中位基准数优化)完成后 nums1 = " + string.Join(",", nums1)); - /* 快速排序(尾递归优化) */ + /* 快速排序(递归深度优化) */ int[] nums2 = [2, 4, 1, 0, 3, 5]; QuickSortTailCall.QuickSort(nums2, 0, nums2.Length - 1); - Console.WriteLine("快速排序(尾递归优化)完成后 nums2 = " + string.Join(",", nums2)); + Console.WriteLine("快速排序(递归深度优化)完成后 nums2 = " + string.Join(",", nums2)); } } diff --git a/codes/dart/chapter_sorting/quick_sort.dart b/codes/dart/chapter_sorting/quick_sort.dart index 5d635bf8a..a34ca096b 100644 --- a/codes/dart/chapter_sorting/quick_sort.dart +++ b/codes/dart/chapter_sorting/quick_sort.dart @@ -86,7 +86,7 @@ class QuickSortMedian { } } -/* 快速排序类(尾递归优化) */ +/* 快速排序类(递归深度优化) */ class QuickSortTailCall { /* 元素交换 */ static void _swap(List nums, int i, int j) { @@ -108,7 +108,7 @@ class QuickSortTailCall { return i; // 返回基准数的索引 } - /* 快速排序(尾递归优化) */ + /* 快速排序(递归深度优化) */ static void quickSort(List nums, int left, int right) { // 子数组长度为 1 时终止 while (left < right) { @@ -138,8 +138,8 @@ void main() { QuickSortMedian.quickSort(nums1, 0, nums1.length - 1); print("快速排序(中位基准数优化)完成后 nums1 = $nums1"); - /* 快速排序(尾递归优化) */ + /* 快速排序(递归深度优化) */ List nums2 = [2, 4, 1, 0, 3, 5]; QuickSortTailCall.quickSort(nums2, 0, nums2.length - 1); - print("快速排序(尾递归优化)完成后 nums2 = $nums2"); + print("快速排序(递归深度优化)完成后 nums2 = $nums2"); } diff --git a/codes/go/chapter_sorting/quick_sort.go b/codes/go/chapter_sorting/quick_sort.go index f5cbf1524..98dfbe060 100644 --- a/codes/go/chapter_sorting/quick_sort.go +++ b/codes/go/chapter_sorting/quick_sort.go @@ -10,7 +10,7 @@ type quickSort struct{} // 快速排序(中位基准数优化) type quickSortMedian struct{} -// 快速排序(尾递归优化) +// 快速排序(递归深度优化) type quickSortTailCall struct{} /* 哨兵划分 */ @@ -112,7 +112,7 @@ func (q *quickSortTailCall) partition(nums []int, left, right int) int { return i // 返回基准数的索引 } -/* 快速排序(尾递归优化)*/ +/* 快速排序(递归深度优化)*/ func (q *quickSortTailCall) quickSort(nums []int, left, right int) { // 子数组长度为 1 时终止 for left < right { diff --git a/codes/go/chapter_sorting/quick_sort_test.go b/codes/go/chapter_sorting/quick_sort_test.go index d780663e1..eb6e3ba75 100644 --- a/codes/go/chapter_sorting/quick_sort_test.go +++ b/codes/go/chapter_sorting/quick_sort_test.go @@ -25,10 +25,10 @@ func TestQuickSortMedian(t *testing.T) { fmt.Println("快速排序(中位基准数优化)完成后 nums = ", nums) } -// 快速排序(尾递归优化) +// 快速排序(递归深度优化) func TestQuickSortTailCall(t *testing.T) { q := quickSortTailCall{} nums := []int{4, 1, 3, 1, 5, 2} q.quickSort(nums, 0, len(nums)-1) - fmt.Println("快速排序(尾递归优化)完成后 nums = ", nums) + fmt.Println("快速排序(递归深度优化)完成后 nums = ", nums) } diff --git a/codes/java/chapter_sorting/quick_sort.java b/codes/java/chapter_sorting/quick_sort.java index a6c39c346..8042a4d0b 100644 --- a/codes/java/chapter_sorting/quick_sort.java +++ b/codes/java/chapter_sorting/quick_sort.java @@ -96,7 +96,7 @@ class QuickSortMedian { } } -/* 快速排序类(尾递归优化) */ +/* 快速排序类(递归深度优化) */ class QuickSortTailCall { /* 元素交换 */ static void swap(int[] nums, int i, int j) { @@ -120,7 +120,7 @@ class QuickSortTailCall { return i; // 返回基准数的索引 } - /* 快速排序(尾递归优化) */ + /* 快速排序(递归深度优化) */ public static void quickSort(int[] nums, int left, int right) { // 子数组长度为 1 时终止 while (left < right) { @@ -150,9 +150,9 @@ public class quick_sort { QuickSortMedian.quickSort(nums1, 0, nums1.length - 1); System.out.println("快速排序(中位基准数优化)完成后 nums1 = " + Arrays.toString(nums1)); - /* 快速排序(尾递归优化) */ + /* 快速排序(递归深度优化) */ int[] nums2 = { 2, 4, 1, 0, 3, 5 }; QuickSortTailCall.quickSort(nums2, 0, nums2.length - 1); - System.out.println("快速排序(尾递归优化)完成后 nums2 = " + Arrays.toString(nums2)); + System.out.println("快速排序(递归深度优化)完成后 nums2 = " + Arrays.toString(nums2)); } } diff --git a/codes/javascript/chapter_sorting/quick_sort.js b/codes/javascript/chapter_sorting/quick_sort.js index fd96b2d16..f5dfd388a 100644 --- a/codes/javascript/chapter_sorting/quick_sort.js +++ b/codes/javascript/chapter_sorting/quick_sort.js @@ -100,7 +100,7 @@ class QuickSortMedian { } } -/* 快速排序类(尾递归优化) */ +/* 快速排序类(递归深度优化) */ class QuickSortTailCall { /* 元素交换 */ swap(nums, i, j) { @@ -123,7 +123,7 @@ class QuickSortTailCall { return i; // 返回基准数的索引 } - /* 快速排序(尾递归优化) */ + /* 快速排序(递归深度优化) */ quickSort(nums, left, right) { // 子数组长度为 1 时终止 while (left < right) { @@ -154,8 +154,8 @@ const quickSortMedian = new QuickSortMedian(); quickSortMedian.quickSort(nums1, 0, nums1.length - 1); console.log('快速排序(中位基准数优化)完成后 nums =', nums1); -/* 快速排序(尾递归优化) */ +/* 快速排序(递归深度优化) */ const nums2 = [2, 4, 1, 0, 3, 5]; const quickSortTailCall = new QuickSortTailCall(); quickSortTailCall.quickSort(nums2, 0, nums2.length - 1); -console.log('快速排序(尾递归优化)完成后 nums =', nums2); +console.log('快速排序(递归深度优化)完成后 nums =', nums2); diff --git a/codes/kotlin/chapter_sorting/quick_sort.kt b/codes/kotlin/chapter_sorting/quick_sort.kt index 77bfa9235..985747d17 100644 --- a/codes/kotlin/chapter_sorting/quick_sort.kt +++ b/codes/kotlin/chapter_sorting/quick_sort.kt @@ -83,7 +83,7 @@ fun quickSortMedian(nums: IntArray, left: Int, right: Int) { quickSort(nums, pivot + 1, right) } -/* 快速排序(尾递归优化) */ +/* 快速排序(递归深度优化) */ fun quickSortTailCall(nums: IntArray, left: Int, right: Int) { // 子数组长度为 1 时终止 var l = left @@ -114,8 +114,8 @@ fun main() { quickSortMedian(nums1, 0, nums1.size - 1) println("快速排序(中位基准数优化)完成后 nums1 = ${nums1.contentToString()}") - /* 快速排序(尾递归优化) */ + /* 快速排序(递归深度优化) */ val nums2 = intArrayOf(2, 4, 1, 0, 3, 5) quickSortTailCall(nums2, 0, nums2.size - 1) - println("快速排序(尾递归优化)完成后 nums2 = ${nums2.contentToString()}") + println("快速排序(递归深度优化)完成后 nums2 = ${nums2.contentToString()}") } \ No newline at end of file diff --git a/codes/python/chapter_sorting/quick_sort.py b/codes/python/chapter_sorting/quick_sort.py index 2c73cc1c5..0ab487a12 100644 --- a/codes/python/chapter_sorting/quick_sort.py +++ b/codes/python/chapter_sorting/quick_sort.py @@ -79,7 +79,7 @@ class QuickSortMedian: class QuickSortTailCall: - """快速排序类(尾递归优化)""" + """快速排序类(递归深度优化)""" def partition(self, nums: list[int], left: int, right: int) -> int: """哨兵划分""" @@ -97,7 +97,7 @@ class QuickSortTailCall: return i # 返回基准数的索引 def quick_sort(self, nums: list[int], left: int, right: int): - """快速排序(尾递归优化)""" + """快速排序(递归深度优化)""" # 子数组长度为 1 时终止 while left < right: # 哨兵划分操作 @@ -123,7 +123,7 @@ if __name__ == "__main__": QuickSortMedian().quick_sort(nums1, 0, len(nums1) - 1) print("快速排序(中位基准数优化)完成后 nums =", nums1) - # 快速排序(尾递归优化) + # 快速排序(递归深度优化) nums2 = [2, 4, 1, 0, 3, 5] QuickSortTailCall().quick_sort(nums2, 0, len(nums2) - 1) - print("快速排序(尾递归优化)完成后 nums =", nums2) + print("快速排序(递归深度优化)完成后 nums =", nums2) diff --git a/codes/ruby/chapter_sorting/quick_sort.rb b/codes/ruby/chapter_sorting/quick_sort.rb index 0ef9c48ff..4d53bd5a6 100644 --- a/codes/ruby/chapter_sorting/quick_sort.rb +++ b/codes/ruby/chapter_sorting/quick_sort.rb @@ -92,7 +92,7 @@ class QuickSortMedian end end -### 快速排序类(尾递归优化)### +### 快速排序类(递归深度优化)### class QuickSortTailCall class << self ### 哨兵划分 ### @@ -115,7 +115,7 @@ class QuickSortTailCall i # 返回基准数的索引 end - ### 快速排序(尾递归优化)### + ### 快速排序(递归深度优化)### def quick_sort(nums, left, right) # 子数组长度不为 1 时递归 while left < right @@ -146,8 +146,8 @@ if __FILE__ == $0 QuickSortMedian.quick_sort(nums1, 0, nums1.length - 1) puts "快速排序(中位基准数优化)完成后 nums1 = #{nums1}" - # 快速排序(尾递归优化) + # 快速排序(递归深度优化) nums2 = [2, 4, 1, 0, 3, 5] QuickSortTailCall.quick_sort(nums2, 0, nums2.length - 1) - puts "快速排序(尾递归优化)完成后 nums2 = #{nums2}" + puts "快速排序(递归深度优化)完成后 nums2 = #{nums2}" end diff --git a/codes/rust/chapter_sorting/quick_sort.rs b/codes/rust/chapter_sorting/quick_sort.rs index c3e0b15b9..b97fa7b26 100644 --- a/codes/rust/chapter_sorting/quick_sort.rs +++ b/codes/rust/chapter_sorting/quick_sort.rs @@ -90,7 +90,7 @@ impl QuickSortMedian { } } -/* 快速排序(尾递归优化) */ +/* 快速排序(递归深度优化) */ struct QuickSortTailCall; impl QuickSortTailCall { @@ -111,7 +111,7 @@ impl QuickSortTailCall { i // 返回基准数的索引 } - /* 快速排序(尾递归优化) */ + /* 快速排序(递归深度优化) */ pub fn quick_sort(mut left: i32, mut right: i32, nums: &mut [i32]) { // 子数组长度为 1 时终止 while left < right { @@ -141,8 +141,8 @@ fn main() { QuickSortMedian::quick_sort(0, (nums.len() - 1) as i32, &mut nums); println!("快速排序(中位基准数优化)完成后 nums = {:?}", nums); - /* 快速排序(尾递归优化) */ + /* 快速排序(递归深度优化) */ let mut nums = [2, 4, 1, 0, 3, 5]; QuickSortTailCall::quick_sort(0, (nums.len() - 1) as i32, &mut nums); - println!("快速排序(尾递归优化)完成后 nums = {:?}", nums); + println!("快速排序(递归深度优化)完成后 nums = {:?}", nums); } diff --git a/codes/swift/chapter_sorting/quick_sort.swift b/codes/swift/chapter_sorting/quick_sort.swift index d4bcf9393..ab1c7754e 100644 --- a/codes/swift/chapter_sorting/quick_sort.swift +++ b/codes/swift/chapter_sorting/quick_sort.swift @@ -73,7 +73,7 @@ func quickSortMedian(nums: inout [Int], left: Int, right: Int) { quickSortMedian(nums: &nums, left: pivot + 1, right: right) } -/* 快速排序(尾递归优化) */ +/* 快速排序(递归深度优化) */ func quickSortTailCall(nums: inout [Int], left: Int, right: Int) { var left = left var right = right @@ -106,9 +106,9 @@ enum QuickSort { quickSortMedian(nums: &nums1, left: nums1.startIndex, right: nums1.endIndex - 1) print("快速排序(中位基准数优化)完成后 nums1 = \(nums1)") - /* 快速排序(尾递归优化) */ + /* 快速排序(递归深度优化) */ var nums2 = [2, 4, 1, 0, 3, 5] quickSortTailCall(nums: &nums2, left: nums2.startIndex, right: nums2.endIndex - 1) - print("快速排序(尾递归优化)完成后 nums2 = \(nums2)") + print("快速排序(递归深度优化)完成后 nums2 = \(nums2)") } } diff --git a/codes/typescript/chapter_sorting/quick_sort.ts b/codes/typescript/chapter_sorting/quick_sort.ts index f3ae3d8f3..cb66ffe95 100644 --- a/codes/typescript/chapter_sorting/quick_sort.ts +++ b/codes/typescript/chapter_sorting/quick_sort.ts @@ -113,7 +113,7 @@ class QuickSortMedian { } } -/* 快速排序类(尾递归优化) */ +/* 快速排序类(递归深度优化) */ class QuickSortTailCall { /* 元素交换 */ swap(nums: number[], i: number, j: number): void { @@ -140,7 +140,7 @@ class QuickSortTailCall { return i; // 返回基准数的索引 } - /* 快速排序(尾递归优化) */ + /* 快速排序(递归深度优化) */ quickSort(nums: number[], left: number, right: number): void { // 子数组长度为 1 时终止 while (left < right) { @@ -171,10 +171,10 @@ const quickSortMedian = new QuickSortMedian(); quickSortMedian.quickSort(nums1, 0, nums1.length - 1); console.log('快速排序(中位基准数优化)完成后 nums =', nums1); -/* 快速排序(尾递归优化) */ +/* 快速排序(递归深度优化) */ const nums2 = [2, 4, 1, 0, 3, 5]; const quickSortTailCall = new QuickSortTailCall(); quickSortTailCall.quickSort(nums2, 0, nums2.length - 1); -console.log('快速排序(尾递归优化)完成后 nums =', nums2); +console.log('快速排序(递归深度优化)完成后 nums =', nums2); export {}; diff --git a/codes/zig/chapter_sorting/quick_sort.zig b/codes/zig/chapter_sorting/quick_sort.zig index 7f0cf5923..1d820f114 100644 --- a/codes/zig/chapter_sorting/quick_sort.zig +++ b/codes/zig/chapter_sorting/quick_sort.zig @@ -94,7 +94,7 @@ const QuickSortMedian = struct { } }; -// 快速排序类(尾递归优化) +// 快速排序类(递归深度优化) const QuickSortTailCall = struct { // 元素交换 @@ -118,7 +118,7 @@ const QuickSortTailCall = struct { return i; // 返回基准数的索引 } - // 快速排序(尾递归优化) + // 快速排序(递归深度优化) pub fn quickSort(nums: []i32, left_: usize, right_: usize) void { var left = left_; var right = right_; @@ -152,10 +152,10 @@ pub fn main() !void { std.debug.print("\n快速排序(中位基准数优化)完成后 nums = ", .{}); inc.PrintUtil.printArray(i32, &nums1); - // 快速排序(尾递归优化) + // 快速排序(递归深度优化) var nums2 = [_]i32{ 2, 4, 1, 0, 3, 5 }; QuickSortTailCall.quickSort(&nums2, 0, nums2.len - 1); - std.debug.print("\n快速排序(尾递归优化)完成后 nums = ", .{}); + std.debug.print("\n快速排序(递归深度优化)完成后 nums = ", .{}); inc.PrintUtil.printArray(i32, &nums2); _ = try std.io.getStdIn().reader().readByte(); diff --git a/docs/chapter_sorting/quick_sort.md b/docs/chapter_sorting/quick_sort.md index 96be54bac..9e80ea9c0 100755 --- a/docs/chapter_sorting/quick_sort.md +++ b/docs/chapter_sorting/quick_sort.md @@ -89,7 +89,7 @@ [file]{quick_sort}-[class]{quick_sort_median}-[func]{partition} ``` -## 尾递归优化 +## 递归深度优化 **在某些输入下,快速排序可能占用空间较多**。以完全有序的输入数组为例,设递归中的子数组长度为 $m$ ,每轮哨兵划分操作都将产生长度为 $0$ 的左子数组和长度为 $m - 1$ 的右子数组,这意味着每一层递归调用减少的问题规模非常小(只减少一个元素),递归树的高度会达到 $n - 1$ ,此时需要占用 $O(n)$ 大小的栈帧空间。 diff --git a/docs/chapter_sorting/summary.md b/docs/chapter_sorting/summary.md index 31edcb8b8..1dbee0768 100644 --- a/docs/chapter_sorting/summary.md +++ b/docs/chapter_sorting/summary.md @@ -4,7 +4,7 @@ - 冒泡排序通过交换相邻元素来实现排序。通过添加一个标志位来实现提前返回,我们可以将冒泡排序的最佳时间复杂度优化到 $O(n)$ 。 - 插入排序每轮将未排序区间内的元素插入到已排序区间的正确位置,从而完成排序。虽然插入排序的时间复杂度为 $O(n^2)$ ,但由于单元操作相对较少,因此在小数据量的排序任务中非常受欢迎。 -- 快速排序基于哨兵划分操作实现排序。在哨兵划分中,有可能每次都选取到最差的基准数,导致时间复杂度劣化至 $O(n^2)$ 。引入中位数基准数或随机基准数可以降低这种劣化的概率。尾递归方法可以有效地减少递归深度,将空间复杂度优化到 $O(\log n)$ 。 +- 快速排序基于哨兵划分操作实现排序。在哨兵划分中,有可能每次都选取到最差的基准数,导致时间复杂度劣化至 $O(n^2)$ 。引入中位数基准数或随机基准数可以降低这种劣化的概率。通过优先递归较短子区间,可有效减小递归深度,将空间复杂度优化到 $O(\log n)$ 。 - 归并排序包括划分和合并两个阶段,典型地体现了分治策略。在归并排序中,排序数组需要创建辅助数组,空间复杂度为 $O(n)$ ;然而排序链表的空间复杂度可以优化至 $O(1)$ 。 - 桶排序包含三个步骤:数据分桶、桶内排序和合并结果。它同样体现了分治策略,适用于数据体量很大的情况。桶排序的关键在于对数据进行平均分配。 - 计数排序是桶排序的一个特例,它通过统计数据出现的次数来实现排序。计数排序适用于数据量大但数据范围有限的情况,并且要求数据能够转换为正整数。 @@ -32,11 +32,11 @@ 再深入思考一下,如果我们选择 `nums[right]` 为基准数,那么正好反过来,必须先“从左往右查找”。 -**Q**:关于尾递归优化,为什么选短的数组能保证递归深度不超过 $\log n$ ? +**Q**:关于快速排序的递归深度优化,为什么选短的数组能保证递归深度不超过 $\log n$ ? -递归深度就是当前未返回的递归方法的数量。每轮哨兵划分我们将原数组划分为两个子数组。在尾递归优化后,向下递归的子数组长度最大为原数组长度的一半。假设最差情况,一直为一半长度,那么最终的递归深度就是 $\log n$ 。 +递归深度就是当前未返回的递归方法的数量。每轮哨兵划分我们将原数组划分为两个子数组。在递归深度优化后,向下递归的子数组长度最大为原数组长度的一半。假设最差情况,一直为一半长度,那么最终的递归深度就是 $\log n$ 。 -回顾原始的快速排序,我们有可能会连续地递归长度较大的数组,最差情况下为 $n$、$n - 1$、$\dots$、$2$、$1$ ,递归深度为 $n$ 。尾递归优化可以避免这种情况出现。 +回顾原始的快速排序,我们有可能会连续地递归长度较大的数组,最差情况下为 $n$、$n - 1$、$\dots$、$2$、$1$ ,递归深度为 $n$ 。递归深度优化可以避免这种情况出现。 **Q**:当数组中所有元素都相等时,快速排序的时间复杂度是 $O(n^2)$ 吗?该如何处理这种退化情况? diff --git a/docs/index.html b/docs/index.html index 5e8b0888a..8ccffcf07 100644 --- a/docs/index.html +++ b/docs/index.html @@ -347,7 +347,7 @@

贡献者

-

本书在开源社区一百多位贡献者的共同努力下不断完善,感谢他们付出的时间与精力!

+

本书在开源社区 200 多位贡献者的共同努力下不断完善,感谢他们付出的时间与精力!

Contributors diff --git a/en/docs/index.html b/en/docs/index.html index dbedfcc7e..2d16406b0 100644 --- a/en/docs/index.html +++ b/en/docs/index.html @@ -414,7 +414,7 @@

Contributors

-

This book has been refined by the efforts of over 180 contributors. We sincerely thank them for their invaluable time and contributions!

+

This book has been refined by the efforts of over 200 contributors. We sincerely thank them for their invaluable time and contributions!

Contributors diff --git a/zh-hant/codes/c/chapter_sorting/quick_sort.c b/zh-hant/codes/c/chapter_sorting/quick_sort.c index 206385b3b..c3acb1a26 100644 --- a/zh-hant/codes/c/chapter_sorting/quick_sort.c +++ b/zh-hant/codes/c/chapter_sorting/quick_sort.c @@ -89,9 +89,9 @@ void quickSortMedian(int nums[], int left, int right) { quickSortMedian(nums, pivot + 1, right); } -// 以下為尾遞迴最佳化的快速排序 +// 以下為遞迴深度最佳化的快速排序 -/* 快速排序(尾遞迴最佳化) */ +/* 快速排序(遞迴深度最佳化) */ void quickSortTailCall(int nums[], int left, int right) { // 子陣列長度為 1 時終止 while (left < right) { @@ -127,10 +127,10 @@ int main() { printf("快速排序(中位基準數最佳化)完成後 nums = "); printArray(nums1, size); - /* 快速排序(尾遞迴最佳化) */ + /* 快速排序(遞迴深度最佳化) */ int nums2[] = {2, 4, 1, 0, 3, 5}; quickSortTailCall(nums2, 0, size - 1); - printf("快速排序(尾遞迴最佳化)完成後 nums = "); + printf("快速排序(遞迴深度最佳化)完成後 nums = "); printArray(nums1, size); return 0; diff --git a/zh-hant/codes/cpp/chapter_sorting/quick_sort.cpp b/zh-hant/codes/cpp/chapter_sorting/quick_sort.cpp index 99ae48d56..7195ed315 100644 --- a/zh-hant/codes/cpp/chapter_sorting/quick_sort.cpp +++ b/zh-hant/codes/cpp/chapter_sorting/quick_sort.cpp @@ -84,7 +84,7 @@ class QuickSortMedian { } }; -/* 快速排序類別(尾遞迴最佳化) */ +/* 快速排序類別(遞迴深度最佳化) */ class QuickSortTailCall { private: /* 哨兵劃分 */ @@ -103,7 +103,7 @@ class QuickSortTailCall { } public: - /* 快速排序(尾遞迴最佳化) */ + /* 快速排序(遞迴深度最佳化) */ static void quickSort(vector &nums, int left, int right) { // 子陣列長度為 1 時終止 while (left < right) { @@ -135,10 +135,10 @@ int main() { cout << "快速排序(中位基準數最佳化)完成後 nums = "; printVector(nums1); - /* 快速排序(尾遞迴最佳化) */ + /* 快速排序(遞迴深度最佳化) */ vector nums2 = {2, 4, 1, 0, 3, 5}; QuickSortTailCall::quickSort(nums2, 0, nums2.size() - 1); - cout << "快速排序(尾遞迴最佳化)完成後 nums = "; + cout << "快速排序(遞迴深度最佳化)完成後 nums = "; printVector(nums2); return 0; diff --git a/zh-hant/codes/csharp/chapter_sorting/quick_sort.cs b/zh-hant/codes/csharp/chapter_sorting/quick_sort.cs index 90fa517f9..b880767a8 100644 --- a/zh-hant/codes/csharp/chapter_sorting/quick_sort.cs +++ b/zh-hant/codes/csharp/chapter_sorting/quick_sort.cs @@ -89,7 +89,7 @@ class QuickSortMedian { } } -/* 快速排序類別(尾遞迴最佳化) */ +/* 快速排序類別(遞迴深度最佳化) */ class QuickSortTailCall { /* 元素交換 */ static void Swap(int[] nums, int i, int j) { @@ -111,7 +111,7 @@ class QuickSortTailCall { return i; // 返回基準數的索引 } - /* 快速排序(尾遞迴最佳化) */ + /* 快速排序(遞迴深度最佳化) */ public static void QuickSort(int[] nums, int left, int right) { // 子陣列長度為 1 時終止 while (left < right) { @@ -142,9 +142,9 @@ public class quick_sort { QuickSortMedian.QuickSort(nums1, 0, nums1.Length - 1); Console.WriteLine("快速排序(中位基準數最佳化)完成後 nums1 = " + string.Join(",", nums1)); - /* 快速排序(尾遞迴最佳化) */ + /* 快速排序(遞迴深度最佳化) */ int[] nums2 = [2, 4, 1, 0, 3, 5]; QuickSortTailCall.QuickSort(nums2, 0, nums2.Length - 1); - Console.WriteLine("快速排序(尾遞迴最佳化)完成後 nums2 = " + string.Join(",", nums2)); + Console.WriteLine("快速排序(遞迴深度最佳化)完成後 nums2 = " + string.Join(",", nums2)); } } diff --git a/zh-hant/codes/dart/chapter_sorting/quick_sort.dart b/zh-hant/codes/dart/chapter_sorting/quick_sort.dart index 369910845..f074fa70c 100644 --- a/zh-hant/codes/dart/chapter_sorting/quick_sort.dart +++ b/zh-hant/codes/dart/chapter_sorting/quick_sort.dart @@ -86,7 +86,7 @@ class QuickSortMedian { } } -/* 快速排序類別(尾遞迴最佳化) */ +/* 快速排序類別(遞迴深度最佳化) */ class QuickSortTailCall { /* 元素交換 */ static void _swap(List nums, int i, int j) { @@ -108,7 +108,7 @@ class QuickSortTailCall { return i; // 返回基準數的索引 } - /* 快速排序(尾遞迴最佳化) */ + /* 快速排序(遞迴深度最佳化) */ static void quickSort(List nums, int left, int right) { // 子陣列長度為 1 時終止 while (left < right) { @@ -138,8 +138,8 @@ void main() { QuickSortMedian.quickSort(nums1, 0, nums1.length - 1); print("快速排序(中位基準數最佳化)完成後 nums1 = $nums1"); - /* 快速排序(尾遞迴最佳化) */ + /* 快速排序(遞迴深度最佳化) */ List nums2 = [2, 4, 1, 0, 3, 5]; QuickSortTailCall.quickSort(nums2, 0, nums2.length - 1); - print("快速排序(尾遞迴最佳化)完成後 nums2 = $nums2"); + print("快速排序(遞迴深度最佳化)完成後 nums2 = $nums2"); } diff --git a/zh-hant/codes/go/chapter_sorting/quick_sort.go b/zh-hant/codes/go/chapter_sorting/quick_sort.go index e8b94da2f..66df74725 100644 --- a/zh-hant/codes/go/chapter_sorting/quick_sort.go +++ b/zh-hant/codes/go/chapter_sorting/quick_sort.go @@ -10,7 +10,7 @@ type quickSort struct{} // 快速排序(中位基準數最佳化) type quickSortMedian struct{} -// 快速排序(尾遞迴最佳化) +// 快速排序(遞迴深度最佳化) type quickSortTailCall struct{} /* 哨兵劃分 */ @@ -112,7 +112,7 @@ func (q *quickSortTailCall) partition(nums []int, left, right int) int { return i // 返回基準數的索引 } -/* 快速排序(尾遞迴最佳化)*/ +/* 快速排序(遞迴深度最佳化)*/ func (q *quickSortTailCall) quickSort(nums []int, left, right int) { // 子陣列長度為 1 時終止 for left < right { diff --git a/zh-hant/codes/go/chapter_sorting/quick_sort_test.go b/zh-hant/codes/go/chapter_sorting/quick_sort_test.go index 503cb8b9f..e6ea1b088 100644 --- a/zh-hant/codes/go/chapter_sorting/quick_sort_test.go +++ b/zh-hant/codes/go/chapter_sorting/quick_sort_test.go @@ -25,10 +25,10 @@ func TestQuickSortMedian(t *testing.T) { fmt.Println("快速排序(中位基準數最佳化)完成後 nums = ", nums) } -// 快速排序(尾遞迴最佳化) +// 快速排序(遞迴深度最佳化) func TestQuickSortTailCall(t *testing.T) { q := quickSortTailCall{} nums := []int{4, 1, 3, 1, 5, 2} q.quickSort(nums, 0, len(nums)-1) - fmt.Println("快速排序(尾遞迴最佳化)完成後 nums = ", nums) + fmt.Println("快速排序(遞迴深度最佳化)完成後 nums = ", nums) } diff --git a/zh-hant/codes/java/chapter_sorting/quick_sort.java b/zh-hant/codes/java/chapter_sorting/quick_sort.java index c4d68a950..b4ab7bca3 100644 --- a/zh-hant/codes/java/chapter_sorting/quick_sort.java +++ b/zh-hant/codes/java/chapter_sorting/quick_sort.java @@ -96,7 +96,7 @@ class QuickSortMedian { } } -/* 快速排序類別(尾遞迴最佳化) */ +/* 快速排序類別(遞迴深度最佳化) */ class QuickSortTailCall { /* 元素交換 */ static void swap(int[] nums, int i, int j) { @@ -120,7 +120,7 @@ class QuickSortTailCall { return i; // 返回基準數的索引 } - /* 快速排序(尾遞迴最佳化) */ + /* 快速排序(遞迴深度最佳化) */ public static void quickSort(int[] nums, int left, int right) { // 子陣列長度為 1 時終止 while (left < right) { @@ -150,9 +150,9 @@ public class quick_sort { QuickSortMedian.quickSort(nums1, 0, nums1.length - 1); System.out.println("快速排序(中位基準數最佳化)完成後 nums1 = " + Arrays.toString(nums1)); - /* 快速排序(尾遞迴最佳化) */ + /* 快速排序(遞迴深度最佳化) */ int[] nums2 = { 2, 4, 1, 0, 3, 5 }; QuickSortTailCall.quickSort(nums2, 0, nums2.length - 1); - System.out.println("快速排序(尾遞迴最佳化)完成後 nums2 = " + Arrays.toString(nums2)); + System.out.println("快速排序(遞迴深度最佳化)完成後 nums2 = " + Arrays.toString(nums2)); } } diff --git a/zh-hant/codes/javascript/chapter_sorting/quick_sort.js b/zh-hant/codes/javascript/chapter_sorting/quick_sort.js index 43e506fa9..731ab81df 100644 --- a/zh-hant/codes/javascript/chapter_sorting/quick_sort.js +++ b/zh-hant/codes/javascript/chapter_sorting/quick_sort.js @@ -100,7 +100,7 @@ class QuickSortMedian { } } -/* 快速排序類別(尾遞迴最佳化) */ +/* 快速排序類別(遞迴深度最佳化) */ class QuickSortTailCall { /* 元素交換 */ swap(nums, i, j) { @@ -123,7 +123,7 @@ class QuickSortTailCall { return i; // 返回基準數的索引 } - /* 快速排序(尾遞迴最佳化) */ + /* 快速排序(遞迴深度最佳化) */ quickSort(nums, left, right) { // 子陣列長度為 1 時終止 while (left < right) { @@ -154,8 +154,8 @@ const quickSortMedian = new QuickSortMedian(); quickSortMedian.quickSort(nums1, 0, nums1.length - 1); console.log('快速排序(中位基準數最佳化)完成後 nums =', nums1); -/* 快速排序(尾遞迴最佳化) */ +/* 快速排序(遞迴深度最佳化) */ const nums2 = [2, 4, 1, 0, 3, 5]; const quickSortTailCall = new QuickSortTailCall(); quickSortTailCall.quickSort(nums2, 0, nums2.length - 1); -console.log('快速排序(尾遞迴最佳化)完成後 nums =', nums2); +console.log('快速排序(遞迴深度最佳化)完成後 nums =', nums2); diff --git a/zh-hant/codes/kotlin/chapter_sorting/quick_sort.kt b/zh-hant/codes/kotlin/chapter_sorting/quick_sort.kt index f7758f3d4..f16d26b45 100644 --- a/zh-hant/codes/kotlin/chapter_sorting/quick_sort.kt +++ b/zh-hant/codes/kotlin/chapter_sorting/quick_sort.kt @@ -83,7 +83,7 @@ fun quickSortMedian(nums: IntArray, left: Int, right: Int) { quickSort(nums, pivot + 1, right) } -/* 快速排序(尾遞迴最佳化) */ +/* 快速排序(遞迴深度最佳化) */ fun quickSortTailCall(nums: IntArray, left: Int, right: Int) { // 子陣列長度為 1 時終止 var l = left @@ -114,8 +114,8 @@ fun main() { quickSortMedian(nums1, 0, nums1.size - 1) println("快速排序(中位基準數最佳化)完成後 nums1 = ${nums1.contentToString()}") - /* 快速排序(尾遞迴最佳化) */ + /* 快速排序(遞迴深度最佳化) */ val nums2 = intArrayOf(2, 4, 1, 0, 3, 5) quickSortTailCall(nums2, 0, nums2.size - 1) - println("快速排序(尾遞迴最佳化)完成後 nums2 = ${nums2.contentToString()}") + println("快速排序(遞迴深度最佳化)完成後 nums2 = ${nums2.contentToString()}") } \ No newline at end of file diff --git a/zh-hant/codes/python/chapter_sorting/quick_sort.py b/zh-hant/codes/python/chapter_sorting/quick_sort.py index 0258da54b..e1d1e63f0 100644 --- a/zh-hant/codes/python/chapter_sorting/quick_sort.py +++ b/zh-hant/codes/python/chapter_sorting/quick_sort.py @@ -79,7 +79,7 @@ class QuickSortMedian: class QuickSortTailCall: - """快速排序類別(尾遞迴最佳化)""" + """快速排序類別(遞迴深度最佳化)""" def partition(self, nums: list[int], left: int, right: int) -> int: """哨兵劃分""" @@ -97,7 +97,7 @@ class QuickSortTailCall: return i # 返回基準數的索引 def quick_sort(self, nums: list[int], left: int, right: int): - """快速排序(尾遞迴最佳化)""" + """快速排序(遞迴深度最佳化)""" # 子陣列長度為 1 時終止 while left < right: # 哨兵劃分操作 @@ -123,7 +123,7 @@ if __name__ == "__main__": QuickSortMedian().quick_sort(nums1, 0, len(nums1) - 1) print("快速排序(中位基準數最佳化)完成後 nums =", nums1) - # 快速排序(尾遞迴最佳化) + # 快速排序(遞迴深度最佳化) nums2 = [2, 4, 1, 0, 3, 5] QuickSortTailCall().quick_sort(nums2, 0, len(nums2) - 1) - print("快速排序(尾遞迴最佳化)完成後 nums =", nums2) + print("快速排序(遞迴深度最佳化)完成後 nums =", nums2) diff --git a/zh-hant/codes/ruby/chapter_sorting/quick_sort.rb b/zh-hant/codes/ruby/chapter_sorting/quick_sort.rb index 221a17715..fc552d17f 100644 --- a/zh-hant/codes/ruby/chapter_sorting/quick_sort.rb +++ b/zh-hant/codes/ruby/chapter_sorting/quick_sort.rb @@ -92,7 +92,7 @@ class QuickSortMedian end end -### 快速排序類別(尾遞迴最佳化)### +### 快速排序類別(遞迴深度最佳化)### class QuickSortTailCall class << self ### 哨兵劃分 ### @@ -115,7 +115,7 @@ class QuickSortTailCall i # 返回基準數的索引 end - ### 快速排序(尾遞迴最佳化)### + ### 快速排序(遞迴深度最佳化)### def quick_sort(nums, left, right) # 子陣列長度不為 1 時遞迴 while left < right @@ -146,8 +146,8 @@ if __FILE__ == $0 QuickSortMedian.quick_sort(nums1, 0, nums1.length - 1) puts "快速排序(中位基準數最佳化)完成後 nums1 = #{nums1}" - # 快速排序(尾遞迴最佳化) + # 快速排序(遞迴深度最佳化) nums2 = [2, 4, 1, 0, 3, 5] QuickSortTailCall.quick_sort(nums2, 0, nums2.length - 1) - puts "快速排序(尾遞迴最佳化)完成後 nums2 = #{nums2}" + puts "快速排序(遞迴深度最佳化)完成後 nums2 = #{nums2}" end diff --git a/zh-hant/codes/rust/chapter_heap/heap.rs b/zh-hant/codes/rust/chapter_heap/heap.rs index 1bf198cea..1a117c024 100644 --- a/zh-hant/codes/rust/chapter_heap/heap.rs +++ b/zh-hant/codes/rust/chapter_heap/heap.rs @@ -6,18 +6,28 @@ use hello_algo_rust::include::print_util; -use std::collections::BinaryHeap; +use std::{cmp::Reverse, collections::BinaryHeap}; -fn test_push(heap: &mut BinaryHeap, val: i32, flag: i32) { - heap.push(flag * val); // 元素入堆積 +fn test_push_max(heap: &mut BinaryHeap, val: i32) { + heap.push(val); // 元素入堆積 println!("\n元素 {} 入堆積後", val); - print_util::print_heap(heap.iter().map(|&val| flag * val).collect()); + print_util::print_heap(heap.iter().map(|&val| val).collect()); +} +fn test_push_min(heap: &mut BinaryHeap>, val: i32) { + heap.push(Reverse(val)); // 元素入堆積 + println!("\n元素 {} 入堆積後", val); + print_util::print_heap(heap.iter().map(|&val| val.0).collect()); } -fn test_pop(heap: &mut BinaryHeap, flag: i32) { +fn test_pop_max(heap: &mut BinaryHeap) { let val = heap.pop().unwrap(); - println!("\n堆積頂元素 {} 出堆積後", flag * val); - print_util::print_heap(heap.iter().map(|&val| flag * val).collect()); + println!("\n堆積頂元素 {} 出堆積後", val); + print_util::print_heap(heap.iter().map(|&val| val).collect()); +} +fn test_pop_min(heap: &mut BinaryHeap>) { + let val = heap.pop().unwrap().0; + println!("\n堆積頂元素 {} 出堆積後", val); + print_util::print_heap(heap.iter().map(|&val| val.0).collect()); } /* Driver Code */ @@ -26,31 +36,29 @@ fn main() { // 初始化小頂堆積 #[allow(unused_assignments)] let mut min_heap = BinaryHeap::new(); - // Rust 的 BinaryHeap 是大頂堆積,當入列時將元素值乘以 -1 將其反轉,當出列時將元素值乘以 -1 將其還原 - let min_heap_flag = -1; + // Rust 的 BinaryHeap 是大頂堆積,小頂堆積一般會“套上”Reverse // 初始化大頂堆積 let mut max_heap = BinaryHeap::new(); - let max_heap_flag = 1; println!("\n以下測試樣例為大頂堆積"); /* 元素入堆積 */ - test_push(&mut max_heap, 1, max_heap_flag); - test_push(&mut max_heap, 3, max_heap_flag); - test_push(&mut max_heap, 2, max_heap_flag); - test_push(&mut max_heap, 5, max_heap_flag); - test_push(&mut max_heap, 4, max_heap_flag); + test_push_max(&mut max_heap, 1); + test_push_max(&mut max_heap, 3); + test_push_max(&mut max_heap, 2); + test_push_max(&mut max_heap, 5); + test_push_max(&mut max_heap, 4); /* 獲取堆積頂元素 */ - let peek = max_heap.peek().unwrap() * max_heap_flag; + let peek = max_heap.peek().unwrap(); println!("\n堆積頂元素為 {}", peek); /* 堆積頂元素出堆積 */ - test_pop(&mut max_heap, max_heap_flag); - test_pop(&mut max_heap, max_heap_flag); - test_pop(&mut max_heap, max_heap_flag); - test_pop(&mut max_heap, max_heap_flag); - test_pop(&mut max_heap, max_heap_flag); + test_pop_max(&mut max_heap); + test_pop_max(&mut max_heap); + test_pop_max(&mut max_heap); + test_pop_max(&mut max_heap); + test_pop_max(&mut max_heap); /* 獲取堆積大小 */ let size = max_heap.len(); @@ -65,9 +73,9 @@ fn main() { min_heap = BinaryHeap::from( vec![1, 3, 2, 5, 4] .into_iter() - .map(|val| min_heap_flag * val) - .collect::>(), + .map(|val| Reverse(val)) + .collect::>>(), ); println!("\n輸入串列並建立小頂堆積後"); - print_util::print_heap(min_heap.iter().map(|&val| min_heap_flag * val).collect()); + print_util::print_heap(min_heap.iter().map(|&val| val.0).collect()); } diff --git a/zh-hant/codes/rust/chapter_sorting/quick_sort.rs b/zh-hant/codes/rust/chapter_sorting/quick_sort.rs index eda8c9259..9d35b46fd 100644 --- a/zh-hant/codes/rust/chapter_sorting/quick_sort.rs +++ b/zh-hant/codes/rust/chapter_sorting/quick_sort.rs @@ -90,7 +90,7 @@ impl QuickSortMedian { } } -/* 快速排序(尾遞迴最佳化) */ +/* 快速排序(遞迴深度最佳化) */ struct QuickSortTailCall; impl QuickSortTailCall { @@ -111,7 +111,7 @@ impl QuickSortTailCall { i // 返回基準數的索引 } - /* 快速排序(尾遞迴最佳化) */ + /* 快速排序(遞迴深度最佳化) */ pub fn quick_sort(mut left: i32, mut right: i32, nums: &mut [i32]) { // 子陣列長度為 1 時終止 while left < right { @@ -141,8 +141,8 @@ fn main() { QuickSortMedian::quick_sort(0, (nums.len() - 1) as i32, &mut nums); println!("快速排序(中位基準數最佳化)完成後 nums = {:?}", nums); - /* 快速排序(尾遞迴最佳化) */ + /* 快速排序(遞迴深度最佳化) */ let mut nums = [2, 4, 1, 0, 3, 5]; QuickSortTailCall::quick_sort(0, (nums.len() - 1) as i32, &mut nums); - println!("快速排序(尾遞迴最佳化)完成後 nums = {:?}", nums); + println!("快速排序(遞迴深度最佳化)完成後 nums = {:?}", nums); } diff --git a/zh-hant/codes/swift/chapter_sorting/quick_sort.swift b/zh-hant/codes/swift/chapter_sorting/quick_sort.swift index 550b18bcd..083a1fcc2 100644 --- a/zh-hant/codes/swift/chapter_sorting/quick_sort.swift +++ b/zh-hant/codes/swift/chapter_sorting/quick_sort.swift @@ -73,7 +73,7 @@ func quickSortMedian(nums: inout [Int], left: Int, right: Int) { quickSortMedian(nums: &nums, left: pivot + 1, right: right) } -/* 快速排序(尾遞迴最佳化) */ +/* 快速排序(遞迴深度最佳化) */ func quickSortTailCall(nums: inout [Int], left: Int, right: Int) { var left = left var right = right @@ -106,9 +106,9 @@ enum QuickSort { quickSortMedian(nums: &nums1, left: nums1.startIndex, right: nums1.endIndex - 1) print("快速排序(中位基準數最佳化)完成後 nums1 = \(nums1)") - /* 快速排序(尾遞迴最佳化) */ + /* 快速排序(遞迴深度最佳化) */ var nums2 = [2, 4, 1, 0, 3, 5] quickSortTailCall(nums: &nums2, left: nums2.startIndex, right: nums2.endIndex - 1) - print("快速排序(尾遞迴最佳化)完成後 nums2 = \(nums2)") + print("快速排序(遞迴深度最佳化)完成後 nums2 = \(nums2)") } } diff --git a/zh-hant/codes/typescript/chapter_sorting/quick_sort.ts b/zh-hant/codes/typescript/chapter_sorting/quick_sort.ts index 5fe31d605..c8a7ac9f7 100644 --- a/zh-hant/codes/typescript/chapter_sorting/quick_sort.ts +++ b/zh-hant/codes/typescript/chapter_sorting/quick_sort.ts @@ -113,7 +113,7 @@ class QuickSortMedian { } } -/* 快速排序類別(尾遞迴最佳化) */ +/* 快速排序類別(遞迴深度最佳化) */ class QuickSortTailCall { /* 元素交換 */ swap(nums: number[], i: number, j: number): void { @@ -140,7 +140,7 @@ class QuickSortTailCall { return i; // 返回基準數的索引 } - /* 快速排序(尾遞迴最佳化) */ + /* 快速排序(遞迴深度最佳化) */ quickSort(nums: number[], left: number, right: number): void { // 子陣列長度為 1 時終止 while (left < right) { @@ -171,10 +171,10 @@ const quickSortMedian = new QuickSortMedian(); quickSortMedian.quickSort(nums1, 0, nums1.length - 1); console.log('快速排序(中位基準數最佳化)完成後 nums =', nums1); -/* 快速排序(尾遞迴最佳化) */ +/* 快速排序(遞迴深度最佳化) */ const nums2 = [2, 4, 1, 0, 3, 5]; const quickSortTailCall = new QuickSortTailCall(); quickSortTailCall.quickSort(nums2, 0, nums2.length - 1); -console.log('快速排序(尾遞迴最佳化)完成後 nums =', nums2); +console.log('快速排序(遞迴深度最佳化)完成後 nums =', nums2); export {}; diff --git a/zh-hant/codes/zig/chapter_sorting/quick_sort.zig b/zh-hant/codes/zig/chapter_sorting/quick_sort.zig index 4c7bb59de..e556b76f1 100644 --- a/zh-hant/codes/zig/chapter_sorting/quick_sort.zig +++ b/zh-hant/codes/zig/chapter_sorting/quick_sort.zig @@ -94,7 +94,7 @@ const QuickSortMedian = struct { } }; -// 快速排序類別(尾遞迴最佳化) +// 快速排序類別(遞迴深度最佳化) const QuickSortTailCall = struct { // 元素交換 @@ -118,7 +118,7 @@ const QuickSortTailCall = struct { return i; // 返回基準數的索引 } - // 快速排序(尾遞迴最佳化) + // 快速排序(遞迴深度最佳化) pub fn quickSort(nums: []i32, left_: usize, right_: usize) void { var left = left_; var right = right_; @@ -152,10 +152,10 @@ pub fn main() !void { std.debug.print("\n快速排序(中位基準數最佳化)完成後 nums = ", .{}); inc.PrintUtil.printArray(i32, &nums1); - // 快速排序(尾遞迴最佳化) + // 快速排序(遞迴深度最佳化) var nums2 = [_]i32{ 2, 4, 1, 0, 3, 5 }; QuickSortTailCall.quickSort(&nums2, 0, nums2.len - 1); - std.debug.print("\n快速排序(尾遞迴最佳化)完成後 nums = ", .{}); + std.debug.print("\n快速排序(遞迴深度最佳化)完成後 nums = ", .{}); inc.PrintUtil.printArray(i32, &nums2); _ = try std.io.getStdIn().reader().readByte(); diff --git a/zh-hant/docs/chapter_array_and_linkedlist/list.md b/zh-hant/docs/chapter_array_and_linkedlist/list.md index 5ce01314f..ff5a6d589 100755 --- a/zh-hant/docs/chapter_array_and_linkedlist/list.md +++ b/zh-hant/docs/chapter_array_and_linkedlist/list.md @@ -1026,7 +1026,7 @@ 為了加深對串列工作原理的理解,我們嘗試實現一個簡易版串列,包括以下三個重點設計。 - **初始容量**:選取一個合理的陣列初始容量。在本示例中,我們選擇 10 作為初始容量。 -- **數量記錄**:宣告一個變數 `size` ,用於記錄串列當前元素數量,並隨著元素插入和刪除實時更新。根據此變數,我們可以定位串列尾部,以及判斷是否需要擴容。 +- **數量記錄**:宣告一個變數 `size` ,用於記錄串列當前元素數量,並隨著元素插入和刪除即時更新。根據此變數,我們可以定位串列尾部,以及判斷是否需要擴容。 - **擴容機制**:若插入元素時串列容量已滿,則需要進行擴容。先根據擴容倍數建立一個更大的陣列,再將當前陣列的所有元素依次移動至新陣列。在本示例中,我們規定每次將陣列擴容至之前的 2 倍。 ```src diff --git a/zh-hant/docs/chapter_backtracking/subset_sum_problem.md b/zh-hant/docs/chapter_backtracking/subset_sum_problem.md index f6418f836..6bab12728 100644 --- a/zh-hant/docs/chapter_backtracking/subset_sum_problem.md +++ b/zh-hant/docs/chapter_backtracking/subset_sum_problem.md @@ -13,7 +13,7 @@ ### 參考全排列解法 -類似於全排列問題,我們可以把子集的生成過程想象成一系列選擇的結果,並在選擇過程中實時更新“元素和”,當元素和等於 `target` 時,就將子集記錄至結果串列。 +類似於全排列問題,我們可以把子集的生成過程想象成一系列選擇的結果,並在選擇過程中即時更新“元素和”,當元素和等於 `target` 時,就將子集記錄至結果串列。 而與全排列問題不同的是,**本題集合中的元素可以被無限次選取**,因此無須藉助 `selected` 布林串列來記錄元素是否已被選擇。我們可以對全排列程式碼進行小幅修改,初步得到解題程式碼: diff --git a/zh-hant/docs/chapter_data_structure/character_encoding.md b/zh-hant/docs/chapter_data_structure/character_encoding.md index 335882821..a09deb252 100644 --- a/zh-hant/docs/chapter_data_structure/character_encoding.md +++ b/zh-hant/docs/chapter_data_structure/character_encoding.md @@ -1,34 +1,34 @@ # 字元編碼 * -在計算機中,所有資料都是以二進位制數的形式儲存的,字元 `char` 也不例外。為了表示字元,我們需要建立一套“字符集”,規定每個字元和二進位制數之間的一一對應關係。有了字符集之後,計算機就可以透過查表完成二進位制數到字元的轉換。 +在計算機中,所有資料都是以二進位制數的形式儲存的,字元 `char` 也不例外。為了表示字元,我們需要建立一套“字元集”,規定每個字元和二進位制數之間的一一對應關係。有了字元集之後,計算機就可以透過查表完成二進位制數到字元的轉換。 -## ASCII 字符集 +## ASCII 字元集 -ASCII 碼是最早出現的字符集,其全稱為 American Standard Code for Information Interchange(美國標準資訊交換程式碼)。它使用 7 位二進位制數(一個位元組的低 7 位)表示一個字元,最多能夠表示 128 個不同的字元。如下圖所示,ASCII 碼包括英文字母的大小寫、數字 0 ~ 9、一些標點符號,以及一些控制字元(如換行符和製表符)。 +ASCII 碼是最早出現的字元集,其全稱為 American Standard Code for Information Interchange(美國標準資訊交換程式碼)。它使用 7 位二進位制數(一個位元組的低 7 位)表示一個字元,最多能夠表示 128 個不同的字元。如下圖所示,ASCII 碼包括英文字母的大小寫、數字 0 ~ 9、一些標點符號,以及一些控制字元(如換行符和製表符)。 ![ASCII 碼](character_encoding.assets/ascii_table.png) -然而,**ASCII 碼僅能夠表示英文**。隨著計算機的全球化,誕生了一種能夠表示更多語言的 EASCII 字符集。它在 ASCII 的 7 位基礎上擴展到 8 位,能夠表示 256 個不同的字元。 +然而,**ASCII 碼僅能夠表示英文**。隨著計算機的全球化,誕生了一種能夠表示更多語言的 EASCII 字元集。它在 ASCII 的 7 位基礎上擴展到 8 位,能夠表示 256 個不同的字元。 -在世界範圍內,陸續出現了一批適用於不同地區的 EASCII 字符集。這些字符集的前 128 個字元統一為 ASCII 碼,後 128 個字元定義不同,以適應不同語言的需求。 +在世界範圍內,陸續出現了一批適用於不同地區的 EASCII 字元集。這些字元集的前 128 個字元統一為 ASCII 碼,後 128 個字元定義不同,以適應不同語言的需求。 -## GBK 字符集 +## GBK 字元集 -後來人們發現,**EASCII 碼仍然無法滿足許多語言的字元數量要求**。比如漢字有近十萬個,光日常使用的就有幾千個。中國國家標準總局於 1980 年釋出了 GB2312 字符集,其收錄了 6763 個漢字,基本滿足了漢字的計算機處理需要。 +後來人們發現,**EASCII 碼仍然無法滿足許多語言的字元數量要求**。比如漢字有近十萬個,光日常使用的就有幾千個。中國國家標準總局於 1980 年釋出了 GB2312 字元集,其收錄了 6763 個漢字,基本滿足了漢字的計算機處理需要。 -然而,GB2312 無法處理部分罕見字和繁體字。GBK 字符集是在 GB2312 的基礎上擴展得到的,它共收錄了 21886 個漢字。在 GBK 的編碼方案中,ASCII 字元使用一個位元組表示,漢字使用兩個位元組表示。 +然而,GB2312 無法處理部分罕見字和繁體字。GBK 字元集是在 GB2312 的基礎上擴展得到的,它共收錄了 21886 個漢字。在 GBK 的編碼方案中,ASCII 字元使用一個位元組表示,漢字使用兩個位元組表示。 -## Unicode 字符集 +## Unicode 字元集 -隨著計算機技術的蓬勃發展,字符集與編碼標準百花齊放,而這帶來了許多問題。一方面,這些字符集一般只定義了特定語言的字元,無法在多語言環境下正常工作。另一方面,同一種語言存在多種字符集標準,如果兩臺計算機使用的是不同的編碼標準,則在資訊傳遞時就會出現亂碼。 +隨著計算機技術的蓬勃發展,字元集與編碼標準百花齊放,而這帶來了許多問題。一方面,這些字元集一般只定義了特定語言的字元,無法在多語言環境下正常工作。另一方面,同一種語言存在多種字元集標準,如果兩臺計算機使用的是不同的編碼標準,則在資訊傳遞時就會出現亂碼。 -那個時代的研究人員就在想:**如果推出一個足夠完整的字符集,將世界範圍內的所有語言和符號都收錄其中,不就可以解決跨語言環境和亂碼問題了嗎**?在這種想法的驅動下,一個大而全的字符集 Unicode 應運而生。 +那個時代的研究人員就在想:**如果推出一個足夠完整的字元集,將世界範圍內的所有語言和符號都收錄其中,不就可以解決跨語言環境和亂碼問題了嗎**?在這種想法的驅動下,一個大而全的字元集 Unicode 應運而生。 -Unicode 的中文名稱為“統一碼”,理論上能容納 100 多萬個字元。它致力於將全球範圍內的字元納入統一的字符集之中,提供一種通用的字符集來處理和顯示各種語言文字,減少因為編碼標準不同而產生的亂碼問題。 +Unicode 的中文名稱為“統一碼”,理論上能容納 100 多萬個字元。它致力於將全球範圍內的字元納入統一的字元集之中,提供一種通用的字元集來處理和顯示各種語言文字,減少因為編碼標準不同而產生的亂碼問題。 -自 1991 年釋出以來,Unicode 不斷擴充新的語言與字元。截至 2022 年 9 月,Unicode 已經包含 149186 個字元,包括各種語言的字元、符號甚至表情符號等。在龐大的 Unicode 字符集中,常用的字元佔用 2 位元組,有些生僻的字元佔用 3 位元組甚至 4 位元組。 +自 1991 年釋出以來,Unicode 不斷擴充新的語言與字元。截至 2022 年 9 月,Unicode 已經包含 149186 個字元,包括各種語言的字元、符號甚至表情符號等。在龐大的 Unicode 字元集中,常用的字元佔用 2 位元組,有些生僻的字元佔用 3 位元組甚至 4 位元組。 -Unicode 是一種通用字符集,本質上是給每個字元分配一個編號(稱為“碼點”),**但它並沒有規定在計算機中如何儲存這些字元碼點**。我們不禁會問:當多種長度的 Unicode 碼點同時出現在一個文字中時,系統如何解析字元?例如給定一個長度為 2 位元組的編碼,系統如何確認它是一個 2 位元組的字元還是兩個 1 位元組的字元? +Unicode 是一種通用字元集,本質上是給每個字元分配一個編號(稱為“碼點”),**但它並沒有規定在計算機中如何儲存這些字元碼點**。我們不禁會問:當多種長度的 Unicode 碼點同時出現在一個文字中時,系統如何解析字元?例如給定一個長度為 2 位元組的編碼,系統如何確認它是一個 2 位元組的字元還是兩個 1 位元組的字元? 對於以上問題,**一種直接的解決方案是將所有字元儲存為等長的編碼**。如下圖所示,“Hello”中的每個字元佔用 1 位元組,“演算法”中的每個字元佔用 2 位元組。我們可以透過高位填 0 將“Hello 演算法”中的所有字元都編碼為 2 位元組長度。這樣系統就可以每隔 2 位元組解析一個字元,恢復這個短語的內容了。 @@ -42,7 +42,7 @@ Unicode 是一種通用字符集,本質上是給每個字元分配一個編號 UTF-8 的編碼規則並不複雜,分為以下兩種情況。 -- 對於長度為 1 位元組的字元,將最高位設定為 $0$ ,其餘 7 位設定為 Unicode 碼點。值得注意的是,ASCII 字元在 Unicode 字符集中佔據了前 128 個碼點。也就是說,**UTF-8 編碼可以向下相容 ASCII 碼**。這意味著我們可以使用 UTF-8 來解析年代久遠的 ASCII 碼文字。 +- 對於長度為 1 位元組的字元,將最高位設定為 $0$ ,其餘 7 位設定為 Unicode 碼點。值得注意的是,ASCII 字元在 Unicode 字元集中佔據了前 128 個碼點。也就是說,**UTF-8 編碼可以向下相容 ASCII 碼**。這意味著我們可以使用 UTF-8 來解析年代久遠的 ASCII 碼文字。 - 對於長度為 $n$ 位元組的字元(其中 $n > 1$),將首個位元組的高 $n$ 位都設定為 $1$ ,第 $n + 1$ 位設定為 $0$ ;從第二個位元組開始,將每個位元組的高 2 位都設定為 $10$ ;其餘所有位用於填充字元的 Unicode 碼點。 下圖展示了“Hello演算法”對應的 UTF-8 編碼。觀察發現,由於最高 $n$ 位都設定為 $1$ ,因此系統可以透過讀取最高位 $1$ 的個數來解析出字元的長度為 $n$ 。 diff --git a/zh-hant/docs/chapter_data_structure/summary.md b/zh-hant/docs/chapter_data_structure/summary.md index 03f326648..415b2d61d 100644 --- a/zh-hant/docs/chapter_data_structure/summary.md +++ b/zh-hant/docs/chapter_data_structure/summary.md @@ -10,7 +10,7 @@ - 原碼、一補數和二補數是在計算機中編碼數字的三種方法,它們之間可以相互轉換。整數的原碼的最高位是符號位,其餘位是數字的值。 - 整數在計算機中是以二補數的形式儲存的。在二補數表示下,計算機可以對正數和負數的加法一視同仁,不需要為減法操作單獨設計特殊的硬體電路,並且不存在正負零歧義的問題。 - 浮點數的編碼由 1 位符號位、8 位指數位和 23 位分數位構成。由於存在指數位,因此浮點數的取值範圍遠大於整數,代價是犧牲了精度。 -- ASCII 碼是最早出現的英文字符集,長度為 1 位元組,共收錄 127 個字元。GBK 字符集是常用的中文字符集,共收錄兩萬多個漢字。Unicode 致力於提供一個完整的字符集標準,收錄世界上各種語言的字元,從而解決由於字元編碼方法不一致而導致的亂碼問題。 +- ASCII 碼是最早出現的英文字元集,長度為 1 位元組,共收錄 127 個字元。GBK 字元集是常用的中文字元集,共收錄兩萬多個漢字。Unicode 致力於提供一個完整的字元集標準,收錄世界上各種語言的字元,從而解決由於字元編碼方法不一致而導致的亂碼問題。 - UTF-8 是最受歡迎的 Unicode 編碼方法,通用性非常好。它是一種變長的編碼方法,具有很好的擴展性,有效提升了儲存空間的使用效率。UTF-16 和 UTF-32 是等長的編碼方法。在編碼中文時,UTF-16 佔用的空間比 UTF-8 更小。Java 和 C# 等程式語言預設使用 UTF-16 編碼。 ### Q & A diff --git a/zh-hant/docs/chapter_greedy/max_product_cutting_problem.md b/zh-hant/docs/chapter_greedy/max_product_cutting_problem.md index 1504b23c0..c756eae85 100644 --- a/zh-hant/docs/chapter_greedy/max_product_cutting_problem.md +++ b/zh-hant/docs/chapter_greedy/max_product_cutting_problem.md @@ -78,8 +78,8 @@ $$ ### 正確性證明 -使用反證法,只分析 $n \geq 3$ 的情況。 +使用反證法,只分析 $n \geq 4$ 的情況。 -1. **所有因子 $\leq 3$** :假設最優切分方案中存在 $\geq 4$ 的因子 $x$ ,那麼一定可以將其繼續劃分為 $2(x-2)$ ,從而獲得更大的乘積。這與假設矛盾。 +1. **所有因子 $\leq 3$** :假設最優切分方案中存在 $\geq 4$ 的因子 $x$ ,那麼一定可以將其繼續劃分為 $2(x-2)$ ,從而獲得更大(或相等)的乘積。這與假設矛盾。 2. **切分方案不包含 $1$** :假設最優切分方案中存在一個因子 $1$ ,那麼它一定可以合併入另外一個因子中,以獲得更大的乘積。這與假設矛盾。 3. **切分方案最多包含兩個 $2$** :假設最優切分方案中包含三個 $2$ ,那麼一定可以替換為兩個 $3$ ,乘積更大。這與假設矛盾。 diff --git a/zh-hant/docs/chapter_sorting/quick_sort.md b/zh-hant/docs/chapter_sorting/quick_sort.md index 2202c0020..8aca8cf3b 100755 --- a/zh-hant/docs/chapter_sorting/quick_sort.md +++ b/zh-hant/docs/chapter_sorting/quick_sort.md @@ -89,7 +89,7 @@ [file]{quick_sort}-[class]{quick_sort_median}-[func]{partition} ``` -## 尾遞迴最佳化 +## 遞迴深度最佳化 **在某些輸入下,快速排序可能佔用空間較多**。以完全有序的輸入陣列為例,設遞迴中的子陣列長度為 $m$ ,每輪哨兵劃分操作都將產生長度為 $0$ 的左子陣列和長度為 $m - 1$ 的右子陣列,這意味著每一層遞迴呼叫減少的問題規模非常小(只減少一個元素),遞迴樹的高度會達到 $n - 1$ ,此時需要佔用 $O(n)$ 大小的堆疊幀空間。 diff --git a/zh-hant/docs/chapter_sorting/summary.md b/zh-hant/docs/chapter_sorting/summary.md index 969b37a5f..66db0d4e1 100644 --- a/zh-hant/docs/chapter_sorting/summary.md +++ b/zh-hant/docs/chapter_sorting/summary.md @@ -4,7 +4,7 @@ - 泡沫排序透過交換相鄰元素來實現排序。透過新增一個標誌位來實現提前返回,我們可以將泡沫排序的最佳時間複雜度最佳化到 $O(n)$ 。 - 插入排序每輪將未排序區間內的元素插入到已排序區間的正確位置,從而完成排序。雖然插入排序的時間複雜度為 $O(n^2)$ ,但由於單元操作相對較少,因此在小資料量的排序任務中非常受歡迎。 -- 快速排序基於哨兵劃分操作實現排序。在哨兵劃分中,有可能每次都選取到最差的基準數,導致時間複雜度劣化至 $O(n^2)$ 。引入中位數基準數或隨機基準數可以降低這種劣化的機率。尾遞迴方法可以有效地減少遞迴深度,將空間複雜度最佳化到 $O(\log n)$ 。 +- 快速排序基於哨兵劃分操作實現排序。在哨兵劃分中,有可能每次都選取到最差的基準數,導致時間複雜度劣化至 $O(n^2)$ 。引入中位數基準數或隨機基準數可以降低這種劣化的機率。透過優先遞迴較短子區間,可有效減小遞迴深度,將空間複雜度最佳化到 $O(\log n)$ 。 - 合併排序包括劃分和合並兩個階段,典型地體現了分治策略。在合併排序中,排序陣列需要建立輔助陣列,空間複雜度為 $O(n)$ ;然而排序鏈結串列的空間複雜度可以最佳化至 $O(1)$ 。 - 桶排序包含三個步驟:資料分桶、桶內排序和合並結果。它同樣體現了分治策略,適用於資料體量很大的情況。桶排序的關鍵在於對資料進行平均分配。 - 計數排序是桶排序的一個特例,它透過統計資料出現的次數來實現排序。計數排序適用於資料量大但資料範圍有限的情況,並且要求資料能夠轉換為正整數。 @@ -32,11 +32,11 @@ 再深入思考一下,如果我們選擇 `nums[right]` 為基準數,那麼正好反過來,必須先“從左往右查詢”。 -**Q**:關於尾遞迴最佳化,為什麼選短的陣列能保證遞迴深度不超過 $\log n$ ? +**Q**:關於快速排序的遞迴深度最佳化,為什麼選短的陣列能保證遞迴深度不超過 $\log n$ ? -遞迴深度就是當前未返回的遞迴方法的數量。每輪哨兵劃分我們將原陣列劃分為兩個子陣列。在尾遞迴最佳化後,向下遞迴的子陣列長度最大為原陣列長度的一半。假設最差情況,一直為一半長度,那麼最終的遞迴深度就是 $\log n$ 。 +遞迴深度就是當前未返回的遞迴方法的數量。每輪哨兵劃分我們將原陣列劃分為兩個子陣列。在遞迴深度最佳化後,向下遞迴的子陣列長度最大為原陣列長度的一半。假設最差情況,一直為一半長度,那麼最終的遞迴深度就是 $\log n$ 。 -回顧原始的快速排序,我們有可能會連續地遞迴長度較大的陣列,最差情況下為 $n$、$n - 1$、$\dots$、$2$、$1$ ,遞迴深度為 $n$ 。尾遞迴最佳化可以避免這種情況出現。 +回顧原始的快速排序,我們有可能會連續地遞迴長度較大的陣列,最差情況下為 $n$、$n - 1$、$\dots$、$2$、$1$ ,遞迴深度為 $n$ 。遞迴深度最佳化可以避免這種情況出現。 **Q**:當陣列中所有元素都相等時,快速排序的時間複雜度是 $O(n^2)$ 嗎?該如何處理這種退化情況? diff --git a/zh-hant/docs/index.html b/zh-hant/docs/index.html index 4628e7070..b5cdd8ebd 100644 --- a/zh-hant/docs/index.html +++ b/zh-hant/docs/index.html @@ -366,7 +366,7 @@

貢獻者

-

本書在開源社群一百多位貢獻者的共同努力下不斷完善,感謝他們付出的時間與精力!

+

本書在開源社群 200 多位貢獻者的共同努力下不斷完善,感謝他們付出的時間與精力!

Contributors