From cf4a59e3d67627be33a4b2d314e1c12cdc8f5735 Mon Sep 17 00:00:00 2001 From: krahets Date: Mon, 17 Apr 2023 21:57:42 +0800 Subject: [PATCH] build --- chapter_array_and_linkedlist/linked_list.md | 3 +- chapter_array_and_linkedlist/list.md | 27 +++---- chapter_binary_search/binary_search.md | 61 ++++++++++------ .../space_complexity.md | 4 +- chapter_graph/graph_operations.md | 62 ++++++++++------ chapter_graph/graph_traversal.md | 21 +++--- chapter_hashing/hash_map.md | 3 +- chapter_heap/heap.md | 2 +- .../replace_linear_by_hashing.md | 4 +- chapter_sorting/bubble_sort.md | 4 +- chapter_sorting/insertion_sort.md | 7 +- chapter_sorting/merge_sort.md | 42 ++++++----- chapter_sorting/quick_sort.md | 40 ++++++++--- chapter_sorting/radix_sort.md | 12 ++-- chapter_stack_and_queue/deque.md | 72 +++++++++---------- chapter_stack_and_queue/queue.md | 27 ++++--- chapter_stack_and_queue/stack.md | 25 +++---- chapter_tree/avl_tree.md | 12 ++-- chapter_tree/binary_search_tree.md | 6 +- chapter_tree/binary_tree_traversal.md | 11 ++- 20 files changed, 247 insertions(+), 198 deletions(-) diff --git a/chapter_array_and_linkedlist/linked_list.md b/chapter_array_and_linkedlist/linked_list.md index a7535442c..342a41f5a 100755 --- a/chapter_array_and_linkedlist/linked_list.md +++ b/chapter_array_and_linkedlist/linked_list.md @@ -522,8 +522,7 @@ comments: true ```javascript title="linked_list.js" /* 删除链表的节点 n0 之后的首个节点 */ function remove(n0) { - if (!n0.next) - return; + if (!n0.next) return; // n0 -> P -> n1 const P = n0.next; const n1 = P.next; diff --git a/chapter_array_and_linkedlist/list.md b/chapter_array_and_linkedlist/list.md index 2e41f027a..4b2c0b438 100755 --- a/chapter_array_and_linkedlist/list.md +++ b/chapter_array_and_linkedlist/list.md @@ -1143,15 +1143,13 @@ comments: true /* 访问元素 */ get(index) { // 索引如果越界则抛出异常,下同 - if (index < 0 || index >= this.#size) - throw new Error('索引越界'); + if (index < 0 || index >= this.#size) throw new Error('索引越界'); return this.#nums[index]; } /* 更新元素 */ set(index, num) { - if (index < 0 || index >= this.#size) - throw new Error('索引越界'); + if (index < 0 || index >= this.#size) throw new Error('索引越界'); this.#nums[index] = num; } @@ -1168,8 +1166,7 @@ comments: true /* 中间插入元素 */ insert(index, num) { - if (index < 0 || index >= this.#size) - throw new Error('索引越界'); + if (index < 0 || index >= this.#size) throw new Error('索引越界'); // 元素数量超出容量时,触发扩容机制 if (this.#size === this.#capacity) { this.extendCapacity(); @@ -1185,8 +1182,7 @@ comments: true /* 删除元素 */ remove(index) { - if (index < 0 || index >= this.#size) - throw new Error('索引越界'); + if (index < 0 || index >= this.#size) throw new Error('索引越界'); let num = this.#nums[index]; // 将索引 index 之后的元素都向前移动一位 for (let j = index; j < this.#size - 1; j++) { @@ -1249,23 +1245,20 @@ comments: true /* 访问元素 */ public get(index: number): number { // 索引如果越界则抛出异常,下同 - if (index < 0 || index >= this._size) - throw new Error('索引越界'); + if (index < 0 || index >= this._size) throw new Error('索引越界'); return this.nums[index]; } /* 更新元素 */ public set(index: number, num: number): void { - if (index < 0 || index >= this._size) - throw new Error('索引越界'); + if (index < 0 || index >= this._size) throw new Error('索引越界'); this.nums[index] = num; } /* 尾部添加元素 */ public add(num: number): void { // 如果长度等于容量,则需要扩容 - if (this._size === this._capacity) - this.extendCapacity(); + if (this._size === this._capacity) this.extendCapacity(); // 将新元素添加到列表尾部 this.nums[this._size] = num; this._size++; @@ -1273,8 +1266,7 @@ comments: true /* 中间插入元素 */ public insert(index: number, num: number): void { - if (index < 0 || index >= this._size) - throw new Error('索引越界'); + if (index < 0 || index >= this._size) throw new Error('索引越界'); // 元素数量超出容量时,触发扩容机制 if (this._size === this._capacity) { this.extendCapacity(); @@ -1290,8 +1282,7 @@ comments: true /* 删除元素 */ public remove(index: number): number { - if (index < 0 || index >= this._size) - throw new Error('索引越界'); + if (index < 0 || index >= this._size) throw new Error('索引越界'); let num = this.nums[index]; // 将索引 index 之后的元素都向前移动一位 for (let j = index; j < this._size - 1; j++) { diff --git a/chapter_binary_search/binary_search.md b/chapter_binary_search/binary_search.md index 70646924a..90e7b288c 100755 --- a/chapter_binary_search/binary_search.md +++ b/chapter_binary_search/binary_search.md @@ -135,16 +135,19 @@ $$ /* 二分查找(双闭区间) */ function binarySearch(nums, target) { // 初始化双闭区间 [0, n-1] ,即 i, j 分别指向数组首元素、尾元素 - let i = 0, j = nums.length - 1; + let i = 0, + j = nums.length - 1; // 循环,当搜索区间为空时跳出(当 i > j 时为空) while (i <= j) { - const m = parseInt((i + j) / 2); // 计算中点索引 m ,在 JS 中需使用 parseInt 函数取整 - if (nums[m] < target) // 此情况说明 target 在区间 [m+1, j] 中 + // 计算中点索引 m ,使用 parseInt() 向下取整 + const m = parseInt((i + j) / 2); + if (nums[m] < target) + // 此情况说明 target 在区间 [m+1, j] 中 i = m + 1; - else if (nums[m] > target) // 此情况说明 target 在区间 [i, m-1] 中 + else if (nums[m] > target) + // 此情况说明 target 在区间 [i, m-1] 中 j = m - 1; - else - return m; // 找到目标元素,返回其索引 + else return m; // 找到目标元素,返回其索引 } // 未找到目标元素,返回 -1 return -1; @@ -157,15 +160,20 @@ $$ /* 二分查找(双闭区间) */ function binarySearch(nums: number[], target: number): number { // 初始化双闭区间 [0, n-1] ,即 i, j 分别指向数组首元素、尾元素 - let i = 0, j = nums.length - 1; + let i = 0, + j = nums.length - 1; // 循环,当搜索区间为空时跳出(当 i > j 时为空) while (i <= j) { - const m = Math.floor((i + j) / 2); // 计算中点索引 m - if (nums[m] < target) { // 此情况说明 target 在区间 [m+1, j] 中 + // 计算中点索引 m + const m = Math.floor((i + j) / 2); + if (nums[m] < target) { + // 此情况说明 target 在区间 [m+1, j] 中 i = m + 1; - } else if (nums[m] > target) { // 此情况说明 target 在区间 [i, m-1] 中 + } else if (nums[m] > target) { + // 此情况说明 target 在区间 [i, m-1] 中 j = m - 1; - } else { // 找到目标元素,返回其索引 + } else { + // 找到目标元素,返回其索引 return m; } } @@ -431,16 +439,20 @@ $$ /* 二分查找(左闭右开) */ function binarySearch1(nums, target) { // 初始化左闭右开 [0, n) ,即 i, j 分别指向数组首元素、尾元素+1 - let i = 0, j = nums.length; + let i = 0, + j = nums.length; // 循环,当搜索区间为空时跳出(当 i = j 时为空) while (i < j) { - const m = parseInt((i + j) / 2); // 计算中点索引 m ,在 JS 中需使用 parseInt 函数取整 - if (nums[m] < target) // 此情况说明 target 在区间 [m+1, j) 中 + // 计算中点索引 m ,使用 parseInt() 向下取整 + const m = parseInt((i + j) / 2); + if (nums[m] < target) + // 此情况说明 target 在区间 [m+1, j) 中 i = m + 1; - else if (nums[m] > target) // 此情况说明 target 在区间 [i, m) 中 + else if (nums[m] > target) + // 此情况说明 target 在区间 [i, m) 中 j = m; - else // 找到目标元素,返回其索引 - return m; + // 找到目标元素,返回其索引 + else return m; } // 未找到目标元素,返回 -1 return -1; @@ -453,15 +465,20 @@ $$ /* 二分查找(左闭右开) */ function binarySearch1(nums: number[], target: number): number { // 初始化左闭右开 [0, n) ,即 i, j 分别指向数组首元素、尾元素+1 - let i = 0, j = nums.length; + let i = 0, + j = nums.length; // 循环,当搜索区间为空时跳出(当 i = j 时为空) while (i < j) { - const m = Math.floor((i + j) / 2); // 计算中点索引 m - if (nums[m] < target) { // 此情况说明 target 在区间 [m+1, j) 中 + // 计算中点索引 m + const m = Math.floor((i + j) / 2); + if (nums[m] < target) { + // 此情况说明 target 在区间 [m+1, j) 中 i = m + 1; - } else if (nums[m] > target) { // 此情况说明 target 在区间 [i, m) 中 + } else if (nums[m] > target) { + // 此情况说明 target 在区间 [i, m) 中 j = m; - } else { // 找到目标元素,返回其索引 + } else { + // 找到目标元素,返回其索引 return m; } } diff --git a/chapter_computational_complexity/space_complexity.md b/chapter_computational_complexity/space_complexity.md index 6308de99d..1fcb1a92c 100755 --- a/chapter_computational_complexity/space_complexity.md +++ b/chapter_computational_complexity/space_complexity.md @@ -1156,7 +1156,9 @@ $$ /* 平方阶 */ function quadratic(n) { // 矩阵占用 O(n^2) 空间 - const numMatrix = Array(n).fill(null).map(() => Array(n).fill(null)); + const numMatrix = Array(n) + .fill(null) + .map(() => Array(n).fill(null)); // 二维列表占用 O(n^2) 空间 const numList = []; for (let i = 0; i < n; i++) { diff --git a/chapter_graph/graph_operations.md b/chapter_graph/graph_operations.md index 83333fdfa..8f3135332 100644 --- a/chapter_graph/graph_operations.md +++ b/chapter_graph/graph_operations.md @@ -391,8 +391,8 @@ comments: true ```javascript title="graph_adjacency_matrix.js" /* 基于邻接矩阵实现的无向图类 */ class GraphAdjMat { - vertices; // 顶点列表,元素代表“顶点值”,索引代表“顶点索引” - adjMat; // 邻接矩阵,行列索引对应“顶点索引” + vertices; // 顶点列表,元素代表“顶点值”,索引代表“顶点索引” + adjMat; // 邻接矩阵,行列索引对应“顶点索引” /* 构造函数 */ constructor(vertices, edges) { @@ -434,7 +434,7 @@ comments: true /* 删除顶点 */ removeVertex(index) { if (index >= this.size()) { - throw new RangeError("Index Out Of Bounds Exception"); + throw new RangeError('Index Out Of Bounds Exception'); } // 在顶点列表中移除索引 index 的顶点 this.vertices.splice(index, 1); @@ -452,7 +452,7 @@ comments: true addEdge(i, j) { // 索引越界与相等处理 if (i < 0 || j < 0 || i >= this.size() || j >= this.size() || i === j) { - throw new RangeError("Index Out Of Bounds Exception"); + throw new RangeError('Index Out Of Bounds Exception'); } // 在无向图中,邻接矩阵沿主对角线对称,即满足 (i, j) == (j, i) this.adjMat[i][j] = 1; @@ -464,7 +464,7 @@ comments: true removeEdge(i, j) { // 索引越界与相等处理 if (i < 0 || j < 0 || i >= this.size() || j >= this.size() || i === j) { - throw new RangeError("Index Out Of Bounds Exception"); + throw new RangeError('Index Out Of Bounds Exception'); } this.adjMat[i][j] = 0; this.adjMat[j][i] = 0; @@ -472,8 +472,8 @@ comments: true /* 打印邻接矩阵 */ print() { - console.log("顶点列表 = ", this.vertices); - console.log("邻接矩阵 =", this.adjMat); + console.log('顶点列表 = ', this.vertices); + console.log('邻接矩阵 =', this.adjMat); } } ``` @@ -483,8 +483,8 @@ comments: true ```typescript title="graph_adjacency_matrix.ts" /* 基于邻接矩阵实现的无向图类 */ class GraphAdjMat { - vertices: number[]; // 顶点列表,元素代表“顶点值”,索引代表“顶点索引” - adjMat: number[][]; // 邻接矩阵,行列索引对应“顶点索引” + vertices: number[]; // 顶点列表,元素代表“顶点值”,索引代表“顶点索引” + adjMat: number[][]; // 邻接矩阵,行列索引对应“顶点索引” /* 构造函数 */ constructor(vertices: number[], edges: number[][]) { @@ -526,7 +526,7 @@ comments: true /* 删除顶点 */ removeVertex(index: number): void { if (index >= this.size()) { - throw new RangeError("Index Out Of Bounds Exception"); + throw new RangeError('Index Out Of Bounds Exception'); } // 在顶点列表中移除索引 index 的顶点 this.vertices.splice(index, 1); @@ -544,7 +544,7 @@ comments: true addEdge(i: number, j: number): void { // 索引越界与相等处理 if (i < 0 || j < 0 || i >= this.size() || j >= this.size() || i === j) { - throw new RangeError("Index Out Of Bounds Exception"); + throw new RangeError('Index Out Of Bounds Exception'); } // 在无向图中,邻接矩阵沿主对角线对称,即满足 (i, j) == (j, i) this.adjMat[i][j] = 1; @@ -556,7 +556,7 @@ comments: true removeEdge(i: number, j: number): void { // 索引越界与相等处理 if (i < 0 || j < 0 || i >= this.size() || j >= this.size() || i === j) { - throw new RangeError("Index Out Of Bounds Exception"); + throw new RangeError('Index Out Of Bounds Exception'); } this.adjMat[i][j] = 0; this.adjMat[j][i] = 0; @@ -564,8 +564,8 @@ comments: true /* 打印邻接矩阵 */ print(): void { - console.log("顶点列表 = ", this.vertices); - console.log("邻接矩阵 =", this.adjMat); + console.log('顶点列表 = ', this.vertices); + console.log('邻接矩阵 =', this.adjMat); } } ``` @@ -1145,8 +1145,12 @@ comments: true /* 添加边 */ addEdge(vet1, vet2) { - if (!this.adjList.has(vet1) || !this.adjList.has(vet2) || vet1 === vet2) { - throw new Error("Illegal Argument Exception"); + if ( + !this.adjList.has(vet1) || + !this.adjList.has(vet2) || + vet1 === vet2 + ) { + throw new Error('Illegal Argument Exception'); } // 添加边 vet1 - vet2 this.adjList.get(vet1).push(vet2); @@ -1155,8 +1159,12 @@ comments: true /* 删除边 */ removeEdge(vet1, vet2) { - if (!this.adjList.has(vet1) || !this.adjList.has(vet2) || vet1 === vet2) { - throw new Error("Illegal Argument Exception"); + if ( + !this.adjList.has(vet1) || + !this.adjList.has(vet2) || + vet1 === vet2 + ) { + throw new Error('Illegal Argument Exception'); } // 删除边 vet1 - vet2 this.adjList.get(vet1).splice(this.adjList.get(vet1).indexOf(vet2), 1); @@ -1173,7 +1181,7 @@ comments: true /* 删除顶点 */ removeVertex(vet) { if (!this.adjList.has(vet)) { - throw new Error("Illegal Argument Exception"); + throw new Error('Illegal Argument Exception'); } // 在邻接表中删除顶点 vet 对应的链表 this.adjList.delete(vet); @@ -1188,13 +1196,13 @@ comments: true /* 打印邻接表 */ print() { - console.log("邻接表 ="); + console.log('邻接表 ='); for (const [key, value] of this.adjList) { const tmp = []; for (const vertex of value) { tmp.push(vertex.val); } - console.log(key.val + ": " + tmp.join()); + console.log(key.val + ': ' + tmp.join()); } } } @@ -1226,7 +1234,11 @@ comments: true /* 添加边 */ addEdge(vet1: Vertex, vet2: Vertex): void { - if (!this.adjList.has(vet1) || !this.adjList.has(vet2) || vet1 === vet2) { + if ( + !this.adjList.has(vet1) || + !this.adjList.has(vet2) || + vet1 === vet2 + ) { throw new Error('Illegal Argument Exception'); } // 添加边 vet1 - vet2 @@ -1236,7 +1248,11 @@ comments: true /* 删除边 */ removeEdge(vet1: Vertex, vet2: Vertex): void { - if (!this.adjList.has(vet1) || !this.adjList.has(vet2) || vet1 === vet2) { + if ( + !this.adjList.has(vet1) || + !this.adjList.has(vet2) || + vet1 === vet2 + ) { throw new Error('Illegal Argument Exception'); } // 删除边 vet1 - vet2 diff --git a/chapter_graph/graph_traversal.md b/chapter_graph/graph_traversal.md index 7ceb8ffae..d4a251438 100644 --- a/chapter_graph/graph_traversal.md +++ b/chapter_graph/graph_traversal.md @@ -167,15 +167,15 @@ BFS 通常借助「队列」来实现。队列具有“先入先出”的性质 const que = [startVet]; // 以顶点 vet 为起点,循环直至访问完所有顶点 while (que.length) { - const vet = que.shift(); // 队首顶点出队 - res.push(vet); // 记录访问顶点 + const vet = que.shift(); // 队首顶点出队 + res.push(vet); // 记录访问顶点 // 遍历该顶点的所有邻接顶点 for (const adjVet of graph.adjList.get(vet) ?? []) { if (visited.has(adjVet)) { - continue; // 跳过已被访问过的顶点 + continue; // 跳过已被访问过的顶点 } - que.push(adjVet); // 只入队未访问的顶点 - visited.add(adjVet); // 标记该顶点已被访问 + que.push(adjVet); // 只入队未访问的顶点 + visited.add(adjVet); // 标记该顶点已被访问 } } // 返回顶点遍历序列 @@ -465,8 +465,8 @@ BFS 通常借助「队列」来实现。队列具有“先入先出”的性质 /* 深度优先遍历 DFS */ // 使用邻接表来表示图,以便获取指定顶点的所有邻接顶点 function dfs(graph, visited, res, vet) { - res.push(vet); // 记录访问顶点 - visited.add(vet); // 标记该顶点已被访问 + res.push(vet); // 记录访问顶点 + visited.add(vet); // 标记该顶点已被访问 // 遍历该顶点的所有邻接顶点 for (const adjVet of graph.adjList.get(vet)) { if (visited.has(adjVet)) { @@ -493,7 +493,12 @@ BFS 通常借助「队列」来实现。队列具有“先入先出”的性质 ```typescript title="graph_dfs.ts" /* 深度优先遍历 DFS 辅助函数 */ - function dfs(graph: GraphAdjList, visited: Set, res: Vertex[], vet: Vertex): void { + function dfs( + graph: GraphAdjList, + visited: Set, + res: Vertex[], + vet: Vertex + ): void { res.push(vet); // 记录访问顶点 visited.add(vet); // 标记该顶点已被访问 // 遍历该顶点的所有邻接顶点 diff --git a/chapter_hashing/hash_map.md b/chapter_hashing/hash_map.md index a2d8da4f7..3b59072b5 100755 --- a/chapter_hashing/hash_map.md +++ b/chapter_hashing/hash_map.md @@ -882,12 +882,11 @@ $$ /* 基于数组简易实现的哈希表 */ class ArrayHashMap { - private readonly buckets: (Entry | null)[]; constructor() { // 初始化数组,包含 100 个桶 - this.buckets = (new Array(100)).fill(null); + this.buckets = new Array(100).fill(null); } /* 哈希函数 */ diff --git a/chapter_heap/heap.md b/chapter_heap/heap.md index 7be6778cd..11c96f659 100644 --- a/chapter_heap/heap.md +++ b/chapter_heap/heap.md @@ -1079,7 +1079,7 @@ comments: true /* 元素出堆 */ pop() { // 判空处理 - if (this.isEmpty()) throw new Error("堆为空"); + if (this.isEmpty()) throw new Error('堆为空'); // 交换根节点与最右叶节点(即交换首元素与尾元素) this.#swap(0, this.size() - 1); // 删除节点 diff --git a/chapter_searching/replace_linear_by_hashing.md b/chapter_searching/replace_linear_by_hashing.md index 26424cac9..2665ebde2 100755 --- a/chapter_searching/replace_linear_by_hashing.md +++ b/chapter_searching/replace_linear_by_hashing.md @@ -118,7 +118,7 @@ comments: true } } return []; - }; + } ``` === "C" @@ -302,7 +302,7 @@ comments: true } } return []; - }; + } ``` === "C" diff --git a/chapter_sorting/bubble_sort.md b/chapter_sorting/bubble_sort.md index dee63829a..0b440627a 100755 --- a/chapter_sorting/bubble_sort.md +++ b/chapter_sorting/bubble_sort.md @@ -345,10 +345,10 @@ comments: true let tmp = nums[j]; nums[j] = nums[j + 1]; nums[j + 1] = tmp; - flag = true; // 记录交换元素 + flag = true; // 记录交换元素 } } - if (!flag) break; // 此轮冒泡未交换任何元素,直接跳出 + if (!flag) break; // 此轮冒泡未交换任何元素,直接跳出 } } ``` diff --git a/chapter_sorting/insertion_sort.md b/chapter_sorting/insertion_sort.md index 308650b85..1f05c0479 100755 --- a/chapter_sorting/insertion_sort.md +++ b/chapter_sorting/insertion_sort.md @@ -102,13 +102,14 @@ comments: true function insertionSort(nums) { // 外循环:base = nums[1], nums[2], ..., nums[n-1] for (let i = 1; i < nums.length; i++) { - let base = nums[i], j = i - 1; + let base = nums[i], + j = i - 1; // 内循环:将 base 插入到左边的正确位置 while (j >= 0 && nums[j] > base) { - nums[j + 1] = nums[j]; // 1. 将 nums[j] 向右移动一位 + nums[j + 1] = nums[j]; // 1. 将 nums[j] 向右移动一位 j--; } - nums[j + 1] = base; // 2. 将 base 赋值到正确位置 + nums[j + 1] = base; // 2. 将 base 赋值到正确位置 } } ``` diff --git a/chapter_sorting/merge_sort.md b/chapter_sorting/merge_sort.md index d5687c20a..97544e309 100755 --- a/chapter_sorting/merge_sort.md +++ b/chapter_sorting/merge_sort.md @@ -248,23 +248,26 @@ comments: true // 右子数组区间 [mid + 1, right] function merge(nums, left, mid, right) { // 初始化辅助数组 - let tmp = nums.slice(left, right + 1); - // 左子数组的起始索引和结束索引 - let leftStart = left - left, leftEnd = mid - left; - // 右子数组的起始索引和结束索引 - let rightStart = mid + 1 - left, rightEnd = right - left; + let tmp = nums.slice(left, right + 1); + // 左子数组的起始索引和结束索引 + let leftStart = left - left, + leftEnd = mid - left; + // 右子数组的起始索引和结束索引 + let rightStart = mid + 1 - left, + rightEnd = right - left; // i, j 分别指向左子数组、右子数组的首元素 - let i = leftStart, j = rightStart; + let i = leftStart, + j = rightStart; // 通过覆盖原数组 nums 来合并左子数组和右子数组 for (let k = left; k <= right; k++) { - // 若“左子数组已全部合并完”,则选取右子数组元素,并且 j++ if (i > leftEnd) { + // 若“左子数组已全部合并完”,则选取右子数组元素,并且 j++ nums[k] = tmp[j++]; - // 否则,若“右子数组已全部合并完”或“左子数组元素 <= 右子数组元素”,则选取左子数组元素,并且 i++ } else if (j > rightEnd || tmp[i] <= tmp[j]) { + // 否则,若“右子数组已全部合并完”或“左子数组元素 <= 右子数组元素”,则选取左子数组元素,并且 i++ nums[k] = tmp[i++]; - // 否则,若“左右子数组都未全部合并完”且“左子数组元素 > 右子数组元素”,则选取右子数组元素,并且 j++ } else { + // 否则,若“左右子数组都未全部合并完”且“左子数组元素 > 右子数组元素”,则选取右子数组元素,并且 j++ nums[k] = tmp[j++]; } } @@ -273,10 +276,10 @@ comments: true /* 归并排序 */ function mergeSort(nums, left, right) { // 终止条件 - if (left >= right) return; // 当子数组长度为 1 时终止递归 + if (left >= right) return; // 当子数组长度为 1 时终止递归 // 划分阶段 - let mid = Math.floor((left + right) / 2); // 计算中点 - mergeSort(nums, left, mid); // 递归左子数组 + let mid = Math.floor((left + right) / 2); // 计算中点 + mergeSort(nums, left, mid); // 递归左子数组 mergeSort(nums, mid + 1, right); // 递归右子数组 // 合并阶段 merge(nums, left, mid, right); @@ -293,20 +296,23 @@ comments: true // 初始化辅助数组 let tmp = nums.slice(left, right + 1); // 左子数组的起始索引和结束索引 - let leftStart = left - left, leftEnd = mid - left; + let leftStart = left - left, + leftEnd = mid - left; // 右子数组的起始索引和结束索引 - let rightStart = mid + 1 - left, rightEnd = right - left; + let rightStart = mid + 1 - left, + rightEnd = right - left; // i, j 分别指向左子数组、右子数组的首元素 - let i = leftStart, j = rightStart; + let i = leftStart, + j = rightStart; // 通过覆盖原数组 nums 来合并左子数组和右子数组 for (let k = left; k <= right; k++) { - // 若“左子数组已全部合并完”,则选取右子数组元素,并且 j++ if (i > leftEnd) { + // 若“左子数组已全部合并完”,则选取右子数组元素,并且 j++ nums[k] = tmp[j++]; - // 否则,若“右子数组已全部合并完”或“左子数组元素 <= 右子数组元素”,则选取左子数组元素,并且 i++ + // 否则,若“右子数组已全部合并完”或“左子数组元素 <= 右子数组元素”,则选取左子数组元素,并且 i++ } else if (j > rightEnd || tmp[i] <= tmp[j]) { nums[k] = tmp[i++]; - // 否则,若“左右子数组都未全部合并完”且“左子数组元素 > 右子数组元素”,则选取右子数组元素,并且 j++ + // 否则,若“左右子数组都未全部合并完”且“左子数组元素 > 右子数组元素”,则选取右子数组元素,并且 j++ } else { nums[k] = tmp[j++]; } diff --git a/chapter_sorting/quick_sort.md b/chapter_sorting/quick_sort.md index 56fe02b1b..3fa254342 100755 --- a/chapter_sorting/quick_sort.md +++ b/chapter_sorting/quick_sort.md @@ -152,7 +152,8 @@ comments: true /* 哨兵划分 */ partition(nums, left, right) { // 以 nums[left] 作为基准数 - let i = left, j = right; + let i = left, + j = right; while (i < j) { while (i < j && nums[j] >= nums[left]) { j -= 1; // 从右向左找首个小于基准数的元素 @@ -181,7 +182,8 @@ comments: true /* 哨兵划分 */ partition(nums: number[], left: number, right: number): number { // 以 nums[left] 作为基准数 - let i = left, j = right; + let i = left, + j = right; while (i < j) { while (i < j && nums[j] >= nums[left]) { j -= 1; // 从右向左找首个小于基准数的元素 @@ -625,18 +627,25 @@ comments: true // 此处使用异或运算来简化代码 // 异或规则为 0 ^ 0 = 1 ^ 1 = 0, 0 ^ 1 = 1 ^ 0 = 1 if ((nums[left] < nums[mid]) ^ (nums[left] < nums[right])) return left; - else if ((nums[mid] < nums[left]) ^ (nums[mid] < nums[right])) return mid; + else if ((nums[mid] < nums[left]) ^ (nums[mid] < nums[right])) + return mid; else return right; } /* 哨兵划分(三数取中值) */ partition(nums, left, right) { // 选取三个候选元素的中位数 - let med = this.medianThree(nums, left, Math.floor((left + right) / 2), right); + let med = this.medianThree( + nums, + left, + Math.floor((left + right) / 2), + right + ); // 将中位数交换至数组最左端 this.swap(nums, left, med); // 以 nums[left] 作为基准数 - let i = left, j = right; + let i = left, + j = right; while (i < j) { while (i < j && nums[j] >= nums[left]) j--; // 从右向左找首个小于基准数的元素 while (i < j && nums[i] <= nums[left]) i++; // 从左向右找首个大于基准数的元素 @@ -651,12 +660,19 @@ comments: true ```typescript title="quick_sort.ts" /* 选取三个元素的中位数 */ - medianThree(nums: number[], left: number, mid: number, right: number): number { + medianThree( + nums: number[], + left: number, + mid: number, + right: number + ): number { // 此处使用异或运算来简化代码 // 异或规则为 0 ^ 0 = 1 ^ 1 = 0, 0 ^ 1 = 1 ^ 0 = 1 if (Number(nums[left] < nums[mid]) ^ Number(nums[left] < nums[right])) { return left; - } else if (Number(nums[mid] < nums[left]) ^ Number(nums[mid] < nums[right])) { + } else if ( + Number(nums[mid] < nums[left]) ^ Number(nums[mid] < nums[right]) + ) { return mid; } else { return right; @@ -666,11 +682,17 @@ comments: true /* 哨兵划分(三数取中值) */ partition(nums: number[], left: number, right: number): number { // 选取三个候选元素的中位数 - let med = this.medianThree(nums, left, Math.floor((left + right) / 2), right); + let med = this.medianThree( + nums, + left, + Math.floor((left + right) / 2), + right + ); // 将中位数交换至数组最左端 this.swap(nums, left, med); // 以 nums[left] 作为基准数 - let i = left, j = right; + let i = left, + j = right; while (i < j) { while (i < j && nums[j] >= nums[left]) { j--; // 从右向左找首个小于基准数的元素 diff --git a/chapter_sorting/radix_sort.md b/chapter_sorting/radix_sort.md index 63bddaef2..06351cbf0 100644 --- a/chapter_sorting/radix_sort.md +++ b/chapter_sorting/radix_sort.md @@ -253,7 +253,7 @@ $$ // 统计 0~9 各数字的出现次数 for (let i = 0; i < n; i++) { const d = digit(nums[i], exp); // 获取 nums[i] 第 k 位,记为 d - counter[d]++; // 统计数字 d 的出现次数 + counter[d]++; // 统计数字 d 的出现次数 } // 求前缀和,将“出现个数”转换为“数组索引” for (let i = 1; i < 10; i++) { @@ -264,8 +264,8 @@ $$ for (let i = n - 1; i >= 0; i--) { const d = digit(nums[i], exp); const j = counter[d] - 1; // 获取 d 在数组中的索引 j - res[j] = nums[i]; // 将当前元素填入索引 j - counter[d]--; // 将 d 的数量减 1 + res[j] = nums[i]; // 将当前元素填入索引 j + counter[d]--; // 将 d 的数量减 1 } // 使用结果覆盖原数组 nums for (let i = 0; i < n; i++) { @@ -310,7 +310,7 @@ $$ // 统计 0~9 各数字的出现次数 for (let i = 0; i < n; i++) { const d = digit(nums[i], exp); // 获取 nums[i] 第 k 位,记为 d - counter[d]++; // 统计数字 d 的出现次数 + counter[d]++; // 统计数字 d 的出现次数 } // 求前缀和,将“出现个数”转换为“数组索引” for (let i = 1; i < 10; i++) { @@ -321,8 +321,8 @@ $$ for (let i = n - 1; i >= 0; i--) { const d = digit(nums[i], exp); const j = counter[d] - 1; // 获取 d 在数组中的索引 j - res[j] = nums[i]; // 将当前元素填入索引 j - counter[d]--; // 将 d 的数量减 1 + res[j] = nums[i]; // 将当前元素填入索引 j + counter[d]--; // 将 d 的数量减 1 } // 使用结果覆盖原数组 nums for (let i = 0; i < n; i++) { diff --git a/chapter_stack_and_queue/deque.md b/chapter_stack_and_queue/deque.md index 7c348cedb..3be5efe6a 100644 --- a/chapter_stack_and_queue/deque.md +++ b/chapter_stack_and_queue/deque.md @@ -784,10 +784,10 @@ comments: true ```javascript title="linkedlist_deque.js" /* 双向链表节点 */ class ListNode { - prev; // 前驱节点引用 (指针) - next; // 后继节点引用 (指针) - val; // 节点值 - + prev; // 前驱节点引用 (指针) + next; // 后继节点引用 (指针) + val; // 节点值 + constructor(val) { this.val = val; this.next = null; @@ -797,9 +797,9 @@ comments: true /* 基于双向链表实现的双向队列 */ class LinkedListDeque { - #front; // 头节点 front - #rear; // 尾节点 rear - #queSize; // 双向队列的长度 + #front; // 头节点 front + #rear; // 尾节点 rear + #queSize; // 双向队列的长度 constructor() { this.#front = null; @@ -851,7 +851,7 @@ comments: true temp.next = null; this.#rear.prev = null; } - this.#rear = temp; // 更新尾节点 + this.#rear = temp; // 更新尾节点 this.#queSize--; return value; } @@ -868,7 +868,7 @@ comments: true temp.prev = null; this.#front.next = null; } - this.#front = temp; // 更新头节点 + this.#front = temp; // 更新头节点 this.#queSize--; return value; } @@ -901,7 +901,7 @@ comments: true arr.push(temp.val); temp = temp.next; } - console.log("[" + arr.join(", ") + "]"); + console.log('[' + arr.join(', ') + ']'); } } ``` @@ -911,9 +911,9 @@ comments: true ```typescript title="linkedlist_deque.ts" /* 双向链表节点 */ class ListNode { - prev: ListNode; // 前驱节点引用 (指针) - next: ListNode; // 后继节点引用 (指针) - val: number; // 节点值 + prev: ListNode; // 前驱节点引用 (指针) + next: ListNode; // 后继节点引用 (指针) + val: number; // 节点值 constructor(val: number) { this.val = val; @@ -924,16 +924,16 @@ comments: true /* 基于双向链表实现的双向队列 */ class LinkedListDeque { - private front: ListNode; // 头节点 front - private rear: ListNode; // 尾节点 rear - private queSize: number; // 双向队列的长度 + private front: ListNode; // 头节点 front + private rear: ListNode; // 尾节点 rear + private queSize: number; // 双向队列的长度 constructor() { this.front = null; this.rear = null; this.queSize = 0; } - + /* 队尾入队操作 */ pushLast(val: number): void { const node: ListNode = new ListNode(val); @@ -978,7 +978,7 @@ comments: true temp.next = null; this.rear.prev = null; } - this.rear = temp; // 更新尾节点 + this.rear = temp; // 更新尾节点 this.queSize--; return value; } @@ -995,7 +995,7 @@ comments: true temp.prev = null; this.front.next = null; } - this.front = temp; // 更新头节点 + this.front = temp; // 更新头节点 this.queSize--; return value; } @@ -1028,7 +1028,7 @@ comments: true arr.push(temp.val); temp = temp.next; } - console.log("[" + arr.join(", ") + "]"); + console.log('[' + arr.join(', ') + ']'); } } ``` @@ -1790,9 +1790,9 @@ comments: true ```javascript title="array_deque.js" /* 基于环形数组实现的双向队列 */ class ArrayDeque { - #nums; // 用于存储双向队列元素的数组 - #front; // 队首指针,指向队首元素 - #queSize; // 双向队列长度 + #nums; // 用于存储双向队列元素的数组 + #front; // 队首指针,指向队首元素 + #queSize; // 双向队列长度 /* 构造方法 */ constructor(capacity) { @@ -1827,7 +1827,7 @@ comments: true /* 队首入队 */ pushFirst(num) { if (this.#queSize === this.capacity()) { - console.log("双向队列已满"); + console.log('双向队列已满'); return; } // 队首指针向左移动一位 @@ -1841,7 +1841,7 @@ comments: true /* 队尾入队 */ pushLast(num) { if (this.#queSize === this.capacity()) { - console.log("双向队列已满"); + console.log('双向队列已满'); return; } // 计算尾指针,指向队尾索引 + 1 @@ -1869,15 +1869,13 @@ comments: true /* 访问队首元素 */ peekFirst() { - if (this.isEmpty()) - throw new Error("The Deque Is Empty."); + if (this.isEmpty()) throw new Error('The Deque Is Empty.'); return this.#nums[this.#front]; } /* 访问队尾元素 */ peekLast() { - if (this.isEmpty()) - throw new Error("The Deque Is Empty."); + if (this.isEmpty()) throw new Error('The Deque Is Empty.'); // 计算尾元素索引 const last = this.index(this.#front + this.#queSize - 1); return this.#nums[last]; @@ -1900,9 +1898,9 @@ comments: true ```typescript title="array_deque.ts" /* 基于环形数组实现的双向队列 */ class ArrayDeque { - private nums: number[]; // 用于存储双向队列元素的数组 - private front: number; // 队首指针,指向队首元素 - private queSize: number; // 双向队列长度 + private nums: number[]; // 用于存储双向队列元素的数组 + private front: number; // 队首指针,指向队首元素 + private queSize: number; // 双向队列长度 /* 构造方法 */ constructor(capacity: number) { @@ -1937,7 +1935,7 @@ comments: true /* 队首入队 */ pushFirst(num: number): void { if (this.queSize === this.capacity()) { - console.log("双向队列已满"); + console.log('双向队列已满'); return; } // 队首指针向左移动一位 @@ -1951,7 +1949,7 @@ comments: true /* 队尾入队 */ pushLast(num: number): void { if (this.queSize === this.capacity()) { - console.log("双向队列已满"); + console.log('双向队列已满'); return; } // 计算尾指针,指向队尾索引 + 1 @@ -1979,15 +1977,13 @@ comments: true /* 访问队首元素 */ peekFirst(): number { - if (this.isEmpty()) - throw new Error("The Deque Is Empty."); + if (this.isEmpty()) throw new Error('The Deque Is Empty.'); return this.nums[this.front]; } /* 访问队尾元素 */ peekLast(): number { - if (this.isEmpty()) - throw new Error("The Deque Is Empty."); + if (this.isEmpty()) throw new Error('The Deque Is Empty.'); // 计算尾元素索引 const last = this.index(this.front + this.queSize - 1); return this.nums[last]; diff --git a/chapter_stack_and_queue/queue.md b/chapter_stack_and_queue/queue.md index 3a299381c..167ef8e3a 100755 --- a/chapter_stack_and_queue/queue.md +++ b/chapter_stack_and_queue/queue.md @@ -544,8 +544,8 @@ comments: true ```javascript title="linkedlist_queue.js" /* 基于链表实现的队列 */ class LinkedListQueue { - #front; // 头节点 #front - #rear; // 尾节点 #rear + #front; // 头节点 #front + #rear; // 尾节点 #rear #queSize = 0; constructor() { @@ -590,8 +590,7 @@ comments: true /* 访问队首元素 */ peek() { - if (this.size === 0) - throw new Error("队列为空"); + if (this.size === 0) throw new Error('队列为空'); return this.#front.val; } @@ -1235,9 +1234,9 @@ comments: true ```javascript title="array_queue.js" /* 基于环形数组实现的队列 */ class ArrayQueue { - #nums; // 用于存储队列元素的数组 - #front = 0; // 队首指针,指向队首元素 - #queSize = 0; // 队列长度 + #nums; // 用于存储队列元素的数组 + #front = 0; // 队首指针,指向队首元素 + #queSize = 0; // 队列长度 constructor(capacity) { this.#nums = new Array(capacity); @@ -1261,7 +1260,7 @@ comments: true /* 入队 */ push(num) { if (this.size == this.capacity) { - console.log("队列已满"); + console.log('队列已满'); return; } // 计算尾指针,指向队尾索引 + 1 @@ -1283,8 +1282,7 @@ comments: true /* 访问队首元素 */ peek() { - if (this.empty()) - throw new Error("队列为空"); + if (this.empty()) throw new Error('队列为空'); return this.#nums[this.#front]; } @@ -1305,8 +1303,8 @@ comments: true ```typescript title="array_queue.ts" /* 基于环形数组实现的队列 */ class ArrayQueue { - private nums: number[]; // 用于存储队列元素的数组 - private front: number; // 队首指针,指向队首元素 + private nums: number[]; // 用于存储队列元素的数组 + private front: number; // 队首指针,指向队首元素 private queSize: number; // 队列长度 constructor(capacity: number) { @@ -1332,7 +1330,7 @@ comments: true /* 入队 */ push(num: number): void { if (this.size == this.capacity) { - console.log("队列已满"); + console.log('队列已满'); return; } // 计算尾指针,指向队尾索引 + 1 @@ -1354,8 +1352,7 @@ comments: true /* 访问队首元素 */ peek(): number { - if (this.empty()) - throw new Error("队列为空"); + if (this.empty()) throw new Error('队列为空'); return this.nums[this.front]; } diff --git a/chapter_stack_and_queue/stack.md b/chapter_stack_and_queue/stack.md index 7d3afa210..cb966d897 100755 --- a/chapter_stack_and_queue/stack.md +++ b/chapter_stack_and_queue/stack.md @@ -517,8 +517,8 @@ comments: true ```javascript title="linkedlist_stack.js" /* 基于链表实现的栈 */ class LinkedListStack { - #stackPeek; // 将头节点作为栈顶 - #stkSize = 0; // 栈的长度 + #stackPeek; // 将头节点作为栈顶 + #stkSize = 0; // 栈的长度 constructor() { this.#stackPeek = null; @@ -552,8 +552,7 @@ comments: true /* 访问栈顶元素 */ peek() { - if (!this.#stackPeek) - throw new Error("栈为空"); + if (!this.#stackPeek) throw new Error('栈为空'); return this.#stackPeek.val; } @@ -1050,7 +1049,7 @@ comments: true constructor() { this.#stack = []; } - + /* 获取栈的长度 */ get size() { return this.#stack.length; @@ -1068,15 +1067,13 @@ comments: true /* 出栈 */ pop() { - if (this.empty()) - throw new Error("栈为空"); + if (this.empty()) throw new Error('栈为空'); return this.#stack.pop(); } /* 访问栈顶元素 */ top() { - if (this.empty()) - throw new Error("栈为空"); + if (this.empty()) throw new Error('栈为空'); return this.#stack[this.#stack.length - 1]; } @@ -1084,7 +1081,7 @@ comments: true toArray() { return this.#stack; } - }; + } ``` === "TypeScript" @@ -1114,15 +1111,13 @@ comments: true /* 出栈 */ pop(): number | undefined { - if (this.empty()) - throw new Error('栈为空'); + if (this.empty()) throw new Error('栈为空'); return this.stack.pop(); } /* 访问栈顶元素 */ top(): number | undefined { - if (this.empty()) - throw new Error('栈为空'); + if (this.empty()) throw new Error('栈为空'); return this.stack[this.stack.length - 1]; } @@ -1130,7 +1125,7 @@ comments: true toArray() { return this.stack; } - }; + } ``` === "C" diff --git a/chapter_tree/avl_tree.md b/chapter_tree/avl_tree.md index 443c0782a..d33c410ec 100644 --- a/chapter_tree/avl_tree.md +++ b/chapter_tree/avl_tree.md @@ -242,7 +242,8 @@ G. M. Adelson-Velsky 和 E. M. Landis 在其 1962 年发表的论文 "An algorit /* 更新节点高度 */ #updateHeight(node) { // 节点高度等于最高子树高度 + 1 - node.height = Math.max(this.height(node.left), this.height(node.right)) + 1; + node.height = + Math.max(this.height(node.left), this.height(node.right)) + 1; } ``` @@ -258,7 +259,8 @@ G. M. Adelson-Velsky 和 E. M. Landis 在其 1962 年发表的论文 "An algorit /* 更新节点高度 */ updateHeight(node: TreeNode): void { // 节点高度等于最高子树高度 + 1 - node.height = Math.max(this.height(node.left), this.height(node.right)) + 1; + node.height = + Math.max(this.height(node.left), this.height(node.right)) + 1; } ``` @@ -1315,7 +1317,8 @@ AVL 树的特点在于「旋转 Rotation」操作,它能够在不影响二叉 if (node === null) return new TreeNode(val); /* 1. 查找插入位置,并插入节点 */ if (val < node.val) node.left = this.#insertHelper(node.left, val); - else if (val > node.val) node.right = this.#insertHelper(node.right, val); + else if (val > node.val) + node.right = this.#insertHelper(node.right, val); else return node; // 重复节点不插入,直接返回 this.#updateHeight(node); // 更新节点高度 /* 2. 执行旋转操作,使该子树重新恢复平衡 */ @@ -1649,7 +1652,8 @@ AVL 树的特点在于「旋转 Rotation」操作,它能够在不影响二叉 if (node === null) return null; /* 1. 查找节点,并删除之 */ if (val < node.val) node.left = this.#removeHelper(node.left, val); - else if (val > node.val) node.right = this.#removeHelper(node.right, val); + else if (val > node.val) + node.right = this.#removeHelper(node.right, val); else { if (node.left === null || node.right === null) { const child = node.left !== null ? node.left : node.right; diff --git a/chapter_tree/binary_search_tree.md b/chapter_tree/binary_search_tree.md index a1125b7c9..6c0e72128 100755 --- a/chapter_tree/binary_search_tree.md +++ b/chapter_tree/binary_search_tree.md @@ -393,7 +393,8 @@ comments: true function insert(num) { // 若树为空,直接提前返回 if (root === null) return; - let cur = root, pre = null; + let cur = root, + pre = null; // 循环查找,越过叶节点后跳出 while (cur !== null) { // 找到重复节点,直接返回 @@ -808,7 +809,8 @@ comments: true function remove(num) { // 若树为空,直接提前返回 if (root === null) return; - let cur = root, pre = null; + let cur = root, + pre = null; // 循环查找,越过叶节点后跳出 while (cur !== null) { // 找到待删除节点,跳出循环 diff --git a/chapter_tree/binary_tree_traversal.md b/chapter_tree/binary_tree_traversal.md index 4147c2609..c37a118ad 100755 --- a/chapter_tree/binary_tree_traversal.md +++ b/chapter_tree/binary_tree_traversal.md @@ -124,13 +124,10 @@ comments: true // 初始化一个列表,用于保存遍历序列 const list = []; while (queue.length) { - let node = queue.shift(); // 队列出队 - list.push(node.val); // 保存节点值 - if (node.left) - queue.push(node.left); // 左子节点入队 - if (node.right) - queue.push(node.right); // 右子节点入队 - + let node = queue.shift(); // 队列出队 + list.push(node.val); // 保存节点值 + if (node.left) queue.push(node.left); // 左子节点入队 + if (node.right) queue.push(node.right); // 右子节点入队 } return list; }