mirror of
				https://github.com/krahets/hello-algo.git
				synced 2025-11-01 03:24:24 +08:00 
			
		
		
		
	Sync zh and zh-hant versions. (#1523)
This commit is contained in:
		| @ -9,26 +9,19 @@ | |||||||
| /* 快速排序類別 */ | /* 快速排序類別 */ | ||||||
| class QuickSort { | class QuickSort { | ||||||
|   private: |   private: | ||||||
|     /* 元素交換 */ |  | ||||||
|     static void swap(vector<int> &nums, int i, int j) { |  | ||||||
|         int tmp = nums[i]; |  | ||||||
|         nums[i] = nums[j]; |  | ||||||
|         nums[j] = tmp; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     /* 哨兵劃分 */ |     /* 哨兵劃分 */ | ||||||
|     static int partition(vector<int> &nums, int left, int right) { |     static int partition(vector<int> &nums, int left, int right) { | ||||||
|         // 以 nums[left] 為基準數 |         // 以 nums[left] 為基準數 | ||||||
|         int i = left, j = right; |         int i = left, j = right; | ||||||
|         while (i < j) { |         while (i < j) { | ||||||
|             while (i < j && nums[j] >= nums[left]) |             while (i < j && nums[j] >= nums[left]) | ||||||
|                 j--; // 從右向左找首個小於基準數的元素 |                 j--;                // 從右向左找首個小於基準數的元素 | ||||||
|             while (i < j && nums[i] <= nums[left]) |             while (i < j && nums[i] <= nums[left]) | ||||||
|                 i++;          // 從左向右找首個大於基準數的元素 |                 i++;                // 從左向右找首個大於基準數的元素 | ||||||
|             swap(nums, i, j); // 交換這兩個元素 |             swap(nums[i], nums[j]); // 交換這兩個元素 | ||||||
|         } |         } | ||||||
|         swap(nums, i, left); // 將基準數交換至兩子陣列的分界線 |         swap(nums[i], nums[left]);  // 將基準數交換至兩子陣列的分界線 | ||||||
|         return i;            // 返回基準數的索引 |         return i;                   // 返回基準數的索引 | ||||||
|     } |     } | ||||||
|  |  | ||||||
|   public: |   public: | ||||||
| @ -48,13 +41,6 @@ class QuickSort { | |||||||
| /* 快速排序類別(中位基準數最佳化) */ | /* 快速排序類別(中位基準數最佳化) */ | ||||||
| class QuickSortMedian { | class QuickSortMedian { | ||||||
|   private: |   private: | ||||||
|     /* 元素交換 */ |  | ||||||
|     static void swap(vector<int> &nums, int i, int j) { |  | ||||||
|         int tmp = nums[i]; |  | ||||||
|         nums[i] = nums[j]; |  | ||||||
|         nums[j] = tmp; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     /* 選取三個候選元素的中位數 */ |     /* 選取三個候選元素的中位數 */ | ||||||
|     static int medianThree(vector<int> &nums, int left, int mid, int right) { |     static int medianThree(vector<int> &nums, int left, int mid, int right) { | ||||||
|         int l = nums[left], m = nums[mid], r = nums[right]; |         int l = nums[left], m = nums[mid], r = nums[right]; | ||||||
| @ -70,18 +56,18 @@ class QuickSortMedian { | |||||||
|         // 選取三個候選元素的中位數 |         // 選取三個候選元素的中位數 | ||||||
|         int med = medianThree(nums, left, (left + right) / 2, right); |         int med = medianThree(nums, left, (left + right) / 2, right); | ||||||
|         // 將中位數交換至陣列最左端 |         // 將中位數交換至陣列最左端 | ||||||
|         swap(nums, left, med); |         swap(nums[left], nums[med]); | ||||||
|         // 以 nums[left] 為基準數 |         // 以 nums[left] 為基準數 | ||||||
|         int i = left, j = right; |         int i = left, j = right; | ||||||
|         while (i < j) { |         while (i < j) { | ||||||
|             while (i < j && nums[j] >= nums[left]) |             while (i < j && nums[j] >= nums[left]) | ||||||
|                 j--; // 從右向左找首個小於基準數的元素 |                 j--;                // 從右向左找首個小於基準數的元素 | ||||||
|             while (i < j && nums[i] <= nums[left]) |             while (i < j && nums[i] <= nums[left]) | ||||||
|                 i++;          // 從左向右找首個大於基準數的元素 |                 i++;                // 從左向右找首個大於基準數的元素 | ||||||
|             swap(nums, i, j); // 交換這兩個元素 |             swap(nums[i], nums[j]); // 交換這兩個元素 | ||||||
|         } |         } | ||||||
|         swap(nums, i, left); // 將基準數交換至兩子陣列的分界線 |         swap(nums[i], nums[left]);  // 將基準數交換至兩子陣列的分界線 | ||||||
|         return i;            // 返回基準數的索引 |         return i;                   // 返回基準數的索引 | ||||||
|     } |     } | ||||||
|  |  | ||||||
|   public: |   public: | ||||||
| @ -101,26 +87,19 @@ class QuickSortMedian { | |||||||
| /* 快速排序類別(尾遞迴最佳化) */ | /* 快速排序類別(尾遞迴最佳化) */ | ||||||
| class QuickSortTailCall { | class QuickSortTailCall { | ||||||
|   private: |   private: | ||||||
|     /* 元素交換 */ |  | ||||||
|     static void swap(vector<int> &nums, int i, int j) { |  | ||||||
|         int tmp = nums[i]; |  | ||||||
|         nums[i] = nums[j]; |  | ||||||
|         nums[j] = tmp; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     /* 哨兵劃分 */ |     /* 哨兵劃分 */ | ||||||
|     static int partition(vector<int> &nums, int left, int right) { |     static int partition(vector<int> &nums, int left, int right) { | ||||||
|         // 以 nums[left] 為基準數 |         // 以 nums[left] 為基準數 | ||||||
|         int i = left, j = right; |         int i = left, j = right; | ||||||
|         while (i < j) { |         while (i < j) { | ||||||
|             while (i < j && nums[j] >= nums[left]) |             while (i < j && nums[j] >= nums[left]) | ||||||
|                 j--; // 從右向左找首個小於基準數的元素 |                 j--;                // 從右向左找首個小於基準數的元素 | ||||||
|             while (i < j && nums[i] <= nums[left]) |             while (i < j && nums[i] <= nums[left]) | ||||||
|                 i++;          // 從左向右找首個大於基準數的元素 |                 i++;                // 從左向右找首個大於基準數的元素 | ||||||
|             swap(nums, i, j); // 交換這兩個元素 |             swap(nums[i], nums[j]); // 交換這兩個元素 | ||||||
|         } |         } | ||||||
|         swap(nums, i, left); // 將基準數交換至兩子陣列的分界線 |         swap(nums[i], nums[left]);  // 將基準數交換至兩子陣列的分界線 | ||||||
|         return i;            // 返回基準數的索引 |         return i;                   // 返回基準數的索引 | ||||||
|     } |     } | ||||||
|  |  | ||||||
|   public: |   public: | ||||||
|  | |||||||
| @ -70,7 +70,7 @@ class MyList { | |||||||
|     remove(index) { |     remove(index) { | ||||||
|         if (index < 0 || index >= this.#size) throw new Error('索引越界'); |         if (index < 0 || index >= this.#size) throw new Error('索引越界'); | ||||||
|         let num = this.#arr[index]; |         let num = this.#arr[index]; | ||||||
|         // 將將索引 index 之後的元素都向前移動一位 |         // 將索引 index 之後的元素都向前移動一位 | ||||||
|         for (let j = index; j < this.#size - 1; j++) { |         for (let j = index; j < this.#size - 1; j++) { | ||||||
|             this.#arr[j] = this.#arr[j + 1]; |             this.#arr[j] = this.#arr[j + 1]; | ||||||
|         } |         } | ||||||
|  | |||||||
| @ -16,11 +16,7 @@ fn backtrack( | |||||||
| ) { | ) { | ||||||
|     // 當放置完所有行時,記錄解 |     // 當放置完所有行時,記錄解 | ||||||
|     if row == n { |     if row == n { | ||||||
|         let mut copy_state: Vec<Vec<String>> = Vec::new(); |         res.push(state.clone()); | ||||||
|         for s_row in state.clone() { |  | ||||||
|             copy_state.push(s_row); |  | ||||||
|         } |  | ||||||
|         res.push(copy_state); |  | ||||||
|         return; |         return; | ||||||
|     } |     } | ||||||
|     // 走訪所有列 |     // 走訪所有列 | ||||||
| @ -31,12 +27,12 @@ fn backtrack( | |||||||
|         // 剪枝:不允許該格子所在列、主對角線、次對角線上存在皇后 |         // 剪枝:不允許該格子所在列、主對角線、次對角線上存在皇后 | ||||||
|         if !cols[col] && !diags1[diag1] && !diags2[diag2] { |         if !cols[col] && !diags1[diag1] && !diags2[diag2] { | ||||||
|             // 嘗試:將皇后放置在該格子 |             // 嘗試:將皇后放置在該格子 | ||||||
|             state.get_mut(row).unwrap()[col] = "Q".into(); |             state[row][col] = "Q".into(); | ||||||
|             (cols[col], diags1[diag1], diags2[diag2]) = (true, true, true); |             (cols[col], diags1[diag1], diags2[diag2]) = (true, true, true); | ||||||
|             // 放置下一行 |             // 放置下一行 | ||||||
|             backtrack(row + 1, n, state, res, cols, diags1, diags2); |             backtrack(row + 1, n, state, res, cols, diags1, diags2); | ||||||
|             // 回退:將該格子恢復為空位 |             // 回退:將該格子恢復為空位 | ||||||
|             state.get_mut(row).unwrap()[col] = "#".into(); |             state[row][col] = "#".into(); | ||||||
|             (cols[col], diags1[diag1], diags2[diag2]) = (false, false, false); |             (cols[col], diags1[diag1], diags2[diag2]) = (false, false, false); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| @ -45,14 +41,7 @@ fn backtrack( | |||||||
| /* 求解 n 皇后 */ | /* 求解 n 皇后 */ | ||||||
| fn n_queens(n: usize) -> Vec<Vec<Vec<String>>> { | fn n_queens(n: usize) -> Vec<Vec<Vec<String>>> { | ||||||
|     // 初始化 n*n 大小的棋盤,其中 'Q' 代表皇后,'#' 代表空位 |     // 初始化 n*n 大小的棋盤,其中 'Q' 代表皇后,'#' 代表空位 | ||||||
|     let mut state: Vec<Vec<String>> = Vec::new(); |     let mut state: Vec<Vec<String>> = vec![vec!["#".to_string(); n]; n]; | ||||||
|     for _ in 0..n { |  | ||||||
|         let mut row: Vec<String> = Vec::new(); |  | ||||||
|         for _ in 0..n { |  | ||||||
|             row.push("#".into()); |  | ||||||
|         } |  | ||||||
|         state.push(row); |  | ||||||
|     } |  | ||||||
|     let mut cols = vec![false; n]; // 記錄列是否有皇后 |     let mut cols = vec![false; n]; // 記錄列是否有皇后 | ||||||
|     let mut diags1 = vec![false; 2 * n - 1]; // 記錄主對角線上是否有皇后 |     let mut diags1 = vec![false; 2 * n - 1]; // 記錄主對角線上是否有皇后 | ||||||
|     let mut diags2 = vec![false; 2 * n - 1]; // 記錄次對角線上是否有皇后 |     let mut diags2 = vec![false; 2 * n - 1]; // 記錄次對角線上是否有皇后 | ||||||
|  | |||||||
| @ -6,7 +6,7 @@ | |||||||
|  |  | ||||||
| /* 回溯演算法:子集和 I */ | /* 回溯演算法:子集和 I */ | ||||||
| fn backtrack( | fn backtrack( | ||||||
|     mut state: Vec<i32>, |     state: &mut Vec<i32>, | ||||||
|     target: i32, |     target: i32, | ||||||
|     choices: &[i32], |     choices: &[i32], | ||||||
|     start: usize, |     start: usize, | ||||||
| @ -14,7 +14,7 @@ fn backtrack( | |||||||
| ) { | ) { | ||||||
|     // 子集和等於 target 時,記錄解 |     // 子集和等於 target 時,記錄解 | ||||||
|     if target == 0 { |     if target == 0 { | ||||||
|         res.push(state); |         res.push(state.clone()); | ||||||
|         return; |         return; | ||||||
|     } |     } | ||||||
|     // 走訪所有選擇 |     // 走訪所有選擇 | ||||||
| @ -28,7 +28,7 @@ fn backtrack( | |||||||
|         // 嘗試:做出選擇,更新 target, start |         // 嘗試:做出選擇,更新 target, start | ||||||
|         state.push(choices[i]); |         state.push(choices[i]); | ||||||
|         // 進行下一輪選擇 |         // 進行下一輪選擇 | ||||||
|         backtrack(state.clone(), target - choices[i], choices, i, res); |         backtrack(state, target - choices[i], choices, i, res); | ||||||
|         // 回退:撤銷選擇,恢復到之前的狀態 |         // 回退:撤銷選擇,恢復到之前的狀態 | ||||||
|         state.pop(); |         state.pop(); | ||||||
|     } |     } | ||||||
| @ -36,11 +36,11 @@ fn backtrack( | |||||||
|  |  | ||||||
| /* 求解子集和 I */ | /* 求解子集和 I */ | ||||||
| fn subset_sum_i(nums: &mut [i32], target: i32) -> Vec<Vec<i32>> { | fn subset_sum_i(nums: &mut [i32], target: i32) -> Vec<Vec<i32>> { | ||||||
|     let state = Vec::new(); // 狀態(子集) |     let mut state = Vec::new(); // 狀態(子集) | ||||||
|     nums.sort(); // 對 nums 進行排序 |     nums.sort(); // 對 nums 進行排序 | ||||||
|     let start = 0; // 走訪起始點 |     let start = 0; // 走訪起始點 | ||||||
|     let mut res = Vec::new(); // 結果串列(子集串列) |     let mut res = Vec::new(); // 結果串列(子集串列) | ||||||
|     backtrack(state, target, nums, start, &mut res); |     backtrack(&mut state, target, nums, start, &mut res); | ||||||
|     res |     res | ||||||
| } | } | ||||||
|  |  | ||||||
|  | |||||||
| @ -6,7 +6,7 @@ | |||||||
|  |  | ||||||
| /* 回溯演算法:子集和 I */ | /* 回溯演算法:子集和 I */ | ||||||
| fn backtrack( | fn backtrack( | ||||||
|     mut state: Vec<i32>, |     state: &mut Vec<i32>, | ||||||
|     target: i32, |     target: i32, | ||||||
|     total: i32, |     total: i32, | ||||||
|     choices: &[i32], |     choices: &[i32], | ||||||
| @ -14,7 +14,7 @@ fn backtrack( | |||||||
| ) { | ) { | ||||||
|     // 子集和等於 target 時,記錄解 |     // 子集和等於 target 時,記錄解 | ||||||
|     if total == target { |     if total == target { | ||||||
|         res.push(state); |         res.push(state.clone()); | ||||||
|         return; |         return; | ||||||
|     } |     } | ||||||
|     // 走訪所有選擇 |     // 走訪所有選擇 | ||||||
| @ -26,7 +26,7 @@ fn backtrack( | |||||||
|         // 嘗試:做出選擇,更新元素和 total |         // 嘗試:做出選擇,更新元素和 total | ||||||
|         state.push(choices[i]); |         state.push(choices[i]); | ||||||
|         // 進行下一輪選擇 |         // 進行下一輪選擇 | ||||||
|         backtrack(state.clone(), target, total + choices[i], choices, res); |         backtrack(state, target, total + choices[i], choices, res); | ||||||
|         // 回退:撤銷選擇,恢復到之前的狀態 |         // 回退:撤銷選擇,恢復到之前的狀態 | ||||||
|         state.pop(); |         state.pop(); | ||||||
|     } |     } | ||||||
| @ -34,10 +34,10 @@ fn backtrack( | |||||||
|  |  | ||||||
| /* 求解子集和 I(包含重複子集) */ | /* 求解子集和 I(包含重複子集) */ | ||||||
| fn subset_sum_i_naive(nums: &[i32], target: i32) -> Vec<Vec<i32>> { | fn subset_sum_i_naive(nums: &[i32], target: i32) -> Vec<Vec<i32>> { | ||||||
|     let state = Vec::new(); // 狀態(子集) |     let mut state = Vec::new(); // 狀態(子集) | ||||||
|     let total = 0; // 子集和 |     let total = 0; // 子集和 | ||||||
|     let mut res = Vec::new(); // 結果串列(子集串列) |     let mut res = Vec::new(); // 結果串列(子集串列) | ||||||
|     backtrack(state, target, total, nums, &mut res); |     backtrack(&mut state, target, total, nums, &mut res); | ||||||
|     res |     res | ||||||
| } | } | ||||||
|  |  | ||||||
|  | |||||||
| @ -6,7 +6,7 @@ | |||||||
|  |  | ||||||
| /* 回溯演算法:子集和 II */ | /* 回溯演算法:子集和 II */ | ||||||
| fn backtrack( | fn backtrack( | ||||||
|     mut state: Vec<i32>, |     state: &mut Vec<i32>, | ||||||
|     target: i32, |     target: i32, | ||||||
|     choices: &[i32], |     choices: &[i32], | ||||||
|     start: usize, |     start: usize, | ||||||
| @ -14,7 +14,7 @@ fn backtrack( | |||||||
| ) { | ) { | ||||||
|     // 子集和等於 target 時,記錄解 |     // 子集和等於 target 時,記錄解 | ||||||
|     if target == 0 { |     if target == 0 { | ||||||
|         res.push(state); |         res.push(state.clone()); | ||||||
|         return; |         return; | ||||||
|     } |     } | ||||||
|     // 走訪所有選擇 |     // 走訪所有選擇 | ||||||
| @ -33,7 +33,7 @@ fn backtrack( | |||||||
|         // 嘗試:做出選擇,更新 target, start |         // 嘗試:做出選擇,更新 target, start | ||||||
|         state.push(choices[i]); |         state.push(choices[i]); | ||||||
|         // 進行下一輪選擇 |         // 進行下一輪選擇 | ||||||
|         backtrack(state.clone(), target - choices[i], choices, i + 1, res); |         backtrack(state, target - choices[i], choices, i + 1, res); | ||||||
|         // 回退:撤銷選擇,恢復到之前的狀態 |         // 回退:撤銷選擇,恢復到之前的狀態 | ||||||
|         state.pop(); |         state.pop(); | ||||||
|     } |     } | ||||||
| @ -41,11 +41,11 @@ fn backtrack( | |||||||
|  |  | ||||||
| /* 求解子集和 II */ | /* 求解子集和 II */ | ||||||
| fn subset_sum_ii(nums: &mut [i32], target: i32) -> Vec<Vec<i32>> { | fn subset_sum_ii(nums: &mut [i32], target: i32) -> Vec<Vec<i32>> { | ||||||
|     let state = Vec::new(); // 狀態(子集) |     let mut state = Vec::new(); // 狀態(子集) | ||||||
|     nums.sort(); // 對 nums 進行排序 |     nums.sort(); // 對 nums 進行排序 | ||||||
|     let start = 0; // 走訪起始點 |     let start = 0; // 走訪起始點 | ||||||
|     let mut res = Vec::new(); // 結果串列(子集串列) |     let mut res = Vec::new(); // 結果串列(子集串列) | ||||||
|     backtrack(state, target, nums, start, &mut res); |     backtrack(&mut state, target, nums, start, &mut res); | ||||||
|     res |     res | ||||||
| } | } | ||||||
|  |  | ||||||
|  | |||||||
| @ -29,7 +29,7 @@ impl<T> ListNode<T> { | |||||||
|         for item in array.iter().rev() { |         for item in array.iter().rev() { | ||||||
|             let node = Rc::new(RefCell::new(ListNode { |             let node = Rc::new(RefCell::new(ListNode { | ||||||
|                 val: *item, |                 val: *item, | ||||||
|                 next: head.clone(), |                 next: head.take(), | ||||||
|             })); |             })); | ||||||
|             head = Some(node); |             head = Some(node); | ||||||
|         } |         } | ||||||
| @ -44,14 +44,14 @@ impl<T> ListNode<T> { | |||||||
|         T: std::hash::Hash + Eq + Copy + Clone, |         T: std::hash::Hash + Eq + Copy + Clone, | ||||||
|     { |     { | ||||||
|         let mut hashmap = HashMap::new(); |         let mut hashmap = HashMap::new(); | ||||||
|         if let Some(node) = linked_list { |         let mut node = linked_list; | ||||||
|             let mut current = Some(node.clone()); |  | ||||||
|             while let Some(cur) = current { |         while let Some(cur) = node { | ||||||
|                 let borrow = cur.borrow(); |             let borrow = cur.borrow(); | ||||||
|                 hashmap.insert(borrow.val.clone(), cur.clone()); |             hashmap.insert(borrow.val.clone(), cur.clone()); | ||||||
|                 current = borrow.next.clone(); |             node = borrow.next.clone(); | ||||||
|             } |  | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         hashmap |         hashmap | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  | |||||||
| @ -72,23 +72,21 @@ pub fn vec_to_tree(arr: Vec<Option<i32>>) -> Option<Rc<RefCell<TreeNode>>> { | |||||||
| } | } | ||||||
|  |  | ||||||
| /* 將二元樹序列化為串列:遞迴 */ | /* 將二元樹序列化為串列:遞迴 */ | ||||||
| fn tree_to_vec_dfs(root: Option<Rc<RefCell<TreeNode>>>, i: usize, res: &mut Vec<Option<i32>>) { | fn tree_to_vec_dfs(root: Option<&Rc<RefCell<TreeNode>>>, i: usize, res: &mut Vec<Option<i32>>) { | ||||||
|     if root.is_none() { |     if let Some(root) = root { | ||||||
|         return; |         // i + 1 is the minimum valid size to access index i | ||||||
|  |         while res.len() < i + 1 { | ||||||
|  |             res.push(None); | ||||||
|  |         } | ||||||
|  |         res[i] = Some(root.borrow().val); | ||||||
|  |         tree_to_vec_dfs(root.borrow().left.as_ref(), 2 * i + 1, res); | ||||||
|  |         tree_to_vec_dfs(root.borrow().right.as_ref(), 2 * i + 2, res); | ||||||
|     } |     } | ||||||
|     let root = root.unwrap(); |  | ||||||
|     // i + 1 is the minimum valid size to access index i |  | ||||||
|     while res.len() < i + 1 { |  | ||||||
|         res.push(None); |  | ||||||
|     } |  | ||||||
|     res[i] = Some(root.borrow().val); |  | ||||||
|     tree_to_vec_dfs(root.borrow().left.clone(), 2 * i + 1, res); |  | ||||||
|     tree_to_vec_dfs(root.borrow().right.clone(), 2 * i + 2, res); |  | ||||||
| } | } | ||||||
|  |  | ||||||
| /* 將二元樹序列化為串列 */ | /* 將二元樹序列化為串列 */ | ||||||
| pub fn tree_to_vec(root: Option<Rc<RefCell<TreeNode>>>) -> Vec<Option<i32>> { | pub fn tree_to_vec(root: Option<Rc<RefCell<TreeNode>>>) -> Vec<Option<i32>> { | ||||||
|     let mut res = vec![]; |     let mut res = vec![]; | ||||||
|     tree_to_vec_dfs(root, 0, &mut res); |     tree_to_vec_dfs(root.as_ref(), 0, &mut res); | ||||||
|     res |     res | ||||||
| } | } | ||||||
|  | |||||||
| @ -635,8 +635,8 @@ | |||||||
|     /* 雙向鏈結串列節點類別 */ |     /* 雙向鏈結串列節點類別 */ | ||||||
|     class ListNode { |     class ListNode { | ||||||
|         int val;        // 節點值 |         int val;        // 節點值 | ||||||
|         ListNode next;  // 指向後繼節點的引用 |         ListNode? next;  // 指向後繼節點的引用 | ||||||
|         ListNode prev;  // 指向前驅節點的引用 |         ListNode? prev;  // 指向前驅節點的引用 | ||||||
|         ListNode(this.val, [this.next, this.prev]);  // 建構子 |         ListNode(this.val, [this.next, this.prev]);  // 建構子 | ||||||
|     } |     } | ||||||
|     ``` |     ``` | ||||||
|  | |||||||
| @ -651,7 +651,7 @@ | |||||||
|  |  | ||||||
| ### 完全二元樹 | ### 完全二元樹 | ||||||
|  |  | ||||||
| 如下圖所示,<u>完全二元樹(complete binary tree)</u>只有最底層的節點未被填滿,且最底層節點儘量靠左填充。 | 如下圖所示,<u>完全二元樹(complete binary tree)</u>只有最底層的節點未被填滿,且最底層節點儘量靠左填充。請注意,完美二元樹也是一棵完全二元樹。 | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  | |||||||
| @ -1,5 +1,5 @@ | |||||||
| # Hello 演算法 | # Hello 演算法 | ||||||
|  |  | ||||||
| 動畫圖解、一鍵執行的資料結構與演算法教程 | 動畫圖解、一鍵執行的資料結構與演算法教程。 | ||||||
|  |  | ||||||
| [開始閱讀](chapter_hello_algo/) | [開始閱讀](chapter_hello_algo/) | ||||||
|  | |||||||
		Reference in New Issue
	
	Block a user
	 Yudong Jin
					Yudong Jin