mirror of
https://github.com/krahets/hello-algo.git
synced 2025-11-02 12:58:42 +08:00
Update the book based on the revised second edition (#1014)
* Revised the book * Update the book with the second revised edition * Revise base on the manuscript of the first edition
This commit is contained in:
@ -41,7 +41,7 @@ impl MyList {
|
||||
|
||||
/* 访问元素 */
|
||||
pub fn get(&self, index: usize) -> i32 {
|
||||
// 索引如果越界则抛出异常,下同
|
||||
// 索引如果越界,则抛出异常,下同
|
||||
if index >= self.size {panic!("索引越界")};
|
||||
return self.arr[index];
|
||||
}
|
||||
@ -89,13 +89,13 @@ impl MyList {
|
||||
}
|
||||
// 更新元素数量
|
||||
self.size -= 1;
|
||||
// 返回被删除元素
|
||||
// 返回被删除的元素
|
||||
return num;
|
||||
}
|
||||
|
||||
/* 列表扩容 */
|
||||
pub fn extend_capacity(&mut self) {
|
||||
// 新建一个长度为原数组 extend_ratio 倍的新数组,并将原数组拷贝到新数组
|
||||
// 新建一个长度为原数组 extend_ratio 倍的新数组,并将原数组复制到新数组
|
||||
let new_capacity = self.capacity * self.extend_ratio;
|
||||
self.arr.resize(new_capacity, 0);
|
||||
// 更新列表容量
|
||||
|
||||
@ -18,10 +18,10 @@ fn backtrack(row: usize, n: usize, state: &mut Vec<Vec<String>>, res: &mut Vec<V
|
||||
}
|
||||
// 遍历所有列
|
||||
for col in 0..n {
|
||||
// 计算该格子对应的主对角线和副对角线
|
||||
// 计算该格子对应的主对角线和次对角线
|
||||
let diag1 = row + n - 1 - col;
|
||||
let diag2 = row + col;
|
||||
// 剪枝:不允许该格子所在列、主对角线、副对角线上存在皇后
|
||||
// 剪枝:不允许该格子所在列、主对角线、次对角线上存在皇后
|
||||
if !cols[col] && !diags1[diag1] && !diags2[diag2] {
|
||||
// 尝试:将皇后放置在该格子
|
||||
state.get_mut(row).unwrap()[col] = "Q".into();
|
||||
@ -48,7 +48,7 @@ fn n_queens(n: usize) -> Vec<Vec<Vec<String>>> {
|
||||
}
|
||||
let mut cols = vec![false; n]; // 记录列是否有皇后
|
||||
let mut diags1 = vec![false; 2 * n - 1]; // 记录主对角线上是否有皇后
|
||||
let mut diags2 = vec![false; 2 * n - 1]; // 记录副对角线上是否有皇后
|
||||
let mut diags2 = vec![false; 2 * n - 1]; // 记录次对角线上是否有皇后
|
||||
let mut res: Vec<Vec<Vec<String>>> = Vec::new();
|
||||
|
||||
backtrack(0, n, &mut state, &mut res, &mut cols, &mut diags1, &mut diags2);
|
||||
|
||||
@ -10,7 +10,7 @@ use std::collections::{HashSet, VecDeque};
|
||||
use graph_adjacency_list::GraphAdjList;
|
||||
use graph_adjacency_list::{Vertex, vets_to_vals, vals_to_vets};
|
||||
|
||||
/* 广度优先遍历 BFS */
|
||||
/* 广度优先遍历 */
|
||||
// 使用邻接表来表示图,以便获取指定顶点的所有邻接顶点
|
||||
fn graph_bfs(graph: GraphAdjList, start_vet: Vertex) -> Vec<Vertex> {
|
||||
// 顶点遍历序列
|
||||
@ -62,7 +62,7 @@ fn main() {
|
||||
println!("\n初始化后,图为");
|
||||
graph.print();
|
||||
|
||||
/* 广度优先遍历 BFS */
|
||||
/* 广度优先遍历 */
|
||||
let res = graph_bfs(graph, v[0]);
|
||||
println!("\n广度优先遍历(BFS)顶点序列为");
|
||||
println!("{:?}", vets_to_vals(res));
|
||||
|
||||
@ -10,7 +10,7 @@ use std::collections::HashSet;
|
||||
use graph_adjacency_list::GraphAdjList;
|
||||
use graph_adjacency_list::{Vertex, vets_to_vals, vals_to_vets};
|
||||
|
||||
/* 深度优先遍历 DFS 辅助函数 */
|
||||
/* 深度优先遍历辅助函数 */
|
||||
fn dfs(graph: &GraphAdjList, visited: &mut HashSet<Vertex>, res: &mut Vec<Vertex>, vet: Vertex) {
|
||||
res.push(vet); // 记录访问顶点
|
||||
visited.insert(vet); // 标记该顶点已被访问
|
||||
@ -26,7 +26,7 @@ fn dfs(graph: &GraphAdjList, visited: &mut HashSet<Vertex>, res: &mut Vec<Vertex
|
||||
}
|
||||
}
|
||||
|
||||
/* 深度优先遍历 DFS */
|
||||
/* 深度优先遍历 */
|
||||
// 使用邻接表来表示图,以便获取指定顶点的所有邻接顶点
|
||||
fn graph_dfs(graph: GraphAdjList, start_vet: Vertex) -> Vec<Vertex> {
|
||||
// 顶点遍历序列
|
||||
@ -54,7 +54,7 @@ fn main() {
|
||||
println!("\n初始化后,图为");
|
||||
graph.print();
|
||||
|
||||
/* 深度优先遍历 DFS */
|
||||
/* 深度优先遍历 */
|
||||
let res = graph_dfs(graph, v[0]);
|
||||
println!("\n深度优先遍历(DFS)顶点序列为");
|
||||
println!("{:?}", vets_to_vals(res));
|
||||
|
||||
@ -6,7 +6,7 @@
|
||||
|
||||
/* 最大容量:贪心 */
|
||||
fn max_capacity(ht: &[i32]) -> i32 {
|
||||
// 初始化 i, j 分列数组两端
|
||||
// 初始化 i, j,使其分列数组两端
|
||||
let mut i = 0;
|
||||
let mut j = ht.len() - 1;
|
||||
// 初始最大容量为 0
|
||||
|
||||
@ -85,7 +85,7 @@ fn main() {
|
||||
map.print();
|
||||
|
||||
/* 查询操作 */
|
||||
// 向哈希表输入键 key ,得到值 value
|
||||
// 向哈希表中输入键 key ,得到值 value
|
||||
let name = map.get(15937).unwrap();
|
||||
println!("\n输入学号 15937 ,查询到姓名 {}", name);
|
||||
|
||||
|
||||
@ -24,7 +24,7 @@ pub fn main() {
|
||||
print_util::print_hash_map(&map);
|
||||
|
||||
// 查询操作
|
||||
// 向哈希表输入键 key ,得到值 value
|
||||
// 向哈希表中输入键 key ,得到值 value
|
||||
let name = map.get(&15937).copied().unwrap();
|
||||
println!("\n输入学号 15937 ,查询到姓名 {name}");
|
||||
|
||||
|
||||
@ -56,7 +56,7 @@ impl HashMapChaining {
|
||||
}
|
||||
}
|
||||
|
||||
// 若未找到 key 则返回 None
|
||||
// 若未找到 key ,则返回 None
|
||||
None
|
||||
}
|
||||
|
||||
@ -122,14 +122,14 @@ impl HashMapChaining {
|
||||
let index = self.hash_func(key);
|
||||
let bucket = &self.buckets[index];
|
||||
|
||||
// 遍历桶,若找到 key 则返回对应 val
|
||||
// 遍历桶,若找到 key ,则返回对应 val
|
||||
for pair in bucket {
|
||||
if pair.key == key {
|
||||
return Some(&pair.val);
|
||||
}
|
||||
}
|
||||
|
||||
// 若未找到 key 则返回 None
|
||||
// 若未找到 key ,则返回 None
|
||||
None
|
||||
}
|
||||
}
|
||||
@ -150,7 +150,7 @@ pub fn main() {
|
||||
map.print();
|
||||
|
||||
/* 查询操作 */
|
||||
// 向哈希表输入键 key ,得到值 value
|
||||
// 向哈希表中输入键 key ,得到值 value
|
||||
println!("\n输入学号 13276,查询到姓名 {}", match map.get(13276) {
|
||||
Some(value) => value,
|
||||
None => "Not a valid Key"
|
||||
|
||||
@ -64,7 +64,7 @@ impl HashMapOpenAddressing {
|
||||
if first_tombstone == -1 && self.buckets[index] == self.TOMBSTONE {
|
||||
first_tombstone = index as i32;
|
||||
}
|
||||
// 计算桶索引,越过尾部返回头部
|
||||
// 计算桶索引,越过尾部则返回头部
|
||||
index = (index + 1) % self.capacity;
|
||||
}
|
||||
// 若 key 不存在,则返回添加点的索引
|
||||
@ -163,7 +163,7 @@ fn main() {
|
||||
hashmap.print();
|
||||
|
||||
/* 查询操作 */
|
||||
// 向哈希表输入键 key ,得到值 val
|
||||
// 向哈希表中输入键 key ,得到值 val
|
||||
let name = hashmap.get(13276).unwrap();
|
||||
println!("\n输入学号 13276 ,查询到姓名 {}", name);
|
||||
|
||||
|
||||
@ -24,17 +24,17 @@ impl MaxHeap {
|
||||
heap
|
||||
}
|
||||
|
||||
/* 获取左子节点索引 */
|
||||
/* 获取左子节点的索引 */
|
||||
fn left(i: usize) -> usize {
|
||||
2 * i + 1
|
||||
}
|
||||
|
||||
/* 获取右子节点索引 */
|
||||
/* 获取右子节点的索引 */
|
||||
fn right(i: usize) -> usize {
|
||||
2 * i + 2
|
||||
}
|
||||
|
||||
/* 获取父节点索引 */
|
||||
/* 获取父节点的索引 */
|
||||
fn parent(i: usize) -> usize {
|
||||
(i - 1) / 2 // 向下整除
|
||||
}
|
||||
|
||||
@ -37,7 +37,7 @@ fn bubble_sort_with_flag(nums: &mut [i32]) {
|
||||
flag = true; // 记录交换元素
|
||||
}
|
||||
}
|
||||
if !flag {break}; // 此轮冒泡未交换任何元素,直接跳出
|
||||
if !flag {break}; // 此轮“冒泡”未交换任何元素,直接跳出
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -6,13 +6,13 @@
|
||||
|
||||
/* 合并左子数组和右子数组 */
|
||||
fn merge(nums: &mut [i32], left: usize, mid: usize, right: usize) {
|
||||
// 左子数组区间 [left, mid], 右子数组区间 [mid+1, right]
|
||||
// 左子数组区间为 [left, mid], 右子数组区间为 [mid+1, right]
|
||||
// 创建一个临时数组 tmp ,用于存放合并后的结果
|
||||
let tmp_size = right - left + 1;
|
||||
let mut tmp = vec![0; tmp_size];
|
||||
// 初始化左子数组和右子数组的起始索引
|
||||
let (mut i, mut j, mut k) = (left, mid + 1, 0);
|
||||
// 当左右子数组都还有元素时,比较并将较小的元素复制到临时数组中
|
||||
// 当左右子数组都还有元素时,进行比较并将较小的元素复制到临时数组中
|
||||
while i <= mid && j <= right {
|
||||
if nums[i] <= nums[j] {
|
||||
tmp[k] = nums[j];
|
||||
|
||||
@ -44,7 +44,7 @@ impl QuickSort {
|
||||
struct QuickSortMedian;
|
||||
|
||||
impl QuickSortMedian {
|
||||
/* 选取三个元素的中位数 */
|
||||
/* 选取三个候选元素的中位数 */
|
||||
fn median_three(nums: &mut [i32], left: usize, mid: usize, right: usize) -> usize {
|
||||
// 此处使用异或运算来简化代码
|
||||
// 异或规则为 0 ^ 0 = 1 ^ 1 = 0, 0 ^ 1 = 1 ^ 0 = 1
|
||||
|
||||
@ -53,7 +53,7 @@ impl ArrayDeque {
|
||||
return
|
||||
}
|
||||
// 队首指针向左移动一位
|
||||
// 通过取余操作,实现 front 越过数组头部后回到尾部
|
||||
// 通过取余操作实现 front 越过数组头部后回到尾部
|
||||
self.front = self.index(self.front as i32 - 1);
|
||||
// 将 num 添加至队首
|
||||
self.nums[self.front] = num;
|
||||
@ -66,7 +66,7 @@ impl ArrayDeque {
|
||||
println!("双向队列已满");
|
||||
return
|
||||
}
|
||||
// 计算尾指针,指向队尾索引 + 1
|
||||
// 计算队尾指针,指向队尾索引 + 1
|
||||
let rear = self.index(self.front as i32 + self.que_size as i32);
|
||||
// 将 num 添加至队尾
|
||||
self.nums[rear] = num;
|
||||
|
||||
@ -44,8 +44,8 @@ impl ArrayQueue {
|
||||
println!("队列已满");
|
||||
return;
|
||||
}
|
||||
// 计算尾指针,指向队尾索引 + 1
|
||||
// 通过取余操作,实现 rear 越过数组尾部后回到头部
|
||||
// 计算队尾指针,指向队尾索引 + 1
|
||||
// 通过取余操作实现 rear 越过数组尾部后回到头部
|
||||
let rear = (self.front + self.que_size) % self.que_capacity;
|
||||
// 将 num 添加至队尾
|
||||
self.nums[rear as usize] = num;
|
||||
@ -55,7 +55,7 @@ impl ArrayQueue {
|
||||
/* 出队 */
|
||||
fn pop(&mut self) -> i32 {
|
||||
let num = self.peek();
|
||||
// 队首指针向后移动一位,若越过尾部则返回到数组头部
|
||||
// 队首指针向后移动一位,若越过尾部,则返回到数组头部
|
||||
self.front = (self.front + 1) % self.que_capacity;
|
||||
self.que_size -= 1;
|
||||
num
|
||||
|
||||
@ -39,7 +39,7 @@ impl<T: Copy> LinkedListQueue<T> {
|
||||
|
||||
/* 入队 */
|
||||
pub fn push(&mut self, num: T) {
|
||||
// 尾节点后添加 num
|
||||
// 在尾节点后添加 num
|
||||
let new_rear = ListNode::new(num);
|
||||
match self.rear.take() {
|
||||
// 如果队列不为空,则将该节点添加到尾节点后
|
||||
|
||||
@ -137,7 +137,7 @@ impl AVLTree {
|
||||
fn insert_helper(node: OptionTreeNodeRc, val: i32) -> OptionTreeNodeRc {
|
||||
match node {
|
||||
Some(mut node) => {
|
||||
/* 1. 查找插入位置,并插入节点 */
|
||||
/* 1. 查找插入位置并插入节点 */
|
||||
match {
|
||||
let node_val = node.borrow().val;
|
||||
node_val
|
||||
@ -175,7 +175,7 @@ impl AVLTree {
|
||||
fn remove_helper(node: OptionTreeNodeRc, val: i32) -> OptionTreeNodeRc {
|
||||
match node {
|
||||
Some(mut node) => {
|
||||
/* 1. 查找节点,并删除之 */
|
||||
/* 1. 查找节点并删除 */
|
||||
if val < node.borrow().val {
|
||||
let left = node.borrow().left.clone();
|
||||
node.borrow_mut().left = Self::remove_helper(left, val);
|
||||
|
||||
Reference in New Issue
Block a user