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:
Yudong Jin
2023-12-28 18:06:09 +08:00
committed by GitHub
parent 19dde675df
commit f68bbb0d59
261 changed files with 643 additions and 647 deletions

View File

@@ -30,7 +30,7 @@ class MyList {
/* 访问元素 */
public int Get(int index) {
// 索引如果越界则抛出异常,下同
// 索引如果越界则抛出异常,下同
if (index < 0 || index >= arrSize)
throw new IndexOutOfRangeException("索引越界");
return arr[index];
@@ -80,13 +80,13 @@ class MyList {
}
// 更新元素数量
arrSize--;
// 返回被删除元素
// 返回被删除元素
return num;
}
/* 列表扩容 */
public void ExtendCapacity() {
// 新建一个长度为 arrCapacity * extendRatio 的数组,并将原数组拷贝到新数组
// 新建一个长度为 arrCapacity * extendRatio 的数组,并将原数组复制到新数组
Array.Resize(ref arr, arrCapacity * extendRatio);
// 更新列表容量
arrCapacity = arr.Length;

View File

@@ -21,10 +21,10 @@ public class n_queens {
}
// 遍历所有列
for (int col = 0; col < n; col++) {
// 计算该格子对应的主对角线和对角线
// 计算该格子对应的主对角线和对角线
int diag1 = row - col + n - 1;
int diag2 = row + col;
// 剪枝:不允许该格子所在列、主对角线、对角线上存在皇后
// 剪枝:不允许该格子所在列、主对角线、对角线上存在皇后
if (!cols[col] && !diags1[diag1] && !diags2[diag2]) {
// 尝试:将皇后放置在该格子
state[row][col] = "Q";
@@ -51,7 +51,7 @@ public class n_queens {
}
bool[] cols = new bool[n]; // 记录列是否有皇后
bool[] diags1 = new bool[2 * n - 1]; // 记录主对角线上是否有皇后
bool[] diags2 = new bool[2 * n - 1]; // 记录对角线上是否有皇后
bool[] diags2 = new bool[2 * n - 1]; // 记录对角线上是否有皇后
List<List<List<string>>> res = [];
Backtrack(0, n, state, res, cols, diags1, diags2);

View File

@@ -7,7 +7,7 @@
namespace hello_algo.chapter_graph;
public class graph_bfs {
/* 广度优先遍历 BFS */
/* 广度优先遍历 */
// 使用邻接表来表示图,以便获取指定顶点的所有邻接顶点
List<Vertex> GraphBFS(GraphAdjList graph, Vertex startVet) {
// 顶点遍历序列
@@ -50,7 +50,7 @@ public class graph_bfs {
Console.WriteLine("\n初始化后图为");
graph.Print();
/* 广度优先遍历 BFS */
/* 广度优先遍历 */
List<Vertex> res = GraphBFS(graph, v[0]);
Console.WriteLine("\n广度优先遍历BFS顶点序列为");
Console.WriteLine(string.Join(" ", Vertex.VetsToVals(res)));

View File

@@ -7,7 +7,7 @@
namespace hello_algo.chapter_graph;
public class graph_dfs {
/* 深度优先遍历 DFS 辅助函数 */
/* 深度优先遍历辅助函数 */
void DFS(GraphAdjList graph, HashSet<Vertex> visited, List<Vertex> res, Vertex vet) {
res.Add(vet); // 记录访问顶点
visited.Add(vet); // 标记该顶点已被访问
@@ -21,7 +21,7 @@ public class graph_dfs {
}
}
/* 深度优先遍历 DFS */
/* 深度优先遍历 */
// 使用邻接表来表示图,以便获取指定顶点的所有邻接顶点
List<Vertex> GraphDFS(GraphAdjList graph, Vertex startVet) {
// 顶点遍历序列
@@ -46,7 +46,7 @@ public class graph_dfs {
Console.WriteLine("\n初始化后图为");
graph.Print();
/* 深度优先遍历 DFS */
/* 深度优先遍历 */
List<Vertex> res = GraphDFS(graph, v[0]);
Console.WriteLine("\n深度优先遍历DFS顶点序列为");
Console.WriteLine(string.Join(" ", Vertex.VetsToVals(res)));

View File

@@ -9,7 +9,7 @@ namespace hello_algo.chapter_greedy;
public class max_capacity {
/* 最大容量:贪心 */
int MaxCapacity(int[] ht) {
// 初始化 i, j 分列数组两端
// 初始化 i, j,使其分列数组两端
int i = 0, j = ht.Length - 1;
// 初始最大容量为 0
int res = 0;

View File

@@ -107,7 +107,7 @@ public class array_hash_map {
map.Print();
/* 查询操作 */
// 向哈希表输入键 key ,得到值 value
// 向哈希表输入键 key ,得到值 value
string? name = map.Get(15937);
Console.WriteLine("\n输入学号 15937 ,查询到姓名 " + name);

View File

@@ -24,7 +24,7 @@ public class hash_map {
PrintUtil.PrintHashMap(map);
/* 查询操作 */
// 向哈希表输入键 key ,得到值 value
// 向哈希表输入键 key ,得到值 value
string name = map[15937];
Console.WriteLine("\n输入学号 15937 ,查询到姓名 " + name);

View File

@@ -39,13 +39,13 @@ class HashMapChaining {
/* 查询操作 */
public string? Get(int key) {
int index = HashFunc(key);
// 遍历桶,若找到 key 则返回对应 val
// 遍历桶,若找到 key 则返回对应 val
foreach (Pair pair in buckets[index]) {
if (pair.key == key) {
return pair.val;
}
}
// 若未找到 key 则返回 null
// 若未找到 key 则返回 null
return null;
}
@@ -131,7 +131,7 @@ public class hash_map_chaining {
map.Print();
/* 查询操作 */
// 向哈希表输入键 key ,得到值 value
// 向哈希表输入键 key ,得到值 value
string? name = map.Get(13276);
Console.WriteLine("\n输入学号 13276 ,查询到姓名 " + name);

View File

@@ -37,9 +37,9 @@ class HashMapOpenAddressing {
int firstTombstone = -1;
// 线性探测,当遇到空桶时跳出
while (buckets[index] != null) {
// 若遇到 key ,返回对应桶索引
// 若遇到 key ,返回对应桶索引
if (buckets[index].key == key) {
// 若之前遇到了删除标记,则将键值对移动至该索引
// 若之前遇到了删除标记,则将键值对移动至该索引
if (firstTombstone != -1) {
buckets[firstTombstone] = buckets[index];
buckets[index] = TOMBSTONE;
@@ -51,7 +51,7 @@ class HashMapOpenAddressing {
if (firstTombstone == -1 && buckets[index] == TOMBSTONE) {
firstTombstone = index;
}
// 计算桶索引,越过尾部返回头部
// 计算桶索引,越过尾部返回头部
index = (index + 1) % capacity;
}
// 若 key 不存在,则返回添加点的索引
@@ -146,7 +146,7 @@ public class hash_map_open_addressing {
map.Print();
/* 查询操作 */
// 向哈希表输入键 key ,得到值 value
// 向哈希表输入键 key ,得到值 value
string? name = map.Get(13276);
Console.WriteLine("\n输入学号 13276 ,查询到姓名 " + name);

View File

@@ -27,17 +27,17 @@ class MaxHeap {
}
}
/* 获取左子节点索引 */
/* 获取左子节点索引 */
int Left(int i) {
return 2 * i + 1;
}
/* 获取右子节点索引 */
/* 获取右子节点索引 */
int Right(int i) {
return 2 * i + 2;
}
/* 获取父节点索引 */
/* 获取父节点索引 */
int Parent(int i) {
return (i - 1) / 2; // 向下整除
}

View File

@@ -34,7 +34,7 @@ public class bubble_sort {
flag = true; // 记录交换元素
}
}
if (!flag) break; // 此轮冒泡未交换任何元素,直接跳出
if (!flag) break; // 此轮冒泡未交换任何元素,直接跳出
}
}

View File

@@ -9,12 +9,12 @@ namespace hello_algo.chapter_sorting;
public class merge_sort {
/* 合并左子数组和右子数组 */
void Merge(int[] nums, int left, int mid, int right) {
// 左子数组区间 [left, mid], 右子数组区间 [mid+1, right]
// 左子数组区间 [left, mid], 右子数组区间 [mid+1, right]
// 创建一个临时数组 tmp ,用于存放合并后的结果
int[] tmp = new int[right - left + 1];
// 初始化左子数组和右子数组的起始索引
int i = left, j = mid + 1, k = 0;
// 当左右子数组都还有元素时,比较并将较小的元素复制到临时数组中
// 当左右子数组都还有元素时,进行比较并将较小的元素复制到临时数组中
while (i <= mid && j <= right) {
if (nums[i] <= nums[j])
tmp[k++] = nums[i++];

View File

@@ -47,7 +47,7 @@ class QuickSortMedian {
(nums[j], nums[i]) = (nums[i], nums[j]);
}
/* 选取三个元素的中位数 */
/* 选取三个候选元素的中位数 */
static int MedianThree(int[] nums, int left, int mid, int right) {
// 此处使用异或运算来简化代码
// 异或规则为 0 ^ 0 = 1 ^ 1 = 0, 0 ^ 1 = 1 ^ 0 = 1

View File

@@ -48,7 +48,7 @@ public class ArrayDeque {
return;
}
// 队首指针向左移动一位
// 通过取余操作实现 front 越过数组头部后回到尾部
// 通过取余操作实现 front 越过数组头部后回到尾部
front = Index(front - 1);
// 将 num 添加至队首
nums[front] = num;
@@ -61,7 +61,7 @@ public class ArrayDeque {
Console.WriteLine("双向队列已满");
return;
}
// 计算尾指针,指向队尾索引 + 1
// 计算尾指针,指向队尾索引 + 1
int rear = Index(front + queSize);
// 将 num 添加至队尾
nums[rear] = num;

View File

@@ -38,8 +38,8 @@ class ArrayQueue {
Console.WriteLine("队列已满");
return;
}
// 计算尾指针,指向队尾索引 + 1
// 通过取余操作实现 rear 越过数组尾部后回到头部
// 计算尾指针,指向队尾索引 + 1
// 通过取余操作实现 rear 越过数组尾部后回到头部
int rear = (front + queSize) % Capacity();
// 将 num 添加至队尾
nums[rear] = num;
@@ -49,7 +49,7 @@ class ArrayQueue {
/* 出队 */
public int Pop() {
int num = Peek();
// 队首指针向后移动一位,若越过尾部则返回到数组头部
// 队首指针向后移动一位,若越过尾部则返回到数组头部
front = (front + 1) % Capacity();
queSize--;
return num;

View File

@@ -28,7 +28,7 @@ class LinkedListQueue {
/* 入队 */
public void Push(int num) {
// 尾节点后添加 num
// 尾节点后添加 num
ListNode node = new(num);
// 如果队列为空,则令头、尾节点都指向该节点
if (front == null) {

View File

@@ -96,7 +96,7 @@ class AVLTree {
/* 递归插入节点(辅助方法) */
TreeNode? InsertHelper(TreeNode? node, int val) {
if (node == null) return new TreeNode(val);
/* 1. 查找插入位置并插入节点 */
/* 1. 查找插入位置并插入节点 */
if (val < node.val)
node.left = InsertHelper(node.left, val);
else if (val > node.val)
@@ -118,7 +118,7 @@ class AVLTree {
/* 递归删除节点(辅助方法) */
TreeNode? RemoveHelper(TreeNode? node, int val) {
if (node == null) return null;
/* 1. 查找节点并删除 */
/* 1. 查找节点并删除 */
if (val < node.val)
node.left = RemoveHelper(node.left, val);
else if (val > node.val)