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

@ -28,7 +28,7 @@ class MyList {
/* 访问元素 */
public get(index: number): number {
// 索引如果越界则抛出异常,下同
// 索引如果越界则抛出异常,下同
if (index < 0 || index >= this._size) throw new Error('索引越界');
return this.arr[index];
}
@ -74,13 +74,13 @@ class MyList {
}
// 更新元素数量
this._size--;
// 返回被删除元素
// 返回被删除元素
return num;
}
/* 列表扩容 */
public extendCapacity(): void {
// 新建一个长度为 size 的数组,并将原数组拷贝到新数组
// 新建一个长度为 size 的数组,并将原数组复制到新数组
this.arr = this.arr.concat(
new Array(this.capacity() * (this.extendRatio - 1))
);

View File

@ -21,10 +21,10 @@ function backtrack(
}
// 遍历所有列
for (let col = 0; col < n; col++) {
// 计算该格子对应的主对角线和对角线
// 计算该格子对应的主对角线和对角线
const diag1 = row - col + n - 1;
const diag2 = row + col;
// 剪枝:不允许该格子所在列、主对角线、对角线上存在皇后
// 剪枝:不允许该格子所在列、主对角线、对角线上存在皇后
if (!cols[col] && !diags1[diag1] && !diags2[diag2]) {
// 尝试:将皇后放置在该格子
state[row][col] = 'Q';
@ -44,7 +44,7 @@ function nQueens(n: number): string[][][] {
const state = Array.from({ length: n }, () => Array(n).fill('#'));
const cols = Array(n).fill(false); // 记录列是否有皇后
const diags1 = Array(2 * n - 1).fill(false); // 记录主对角线上是否有皇后
const diags2 = Array(2 * n - 1).fill(false); // 记录对角线上是否有皇后
const diags2 = Array(2 * n - 1).fill(false); // 记录对角线上是否有皇后
const res: string[][][] = [];
backtrack(0, n, state, res, cols, diags1, diags2);

View File

@ -7,7 +7,7 @@
import { GraphAdjList } from './graph_adjacency_list';
import { Vertex } from '../modules/Vertex';
/* 广度优先遍历 BFS */
/* 广度优先遍历 */
// 使用邻接表来表示图,以便获取指定顶点的所有邻接顶点
function graphBFS(graph: GraphAdjList, startVet: Vertex): Vertex[] {
// 顶点遍历序列
@ -55,7 +55,7 @@ const graph = new GraphAdjList(edges);
console.log('\n初始化后图为');
graph.print();
/* 广度优先遍历 BFS */
/* 广度优先遍历 */
const res = graphBFS(graph, v[0]);
console.log('\n广度优先遍历BFS顶点序列为');
console.log(Vertex.vetsToVals(res));

View File

@ -7,7 +7,7 @@
import { Vertex } from '../modules/Vertex';
import { GraphAdjList } from './graph_adjacency_list';
/* 深度优先遍历 DFS 辅助函数 */
/* 深度优先遍历辅助函数 */
function dfs(
graph: GraphAdjList,
visited: Set<Vertex>,
@ -26,7 +26,7 @@ function dfs(
}
}
/* 深度优先遍历 DFS */
/* 深度优先遍历 */
// 使用邻接表来表示图,以便获取指定顶点的所有邻接顶点
function graphDFS(graph: GraphAdjList, startVet: Vertex): Vertex[] {
// 顶点遍历序列
@ -52,7 +52,7 @@ const graph = new GraphAdjList(edges);
console.log('\n初始化后图为');
graph.print();
/* 深度优先遍历 DFS */
/* 深度优先遍历 */
const res = graphDFS(graph, v[0]);
console.log('\n深度优先遍历DFS顶点序列为');
console.log(Vertex.vetsToVals(res));

View File

@ -6,7 +6,7 @@
/* 最大容量:贪心 */
function maxCapacity(ht: number[]): number {
// 初始化 i, j 分列数组两端
// 初始化 i, j,使其分列数组两端
let i = 0,
j = ht.length - 1;
// 初始最大容量为 0

View File

@ -106,7 +106,7 @@ console.info('\n添加完成后哈希表为\nKey -> Value');
map.print();
/* 查询操作 */
// 向哈希表输入键 key ,得到值 value
// 向哈希表输入键 key ,得到值 value
let name = map.get(15937);
console.info('\n输入学号 15937 ,查询到姓名 ' + name);

View File

@ -19,7 +19,7 @@ console.info('\n添加完成后哈希表为\nKey -> Value');
console.info(map);
/* 查询操作 */
// 向哈希表输入键 key ,得到值 value
// 向哈希表输入键 key ,得到值 value
let name = map.get(15937);
console.info('\n输入学号 15937 ,查询到姓名 ' + name);

View File

@ -45,13 +45,13 @@ class HashMapChaining {
get(key: number): string | null {
const index = this.#hashFunc(key);
const bucket = this.#buckets[index];
// 遍历桶,若找到 key 则返回对应 val
// 遍历桶,若找到 key 则返回对应 val
for (const pair of bucket) {
if (pair.key === key) {
return pair.val;
}
}
// 若未找到 key 则返回 null
// 若未找到 key 则返回 null
return null;
}
@ -133,7 +133,7 @@ console.log('\n添加完成后哈希表为\nKey -> Value');
map.print();
/* 查询操作 */
// 向哈希表输入键 key ,得到值 value
// 向哈希表输入键 key ,得到值 value
const name = map.get(13276);
console.log('\n输入学号 13276 ,查询到姓名 ' + name);

View File

@ -50,9 +50,9 @@ class HashMapOpenAddressing {
let firstTombstone = -1;
// 线性探测,当遇到空桶时跳出
while (this.buckets[index] !== null) {
// 若遇到 key ,返回对应桶索引
// 若遇到 key ,返回对应桶索引
if (this.buckets[index]!.key === key) {
// 若之前遇到了删除标记,则将键值对移动至该索引
// 若之前遇到了删除标记,则将键值对移动至该索引
if (firstTombstone !== -1) {
this.buckets[firstTombstone] = this.buckets[index];
this.buckets[index] = this.TOMBSTONE;
@ -67,7 +67,7 @@ class HashMapOpenAddressing {
) {
firstTombstone = index;
}
// 计算桶索引,越过尾部返回头部
// 计算桶索引,越过尾部返回头部
index = (index + 1) % this.capacity;
}
// 若 key 不存在,则返回添加点的索引
@ -169,7 +169,7 @@ console.log('\n添加完成后哈希表为\nKey -> Value');
hashmap.print();
// 查询操作
// 向哈希表输入键 key ,得到值 val
// 向哈希表输入键 key ,得到值 val
const name = hashmap.get(13276);
console.log('\n输入学号 13276 ,查询到姓名 ' + name);

View File

@ -19,17 +19,17 @@ class MaxHeap {
}
}
/* 获取左子节点索引 */
/* 获取左子节点索引 */
private left(i: number): number {
return 2 * i + 1;
}
/* 获取右子节点索引 */
/* 获取右子节点索引 */
private right(i: number): number {
return 2 * i + 2;
}
/* 获取父节点索引 */
/* 获取父节点索引 */
private parent(i: number): number {
return Math.floor((i - 1) / 2); // 向下整除
}

View File

@ -35,7 +35,7 @@ function bubbleSortWithFlag(nums: number[]): void {
flag = true; // 记录交换元素
}
}
if (!flag) break; // 此轮冒泡未交换任何元素,直接跳出
if (!flag) break; // 此轮冒泡未交换任何元素,直接跳出
}
}

View File

@ -6,14 +6,14 @@
/* 合并左子数组和右子数组 */
function merge(nums: number[], left: number, mid: number, right: number): void {
// 左子数组区间 [left, mid], 右子数组区间 [mid+1, right]
// 左子数组区间 [left, mid], 右子数组区间 [mid+1, right]
// 创建一个临时数组 tmp ,用于存放合并后的结果
const tmp = new Array(right - left + 1);
// 初始化左子数组和右子数组的起始索引
let i = left,
j = mid + 1,
k = 0;
// 当左右子数组都还有元素时,比较并将较小的元素复制到临时数组中
// 当左右子数组都还有元素时,进行比较并将较小的元素复制到临时数组中
while (i <= mid && j <= right) {
if (nums[i] <= nums[j]) {
tmp[k++] = nums[i++];

View File

@ -55,7 +55,7 @@ class QuickSortMedian {
nums[j] = tmp;
}
/* 选取三个元素的中位数 */
/* 选取三个候选元素的中位数 */
medianThree(
nums: number[],
left: number,

View File

@ -47,7 +47,7 @@ class ArrayDeque {
return;
}
// 队首指针向左移动一位
// 通过取余操作实现 front 越过数组头部后回到尾部
// 通过取余操作实现 front 越过数组头部后回到尾部
this.front = this.index(this.front - 1);
// 将 num 添加至队首
this.nums[this.front] = num;
@ -60,7 +60,7 @@ class ArrayDeque {
console.log('双向队列已满');
return;
}
// 计算尾指针,指向队尾索引 + 1
// 计算尾指针,指向队尾索引 + 1
const rear: number = this.index(this.front + this.queSize);
// 将 num 添加至队尾
this.nums[rear] = num;

View File

@ -36,8 +36,8 @@ class ArrayQueue {
console.log('队列已满');
return;
}
// 计算尾指针,指向队尾索引 + 1
// 通过取余操作实现 rear 越过数组尾部后回到头部
// 计算尾指针,指向队尾索引 + 1
// 通过取余操作实现 rear 越过数组尾部后回到头部
const rear = (this.front + this.queSize) % this.capacity;
// 将 num 添加至队尾
this.nums[rear] = num;
@ -47,7 +47,7 @@ class ArrayQueue {
/* 出队 */
pop(): number {
const num = this.peek();
// 队首指针向后移动一位,若越过尾部则返回到数组头部
// 队首指针向后移动一位,若越过尾部则返回到数组头部
this.front = (this.front + 1) % this.capacity;
this.queSize--;
return num;

View File

@ -29,7 +29,7 @@ class LinkedListQueue {
/* 入队 */
push(num: number): void {
// 尾节点后添加 num
// 尾节点后添加 num
const node = new ListNode(num);
// 如果队列为空,则令头、尾节点都指向该节点
if (!this.front) {

View File

@ -102,7 +102,7 @@ class AVLTree {
/* 递归插入节点(辅助方法) */
private insertHelper(node: TreeNode, val: number): TreeNode {
if (node === null) return new TreeNode(val);
/* 1. 查找插入位置并插入节点 */
/* 1. 查找插入位置并插入节点 */
if (val < node.val) {
node.left = this.insertHelper(node.left, val);
} else if (val > node.val) {
@ -125,7 +125,7 @@ class AVLTree {
/* 递归删除节点(辅助方法) */
private removeHelper(node: TreeNode, val: number): TreeNode {
if (node === null) return null;
/* 1. 查找节点并删除 */
/* 1. 查找节点并删除 */
if (val < node.val) {
node.left = this.removeHelper(node.left, val);
} else if (val > node.val) {