From ecbf2d15600d227a1211320d2f305ab92f3619c6 Mon Sep 17 00:00:00 2001 From: krahets Date: Tue, 7 Feb 2023 04:43:52 +0800 Subject: [PATCH] =?UTF-8?q?1.=20Add=20build=20script=20for=20Java.=202.=20?= =?UTF-8?q?Add=20height=20limitation=20for=20code=20blocks=20in=20extra.cs?= =?UTF-8?q?s.=203.=20Fix=20"=E8=8A=82=E7=82=B9"=20to=20"=E7=BB=93=E7=82=B9?= =?UTF-8?q?".?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- codes/c/chapter_tree/avl_tree.c | 8 +- codes/c/chapter_tree/binary_tree_bfs.c | 2 +- codes/cpp/chapter_sorting/merge_sort.cpp | 8 +- codes/cpp/chapter_tree/avl_tree.cpp | 10 +- codes/cpp/chapter_tree/binary_tree_bfs.cpp | 2 +- codes/csharp/chapter_tree/avl_tree.cs | 10 +- codes/go/chapter_tree/avl_tree.go | 10 +- codes/go/chapter_tree/binary_tree_bfs.go | 2 +- .../space_complexity.java | 1 + codes/java/chapter_sorting/merge_sort.java | 8 +- codes/java/chapter_sorting/quick_sort.java | 2 +- codes/java/chapter_tree/avl_tree.java | 10 +- codes/java/chapter_tree/binary_tree_bfs.java | 2 +- .../javascript/chapter_sorting/merge_sort.js | 8 +- codes/javascript/chapter_tree/avl_tree.js | 10 +- .../chapter_tree/binary_tree_bfs.js | 2 +- codes/python/chapter_tree/avl_tree.py | 4 +- codes/python/chapter_tree/binary_tree.py | 4 +- codes/python/chapter_tree/binary_tree_bfs.py | 2 +- codes/swift/chapter_sorting/merge_sort.swift | 8 +- codes/swift/chapter_tree/avl_tree.swift | 10 +- .../swift/chapter_tree/binary_tree_bfs.swift | 2 +- .../typescript/chapter_sorting/merge_sort.ts | 8 +- codes/typescript/chapter_tree/avl_tree.ts | 10 +- .../chapter_tree/binary_tree_bfs.ts | 2 +- codes/zig/chapter_tree/avl_tree.zig | 10 +- codes/zig/chapter_tree/binary_tree_bfs.zig | 2 +- docs/chapter_array_and_linkedlist/array.md | 63 +---- .../linked_list.md | 41 +--- docs/chapter_array_and_linkedlist/list.md | 87 +------ .../space_complexity.md | 72 +----- .../space_time_tradeoff.md | 30 +-- .../time_complexity.md | 146 ++---------- docs/chapter_graph/graph_operations.md | 148 +----------- docs/chapter_hashing/hash_map.md | 52 +---- docs/chapter_heap/heap.md | 103 ++------ docs/chapter_searching/binary_search.md | 36 +-- docs/chapter_searching/hashing_search.md | 14 +- docs/chapter_searching/linear_search.md | 25 +- docs/chapter_sorting/bubble_sort.md | 35 +-- docs/chapter_sorting/insertion_sort.md | 14 +- docs/chapter_sorting/merge_sort.md | 74 ++---- docs/chapter_sorting/quick_sort.md | 79 +------ docs/chapter_stack_and_queue/deque.md | 116 +-------- docs/chapter_stack_and_queue/queue.md | 105 +-------- docs/chapter_stack_and_queue/stack.md | 70 +----- docs/chapter_tree/avl_tree.md | 220 +++++------------- docs/chapter_tree/binary_search_tree.md | 88 +------ docs/chapter_tree/binary_tree.md | 4 +- docs/chapter_tree/binary_tree_traversal.md | 58 +---- docs/stylesheets/extra.css | 8 +- docs/utils/build_markdown.py | 43 ++-- docs/utils/extract_code_java.py | 145 ++++++++++++ docs/utils/extract_code_python.py | 57 +++-- 54 files changed, 457 insertions(+), 1633 deletions(-) create mode 100644 docs/utils/extract_code_java.py diff --git a/codes/c/chapter_tree/avl_tree.c b/codes/c/chapter_tree/avl_tree.c index 74b40d3b7..9bce9c9b5 100644 --- a/codes/c/chapter_tree/avl_tree.c +++ b/codes/c/chapter_tree/avl_tree.c @@ -61,7 +61,7 @@ TreeNode *rightRotate(TreeNode *node) { // 更新结点高度 updateHeight(node); updateHeight(child); - // 返回旋转后子树的根节点 + // 返回旋转后子树的根结点 return child; } @@ -76,7 +76,7 @@ TreeNode *leftRotate(TreeNode *node) { // 更新结点高度 updateHeight(node); updateHeight(child); - // 返回旋转后子树的根节点 + // 返回旋转后子树的根结点 return child; } @@ -128,7 +128,7 @@ TreeNode *insertHelper(TreeNode *node, int val) { updateHeight(node); /* 2. 执行旋转操作,使该子树重新恢复平衡 */ node = rotate(node); - // 返回子树的根节点 + // 返回子树的根结点 return node; } @@ -186,7 +186,7 @@ TreeNode *removeHelper(TreeNode *node, int val) { updateHeight(node); /* 2. 执行旋转操作,使该子树重新恢复平衡 */ node = rotate(node); - // 返回子树的根节点 + // 返回子树的根结点 return node; } diff --git a/codes/c/chapter_tree/binary_tree_bfs.c b/codes/c/chapter_tree/binary_tree_bfs.c index c7b83b912..fe2604ebf 100644 --- a/codes/c/chapter_tree/binary_tree_bfs.c +++ b/codes/c/chapter_tree/binary_tree_bfs.c @@ -28,7 +28,7 @@ int *levelOrder(TreeNode *root, int *size) { while (front < rear) { // 队列出队 node = queue[front++]; - // 保存结点 + // 保存结点值 arr[index++] = node->val; if (node->left != NULL) { // 左子结点入队 diff --git a/codes/cpp/chapter_sorting/merge_sort.cpp b/codes/cpp/chapter_sorting/merge_sort.cpp index 89b5b09cd..c16911175 100644 --- a/codes/cpp/chapter_sorting/merge_sort.cpp +++ b/codes/cpp/chapter_sorting/merge_sort.cpp @@ -6,11 +6,9 @@ #include "../include/include.hpp" -/** - * 合并左子数组和右子数组 - * 左子数组区间 [left, mid] - * 右子数组区间 [mid + 1, right] - */ +/* 合并左子数组和右子数组 */ +// 左子数组区间 [left, mid] +// 右子数组区间 [mid + 1, right] void merge(vector& nums, int left, int mid, int right) { // 初始化辅助数组 vector tmp(nums.begin() + left, nums.begin() + right + 1); diff --git a/codes/cpp/chapter_tree/avl_tree.cpp b/codes/cpp/chapter_tree/avl_tree.cpp index 98fece3b2..a6b523143 100644 --- a/codes/cpp/chapter_tree/avl_tree.cpp +++ b/codes/cpp/chapter_tree/avl_tree.cpp @@ -9,7 +9,7 @@ /* AVL 树 */ class AVLTree { public: - TreeNode* root; // 根节点 + TreeNode* root; // 根结点 private: /* 更新结点高度 */ void updateHeight(TreeNode* node) { @@ -27,7 +27,7 @@ private: // 更新结点高度 updateHeight(node); updateHeight(child); - // 返回旋转后子树的根节点 + // 返回旋转后子树的根结点 return child; } @@ -41,7 +41,7 @@ private: // 更新结点高度 updateHeight(node); updateHeight(child); - // 返回旋转后子树的根节点 + // 返回旋转后子树的根结点 return child; } @@ -88,7 +88,7 @@ private: updateHeight(node); // 更新结点高度 /* 2. 执行旋转操作,使该子树重新恢复平衡 */ node = rotate(node); - // 返回子树的根节点 + // 返回子树的根结点 return node; } @@ -133,7 +133,7 @@ private: updateHeight(node); // 更新结点高度 /* 2. 执行旋转操作,使该子树重新恢复平衡 */ node = rotate(node); - // 返回子树的根节点 + // 返回子树的根结点 return node; } diff --git a/codes/cpp/chapter_tree/binary_tree_bfs.cpp b/codes/cpp/chapter_tree/binary_tree_bfs.cpp index ffc2e372c..c3694eb9c 100644 --- a/codes/cpp/chapter_tree/binary_tree_bfs.cpp +++ b/codes/cpp/chapter_tree/binary_tree_bfs.cpp @@ -16,7 +16,7 @@ vector hierOrder(TreeNode* root) { while (!queue.empty()) { TreeNode* node = queue.front(); queue.pop(); // 队列出队 - vec.push_back(node->val); // 保存结点 + vec.push_back(node->val); // 保存结点值 if (node->left != nullptr) queue.push(node->left); // 左子结点入队 if (node->right != nullptr) diff --git a/codes/csharp/chapter_tree/avl_tree.cs b/codes/csharp/chapter_tree/avl_tree.cs index 778c9d40b..19ac8b85a 100644 --- a/codes/csharp/chapter_tree/avl_tree.cs +++ b/codes/csharp/chapter_tree/avl_tree.cs @@ -12,7 +12,7 @@ namespace hello_algo.chapter_tree /* AVL 树 */ class AVLTree { - public TreeNode? root; // 根节点 + public TreeNode? root; // 根结点 /* 获取结点高度 */ public int height(TreeNode? node) @@ -48,7 +48,7 @@ namespace hello_algo.chapter_tree // 更新结点高度 updateHeight(node); updateHeight(child); - // 返回旋转后子树的根节点 + // 返回旋转后子树的根结点 return child; } @@ -63,7 +63,7 @@ namespace hello_algo.chapter_tree // 更新结点高度 updateHeight(node); updateHeight(child); - // 返回旋转后子树的根节点 + // 返回旋转后子树的根结点 return child; } @@ -127,7 +127,7 @@ namespace hello_algo.chapter_tree updateHeight(node); // 更新结点高度 /* 2. 执行旋转操作,使该子树重新恢复平衡 */ node = rotate(node); - // 返回子树的根节点 + // 返回子树的根结点 return node; } @@ -170,7 +170,7 @@ namespace hello_algo.chapter_tree updateHeight(node); // 更新结点高度 /* 2. 执行旋转操作,使该子树重新恢复平衡 */ node = rotate(node); - // 返回子树的根节点 + // 返回子树的根结点 return node; } diff --git a/codes/go/chapter_tree/avl_tree.go b/codes/go/chapter_tree/avl_tree.go index 822f116c1..9f1e51345 100644 --- a/codes/go/chapter_tree/avl_tree.go +++ b/codes/go/chapter_tree/avl_tree.go @@ -8,7 +8,7 @@ import . "github.com/krahets/hello-algo/pkg" /* AVL 树 */ type avlTree struct { - // 根节点 + // 根结点 root *TreeNode } @@ -57,7 +57,7 @@ func rightRotate(node *TreeNode) *TreeNode { // 更新结点高度 updateHeight(node) updateHeight(child) - // 返回旋转后子树的根节点 + // 返回旋转后子树的根结点 return child } @@ -71,7 +71,7 @@ func leftRotate(node *TreeNode) *TreeNode { // 更新结点高度 updateHeight(node) updateHeight(child) - // 返回旋转后子树的根节点 + // 返回旋转后子树的根结点 return child } @@ -130,7 +130,7 @@ func insertHelper(node *TreeNode, val int) *TreeNode { updateHeight(node) /* 2. 执行旋转操作,使该子树重新恢复平衡 */ node = rotate(node) - // 返回子树的根节点 + // 返回子树的根结点 return node } @@ -174,7 +174,7 @@ func removeHelper(node *TreeNode, val int) *TreeNode { updateHeight(node) /* 2. 执行旋转操作,使该子树重新恢复平衡 */ node = rotate(node) - // 返回子树的根节点 + // 返回子树的根结点 return node } diff --git a/codes/go/chapter_tree/binary_tree_bfs.go b/codes/go/chapter_tree/binary_tree_bfs.go index d77bc97b1..8ec46fbe7 100644 --- a/codes/go/chapter_tree/binary_tree_bfs.go +++ b/codes/go/chapter_tree/binary_tree_bfs.go @@ -20,7 +20,7 @@ func levelOrder(root *TreeNode) []int { for queue.Len() > 0 { // poll node := queue.Remove(queue.Front()).(*TreeNode) - // 保存结点 + // 保存结点值 nums = append(nums, node.Val) if node.Left != nil { // 左子结点入队 diff --git a/codes/java/chapter_computational_complexity/space_complexity.java b/codes/java/chapter_computational_complexity/space_complexity.java index 275a37ec0..497d302aa 100644 --- a/codes/java/chapter_computational_complexity/space_complexity.java +++ b/codes/java/chapter_computational_complexity/space_complexity.java @@ -74,6 +74,7 @@ public class space_complexity { /* 平方阶(递归实现) */ static int quadraticRecur(int n) { if (n <= 0) return 0; + // 数组 nums 长度为 n, n-1, ..., 2, 1 int[] nums = new int[n]; System.out.println("递归 n = " + n + " 中的 nums 长度 = " + nums.length); return quadraticRecur(n - 1); diff --git a/codes/java/chapter_sorting/merge_sort.java b/codes/java/chapter_sorting/merge_sort.java index 68f76c9b1..6b4a2fc71 100644 --- a/codes/java/chapter_sorting/merge_sort.java +++ b/codes/java/chapter_sorting/merge_sort.java @@ -9,11 +9,9 @@ package chapter_sorting; import java.util.*; public class merge_sort { - /** - * 合并左子数组和右子数组 - * 左子数组区间 [left, mid] - * 右子数组区间 [mid + 1, right] - */ + /* 合并左子数组和右子数组 */ + // 左子数组区间 [left, mid] + // 右子数组区间 [mid + 1, right] static void merge(int[] nums, int left, int mid, int right) { // 初始化辅助数组 int[] tmp = Arrays.copyOfRange(nums, left, right + 1); diff --git a/codes/java/chapter_sorting/quick_sort.java b/codes/java/chapter_sorting/quick_sort.java index 1eaa1011d..16e84d51a 100644 --- a/codes/java/chapter_sorting/quick_sort.java +++ b/codes/java/chapter_sorting/quick_sort.java @@ -123,7 +123,7 @@ class QuickSortTailCall { } /* 快速排序(尾递归优化) */ - static void quickSort(int[] nums, int left, int right) { + public static void quickSort(int[] nums, int left, int right) { // 子数组长度为 1 时终止 while (left < right) { // 哨兵划分操作 diff --git a/codes/java/chapter_tree/avl_tree.java b/codes/java/chapter_tree/avl_tree.java index 3d2b8d5e4..945719dd5 100644 --- a/codes/java/chapter_tree/avl_tree.java +++ b/codes/java/chapter_tree/avl_tree.java @@ -10,7 +10,7 @@ import include.*; /* AVL 树 */ class AVLTree { - TreeNode root; // 根节点 + TreeNode root; // 根结点 /* 获取结点高度 */ public int height(TreeNode node) { @@ -42,7 +42,7 @@ class AVLTree { // 更新结点高度 updateHeight(node); updateHeight(child); - // 返回旋转后子树的根节点 + // 返回旋转后子树的根结点 return child; } @@ -56,7 +56,7 @@ class AVLTree { // 更新结点高度 updateHeight(node); updateHeight(child); - // 返回旋转后子树的根节点 + // 返回旋转后子树的根结点 return child; } @@ -109,7 +109,7 @@ class AVLTree { updateHeight(node); // 更新结点高度 /* 2. 执行旋转操作,使该子树重新恢复平衡 */ node = rotate(node); - // 返回子树的根节点 + // 返回子树的根结点 return node; } @@ -146,7 +146,7 @@ class AVLTree { updateHeight(node); // 更新结点高度 /* 2. 执行旋转操作,使该子树重新恢复平衡 */ node = rotate(node); - // 返回子树的根节点 + // 返回子树的根结点 return node; } diff --git a/codes/java/chapter_tree/binary_tree_bfs.java b/codes/java/chapter_tree/binary_tree_bfs.java index ffeb352e0..578ed2b81 100644 --- a/codes/java/chapter_tree/binary_tree_bfs.java +++ b/codes/java/chapter_tree/binary_tree_bfs.java @@ -18,7 +18,7 @@ public class binary_tree_bfs { List list = new ArrayList<>(); while (!queue.isEmpty()) { TreeNode node = queue.poll(); // 队列出队 - list.add(node.val); // 保存结点 + list.add(node.val); // 保存结点值 if (node.left != null) queue.offer(node.left); // 左子结点入队 if (node.right != null) diff --git a/codes/javascript/chapter_sorting/merge_sort.js b/codes/javascript/chapter_sorting/merge_sort.js index 4e2449af2..515b163a3 100644 --- a/codes/javascript/chapter_sorting/merge_sort.js +++ b/codes/javascript/chapter_sorting/merge_sort.js @@ -4,11 +4,9 @@ * Author: IsChristina (christinaxia77@foxmail.com) */ -/** - * 合并左子数组和右子数组 - * 左子数组区间 [left, mid] - * 右子数组区间 [mid + 1, right] - */ +/* 合并左子数组和右子数组 */ +// 左子数组区间 [left, mid] +// 右子数组区间 [mid + 1, right] function merge(nums, left, mid, right) { // 初始化辅助数组 let tmp = nums.slice(left, right + 1); diff --git a/codes/javascript/chapter_tree/avl_tree.js b/codes/javascript/chapter_tree/avl_tree.js index 580989c2b..c949d5e45 100644 --- a/codes/javascript/chapter_tree/avl_tree.js +++ b/codes/javascript/chapter_tree/avl_tree.js @@ -11,7 +11,7 @@ const { printTree } = require("../include/PrintUtil"); class AVLTree { /*构造函数*/ constructor() { - this.root = null; //根节点 + this.root = null; //根结点 } /* 获取结点高度 */ @@ -44,7 +44,7 @@ class AVLTree { // 更新结点高度 this.updateHeight(node); this.updateHeight(child); - // 返回旋转后子树的根节点 + // 返回旋转后子树的根结点 return child; } @@ -58,7 +58,7 @@ class AVLTree { // 更新结点高度 this.updateHeight(node); this.updateHeight(child); - // 返回旋转后子树的根节点 + // 返回旋转后子树的根结点 return child; } @@ -108,7 +108,7 @@ class AVLTree { this.updateHeight(node); // 更新结点高度 /* 2. 执行旋转操作,使该子树重新恢复平衡 */ node = this.rotate(node); - // 返回子树的根节点 + // 返回子树的根结点 return node; } @@ -141,7 +141,7 @@ class AVLTree { this.updateHeight(node); // 更新结点高度 /* 2. 执行旋转操作,使该子树重新恢复平衡 */ node = this.rotate(node); - // 返回子树的根节点 + // 返回子树的根结点 return node; } diff --git a/codes/javascript/chapter_tree/binary_tree_bfs.js b/codes/javascript/chapter_tree/binary_tree_bfs.js index 21daaa8dc..5b410bddd 100644 --- a/codes/javascript/chapter_tree/binary_tree_bfs.js +++ b/codes/javascript/chapter_tree/binary_tree_bfs.js @@ -15,7 +15,7 @@ function hierOrder(root) { let list = []; while (queue.length) { let node = queue.shift(); // 队列出队 - list.push(node.val); // 保存结点 + list.push(node.val); // 保存结点值 if (node.left) queue.push(node.left); // 左子结点入队 if (node.right) diff --git a/codes/python/chapter_tree/avl_tree.py b/codes/python/chapter_tree/avl_tree.py index bedd5c37f..e4858c362 100644 --- a/codes/python/chapter_tree/avl_tree.py +++ b/codes/python/chapter_tree/avl_tree.py @@ -43,7 +43,7 @@ class AVLTree: # 更新结点高度 self.__update_height(node) self.__update_height(child) - # 返回旋转后子树的根节点 + # 返回旋转后子树的根结点 return child """ 左旋操作 """ @@ -56,7 +56,7 @@ class AVLTree: # 更新结点高度 self.__update_height(node) self.__update_height(child) - # 返回旋转后子树的根节点 + # 返回旋转后子树的根结点 return child """ 执行旋转操作,使该子树重新恢复平衡 """ diff --git a/codes/python/chapter_tree/binary_tree.py b/codes/python/chapter_tree/binary_tree.py index e00eeb4e5..a1a8b4e37 100644 --- a/codes/python/chapter_tree/binary_tree.py +++ b/codes/python/chapter_tree/binary_tree.py @@ -13,7 +13,7 @@ from include import * """ Driver Code """ if __name__ == "__main__": """ 初始化二叉树 """ - # 初始化节点 + # 初始化结点 n1 = TreeNode(val=1) n2 = TreeNode(val=2) n3 = TreeNode(val=3) @@ -29,7 +29,7 @@ if __name__ == "__main__": """ 插入与删除结点 """ P = TreeNode(0) - # 在 n1 -> n2 中间插入节点 P + # 在 n1 -> n2 中间插入结点 P n1.left = P P.left = n2 print("\n插入结点 P 后\n") diff --git a/codes/python/chapter_tree/binary_tree_bfs.py b/codes/python/chapter_tree/binary_tree_bfs.py index fb3e93059..657fd51da 100644 --- a/codes/python/chapter_tree/binary_tree_bfs.py +++ b/codes/python/chapter_tree/binary_tree_bfs.py @@ -18,7 +18,7 @@ def hier_order(root: Optional[TreeNode]): res = [] while queue: node = queue.popleft() # 队列出队 - res.append(node.val) # 保存节点值 + res.append(node.val) # 保存结点值 if node.left is not None: queue.append(node.left) # 左子结点入队 if node.right is not None: diff --git a/codes/swift/chapter_sorting/merge_sort.swift b/codes/swift/chapter_sorting/merge_sort.swift index 80d9d701a..7dadedd37 100644 --- a/codes/swift/chapter_sorting/merge_sort.swift +++ b/codes/swift/chapter_sorting/merge_sort.swift @@ -4,11 +4,9 @@ * Author: nuomi1 (nuomi1@qq.com) */ -/** - * 合并左子数组和右子数组 - * 左子数组区间 [left, mid] - * 右子数组区间 [mid + 1, right] - */ +/* 合并左子数组和右子数组 */ +// 左子数组区间 [left, mid] +// 右子数组区间 [mid + 1, right] func merge(nums: inout [Int], left: Int, mid: Int, right: Int) { // 初始化辅助数组 let tmp = Array(nums[left ..< (right + 1)]) diff --git a/codes/swift/chapter_tree/avl_tree.swift b/codes/swift/chapter_tree/avl_tree.swift index 08036686a..c0a8092c6 100644 --- a/codes/swift/chapter_tree/avl_tree.swift +++ b/codes/swift/chapter_tree/avl_tree.swift @@ -8,7 +8,7 @@ import utils /* AVL 树 */ class AVLTree { - fileprivate var root: TreeNode? // 根节点 + fileprivate var root: TreeNode? // 根结点 /* 获取结点高度 */ func height(node: TreeNode?) -> Int { @@ -40,7 +40,7 @@ class AVLTree { // 更新结点高度 updateHeight(node: node) updateHeight(node: child) - // 返回旋转后子树的根节点 + // 返回旋转后子树的根结点 return child } @@ -54,7 +54,7 @@ class AVLTree { // 更新结点高度 updateHeight(node: node) updateHeight(node: child) - // 返回旋转后子树的根节点 + // 返回旋转后子树的根结点 return child } @@ -112,7 +112,7 @@ class AVLTree { updateHeight(node: node) // 更新结点高度 /* 2. 执行旋转操作,使该子树重新恢复平衡 */ node = rotate(node: node) - // 返回子树的根节点 + // 返回子树的根结点 return node } @@ -155,7 +155,7 @@ class AVLTree { updateHeight(node: node) // 更新结点高度 /* 2. 执行旋转操作,使该子树重新恢复平衡 */ node = rotate(node: node) - // 返回子树的根节点 + // 返回子树的根结点 return node } diff --git a/codes/swift/chapter_tree/binary_tree_bfs.swift b/codes/swift/chapter_tree/binary_tree_bfs.swift index bdd09559e..a0aa3cd00 100644 --- a/codes/swift/chapter_tree/binary_tree_bfs.swift +++ b/codes/swift/chapter_tree/binary_tree_bfs.swift @@ -14,7 +14,7 @@ func hierOrder(root: TreeNode) -> [Int] { var list: [Int] = [] while !queue.isEmpty { let node = queue.removeFirst() // 队列出队 - list.append(node.val) // 保存结点 + list.append(node.val) // 保存结点值 if let left = node.left { queue.append(left) // 左子结点入队 } diff --git a/codes/typescript/chapter_sorting/merge_sort.ts b/codes/typescript/chapter_sorting/merge_sort.ts index 754502949..6f94b7564 100644 --- a/codes/typescript/chapter_sorting/merge_sort.ts +++ b/codes/typescript/chapter_sorting/merge_sort.ts @@ -4,11 +4,9 @@ * Author: Justin (xiefahit@gmail.com) */ -/** - * 合并左子数组和右子数组 - * 左子数组区间 [left, mid] - * 右子数组区间 [mid + 1, right] - */ +/* 合并左子数组和右子数组 */ +// 左子数组区间 [left, mid] +// 右子数组区间 [mid + 1, right] function merge(nums: number[], left: number, mid: number, right: number): void { // 初始化辅助数组 let tmp = nums.slice(left, right + 1); diff --git a/codes/typescript/chapter_tree/avl_tree.ts b/codes/typescript/chapter_tree/avl_tree.ts index bd3f9c659..bc052aa1a 100644 --- a/codes/typescript/chapter_tree/avl_tree.ts +++ b/codes/typescript/chapter_tree/avl_tree.ts @@ -12,7 +12,7 @@ class AVLTree { root: TreeNode; /*构造函数*/ constructor() { - this.root = null; //根节点 + this.root = null; //根结点 } /* 获取结点高度 */ @@ -45,7 +45,7 @@ class AVLTree { // 更新结点高度 this.updateHeight(node); this.updateHeight(child); - // 返回旋转后子树的根节点 + // 返回旋转后子树的根结点 return child; } @@ -59,7 +59,7 @@ class AVLTree { // 更新结点高度 this.updateHeight(node); this.updateHeight(child); - // 返回旋转后子树的根节点 + // 返回旋转后子树的根结点 return child; } @@ -113,7 +113,7 @@ class AVLTree { this.updateHeight(node); // 更新结点高度 /* 2. 执行旋转操作,使该子树重新恢复平衡 */ node = this.rotate(node); - // 返回子树的根节点 + // 返回子树的根结点 return node; } @@ -151,7 +151,7 @@ class AVLTree { this.updateHeight(node); // 更新结点高度 /* 2. 执行旋转操作,使该子树重新恢复平衡 */ node = this.rotate(node); - // 返回子树的根节点 + // 返回子树的根结点 return node; } diff --git a/codes/typescript/chapter_tree/binary_tree_bfs.ts b/codes/typescript/chapter_tree/binary_tree_bfs.ts index 58529c2e2..f723e0486 100644 --- a/codes/typescript/chapter_tree/binary_tree_bfs.ts +++ b/codes/typescript/chapter_tree/binary_tree_bfs.ts @@ -16,7 +16,7 @@ function hierOrder(root: TreeNode | null): number[] { const list: number[] = []; while (queue.length) { let node = queue.shift() as TreeNode; // 队列出队 - list.push(node.val); // 保存结点 + list.push(node.val); // 保存结点值 if (node.left) { queue.push(node.left); // 左子结点入队 } diff --git a/codes/zig/chapter_tree/avl_tree.zig b/codes/zig/chapter_tree/avl_tree.zig index d73286d2f..5ff24b90a 100644 --- a/codes/zig/chapter_tree/avl_tree.zig +++ b/codes/zig/chapter_tree/avl_tree.zig @@ -10,7 +10,7 @@ pub fn AVLTree(comptime T: type) type { return struct { const Self = @This(); - root: ?*inc.TreeNode(T) = null, // 根节点 + root: ?*inc.TreeNode(T) = null, // 根结点 mem_arena: ?std.heap.ArenaAllocator = null, mem_allocator: std.mem.Allocator = undefined, // 内存分配器 @@ -59,7 +59,7 @@ pub fn AVLTree(comptime T: type) type { // 更新结点高度 self.updateHeight(node); self.updateHeight(child); - // 返回旋转后子树的根节点 + // 返回旋转后子树的根结点 return child; } @@ -73,7 +73,7 @@ pub fn AVLTree(comptime T: type) type { // 更新结点高度 self.updateHeight(node); self.updateHeight(child); - // 返回旋转后子树的根节点 + // 返回旋转后子树的根结点 return child; } @@ -132,7 +132,7 @@ pub fn AVLTree(comptime T: type) type { self.updateHeight(node); // 更新结点高度 // 2. 执行旋转操作,使该子树重新恢复平衡 node = self.rotate(node); - // 返回子树的根节点 + // 返回子树的根结点 return node; } @@ -171,7 +171,7 @@ pub fn AVLTree(comptime T: type) type { self.updateHeight(node); // 更新结点高度 // 2. 执行旋转操作,使该子树重新恢复平衡 node = self.rotate(node); - // 返回子树的根节点 + // 返回子树的根结点 return node; } diff --git a/codes/zig/chapter_tree/binary_tree_bfs.zig b/codes/zig/chapter_tree/binary_tree_bfs.zig index 56c1d8abb..eaa0d0d5a 100644 --- a/codes/zig/chapter_tree/binary_tree_bfs.zig +++ b/codes/zig/chapter_tree/binary_tree_bfs.zig @@ -18,7 +18,7 @@ fn hierOrder(comptime T: type, mem_allocator: std.mem.Allocator, root: *inc.Tree while (queue.len > 0) { var queue_node = queue.popFirst().?; // 队列出队 var node = queue_node.data; - try list.append(node.val); // 保存结点 + try list.append(node.val); // 保存结点值 if (node.left != null) { var tmp_node = try mem_allocator.create(L.Node); tmp_node.data = node.left.?; diff --git a/docs/chapter_array_and_linkedlist/array.md b/docs/chapter_array_and_linkedlist/array.md index f60c64628..575213a02 100755 --- a/docs/chapter_array_and_linkedlist/array.md +++ b/docs/chapter_array_and_linkedlist/array.md @@ -117,14 +117,7 @@ elementAddr = firtstElementAddr + elementLength * elementIndex === "Java" ```java title="array.java" - /* 随机返回一个数组元素 */ - int randomAccess(int[] nums) { - // 在区间 [0, nums.length) 中随机抽取一个数字 - int randomIndex = ThreadLocalRandom.current(). - nextInt(0, nums.length); - int randomNum = nums[randomIndex]; - return randomNum; - } + [class]{array}-[func]{randomAccess} ``` === "C++" @@ -239,17 +232,7 @@ elementAddr = firtstElementAddr + elementLength * elementIndex === "Java" ```java title="array.java" - /* 扩展数组长度 */ - int[] extend(int[] nums, int enlarge) { - // 初始化一个扩展长度后的数组 - int[] res = new int[nums.length + enlarge]; - // 将原数组中的所有元素复制到新数组 - for (int i = 0; i < nums.length; i++) { - res[i] = nums[i]; - } - // 返回扩展后的新数组 - return res; - } + [class]{array}-[func]{extend} ``` === "C++" @@ -392,23 +375,9 @@ elementAddr = firtstElementAddr + elementLength * elementIndex === "Java" ```java title="array.java" - /* 在数组的索引 index 处插入元素 num */ - void insert(int[] nums, int num, int index) { - // 把索引 index 以及之后的所有元素向后移动一位 - for (int i = nums.length - 1; i > index; i--) { - nums[i] = nums[i - 1]; - } - // 将 num 赋给 index 处元素 - nums[index] = num; - } - - /* 删除索引 index 处元素 */ - void remove(int[] nums, int index) { - // 把索引 index 之后的所有元素向前移动一位 - for (int i = index; i < nums.length - 1; i++) { - nums[i] = nums[i + 1]; - } - } + [class]{array}-[func]{insert} + + [class]{array}-[func]{remove} ``` === "C++" @@ -592,18 +561,7 @@ elementAddr = firtstElementAddr + elementLength * elementIndex === "Java" ```java title="array.java" - /* 遍历数组 */ - void traverse(int[] nums) { - int count = 0; - // 通过索引遍历数组 - for (int i = 0; i < nums.length; i++) { - count++; - } - // 直接遍历数组 - for (int num : nums) { - count++; - } - } + [class]{array}-[func]{traverse} ``` === "C++" @@ -743,14 +701,7 @@ elementAddr = firtstElementAddr + elementLength * elementIndex === "Java" ```java title="array.java" - /* 在数组中查找指定元素 */ - int find(int[] nums, int target) { - for (int i = 0; i < nums.length; i++) { - if (nums[i] == target) - return i; - } - return -1; - } + [class]{array}-[func]{find} ``` === "C++" diff --git a/docs/chapter_array_and_linkedlist/linked_list.md b/docs/chapter_array_and_linkedlist/linked_list.md index 71d91d73e..af0edd8ba 100755 --- a/docs/chapter_array_and_linkedlist/linked_list.md +++ b/docs/chapter_array_and_linkedlist/linked_list.md @@ -325,22 +325,9 @@ comments: true === "Java" ```java title="linked_list.java" - /* 在链表的结点 n0 之后插入结点 P */ - void insert(ListNode n0, ListNode P) { - ListNode n1 = n0.next; - n0.next = P; - P.next = n1; - } - - /* 删除链表的结点 n0 之后的首个结点 */ - void remove(ListNode n0) { - if (n0.next == null) - return; - // n0 -> P -> n1 - ListNode P = n0.next; - ListNode n1 = P.next; - n0.next = n1; - } + [class]{linked_list}-[func]{insert} + + [class]{linked_list}-[func]{remove} ``` === "C++" @@ -518,15 +505,7 @@ comments: true === "Java" ```java title="linked_list.java" - /* 访问链表中索引为 index 的结点 */ - ListNode access(ListNode head, int index) { - for (int i = 0; i < index; i++) { - if (head == null) - return null; - head = head.next; - } - return head; - } + [class]{linked_list}-[func]{access} ``` === "C++" @@ -655,17 +634,7 @@ comments: true === "Java" ```java title="linked_list.java" - /* 在链表中查找值为 target 的首个结点 */ - int find(ListNode head, int target) { - int index = 0; - while (head != null) { - if (head.val == target) - return index; - head = head.next; - index++; - } - return -1; - } + [class]{linked_list}-[func]{find} ``` === "C++" diff --git a/docs/chapter_array_and_linkedlist/list.md b/docs/chapter_array_and_linkedlist/list.md index f1c470499..a46deec09 100755 --- a/docs/chapter_array_and_linkedlist/list.md +++ b/docs/chapter_array_and_linkedlist/list.md @@ -716,92 +716,7 @@ comments: true === "Java" ```java title="my_list.java" - /* 列表类简易实现 */ - class MyList { - private int[] nums; // 数组(存储列表元素) - private int capacity = 10; // 列表容量 - private int size = 0; // 列表长度(即当前元素数量) - private int extendRatio = 2; // 每次列表扩容的倍数 - - /* 构造函数 */ - public MyList() { - nums = new int[capacity]; - } - - /* 获取列表长度(即当前元素数量)*/ - public int size() { - return size; - } - - /* 获取列表容量 */ - public int capacity() { - return capacity; - } - - /* 访问元素 */ - public int get(int index) { - // 索引如果越界则抛出异常,下同 - if (index < 0 || index >= size) - throw new IndexOutOfBoundsException("索引越界"); - return nums[index]; - } - - /* 更新元素 */ - public void set(int index, int num) { - if (index < 0 || index >= size) - throw new IndexOutOfBoundsException("索引越界"); - nums[index] = num; - } - - /* 尾部添加元素 */ - public void add(int num) { - // 元素数量超出容量时,触发扩容机制 - if (size == capacity()) - extendCapacity(); - nums[size] = num; - // 更新元素数量 - size++; - } - - /* 中间插入元素 */ - public void insert(int index, int num) { - if (index < 0 || index >= size) - throw new IndexOutOfBoundsException("索引越界"); - // 元素数量超出容量时,触发扩容机制 - if (size == capacity()) - extendCapacity(); - // 将索引 index 以及之后的元素都向后移动一位 - for (int j = size - 1; j >= index; j--) { - nums[j + 1] = nums[j]; - } - nums[index] = num; - // 更新元素数量 - size++; - } - - /* 删除元素 */ - public int remove(int index) { - if (index < 0 || index >= size) - throw new IndexOutOfBoundsException("索引越界"); - int num = nums[index]; - // 将索引 index 之后的元素都向前移动一位 - for (int j = index; j < size - 1; j++) { - nums[j] = nums[j + 1]; - } - // 更新元素数量 - size--; - // 返回被删除元素 - return num; - } - - /* 列表扩容 */ - public void extendCapacity() { - // 新建一个长度为 size 的数组,并将原数组拷贝到新数组 - nums = Arrays.copyOf(nums, capacity() * extendRatio); - // 更新列表容量 - capacity = nums.length; - } - } + [class]{MyList}-[func]{} ``` === "C++" diff --git a/docs/chapter_computational_complexity/space_complexity.md b/docs/chapter_computational_complexity/space_complexity.md index 8033d2a1e..434b7fda9 100755 --- a/docs/chapter_computational_complexity/space_complexity.md +++ b/docs/chapter_computational_complexity/space_complexity.md @@ -582,22 +582,7 @@ $$ === "Java" ```java title="space_complexity.java" - /* 常数阶 */ - void constant(int n) { - // 常量、变量、对象占用 O(1) 空间 - final int a = 0; - int b = 0; - int[] nums = new int[10000]; - ListNode node = new ListNode(0); - // 循环中的变量占用 O(1) 空间 - for (int i = 0; i < n; i++) { - int c = 0; - } - // 循环中的函数占用 O(1) 空间 - for (int i = 0; i < n; i++) { - function(); - } - } + [class]{space_complexity}-[func]{constant} ``` === "C++" @@ -778,21 +763,7 @@ $$ === "Java" ```java title="space_complexity.java" - /* 线性阶 */ - void linear(int n) { - // 长度为 n 的数组占用 O(n) 空间 - int[] nums = new int[n]; - // 长度为 n 的列表占用 O(n) 空间 - List nodes = new ArrayList<>(); - for (int i = 0; i < n; i++) { - nodes.add(new ListNode(i)); - } - // 长度为 n 的哈希表占用 O(n) 空间 - Map map = new HashMap<>(); - for (int i = 0; i < n; i++) { - map.put(i, String.valueOf(i)); - } - } + [class]{space_complexity}-[func]{linear} ``` === "C++" @@ -956,12 +927,7 @@ $$ === "Java" ```java title="space_complexity.java" - /* 线性阶(递归实现) */ - void linearRecur(int n) { - System.out.println("递归 n = " + n); - if (n == 1) return; - linearRecur(n - 1); - } + [class]{space_complexity}-[func]{linearRecur} ``` === "C++" @@ -1069,20 +1035,7 @@ $$ === "Java" ```java title="space_complexity.java" - /* 平方阶 */ - void quadratic(int n) { - // 矩阵占用 O(n^2) 空间 - int [][]numMatrix = new int[n][n]; - // 二维列表占用 O(n^2) 空间 - List> numList = new ArrayList<>(); - for (int i = 0; i < n; i++) { - List tmp = new ArrayList<>(); - for (int j = 0; j < n; j++) { - tmp.add(0); - } - numList.add(tmp); - } - } + [class]{space_complexity}-[func]{quadratic} ``` === "C++" @@ -1223,13 +1176,7 @@ $$ === "Java" ```java title="space_complexity.java" - /* 平方阶(递归实现) */ - int quadraticRecur(int n) { - if (n <= 0) return 0; - // 数组 nums 长度为 n, n-1, ..., 2, 1 - int[] nums = new int[n]; - return quadraticRecur(n - 1); - } + [class]{space_complexity}-[func]{quadraticRecur} ``` === "C++" @@ -1344,14 +1291,7 @@ $$ === "Java" ```java title="space_complexity.java" - /* 指数阶(建立满二叉树) */ - TreeNode buildTree(int n) { - if (n == 0) return null; - TreeNode root = new TreeNode(0); - root.left = buildTree(n - 1); - root.right = buildTree(n - 1); - return root; - } + [class]{space_complexity}-[func]{buildTree} ``` === "C++" diff --git a/docs/chapter_computational_complexity/space_time_tradeoff.md b/docs/chapter_computational_complexity/space_time_tradeoff.md index 8b8ee2be6..e5d712fd0 100755 --- a/docs/chapter_computational_complexity/space_time_tradeoff.md +++ b/docs/chapter_computational_complexity/space_time_tradeoff.md @@ -33,19 +33,7 @@ comments: true === "Java" ```java title="leetcode_two_sum.java" - class SolutionBruteForce { - public int[] twoSum(int[] nums, int target) { - int size = nums.length; - // 两层循环,时间复杂度 O(n^2) - for (int i = 0; i < size - 1; i++) { - for (int j = i + 1; j < size; j++) { - if (nums[i] + nums[j] == target) - return new int[] { i, j }; - } - } - return new int[0]; - } - } + [class]{SolutionBruteForce}-[func]{} ``` === "C++" @@ -199,21 +187,7 @@ comments: true === "Java" ```java title="leetcode_two_sum.java" - class SolutionHashMap { - public int[] twoSum(int[] nums, int target) { - int size = nums.length; - // 辅助哈希表,空间复杂度 O(n) - Map dic = new HashMap<>(); - // 单层循环,时间复杂度 O(n) - for (int i = 0; i < size; i++) { - if (dic.containsKey(target - nums[i])) { - return new int[] { dic.get(target - nums[i]), i }; - } - dic.put(nums[i], i); - } - return new int[0]; - } - } + [class]{SolutionHashMap}-[func]{} ``` === "C++" diff --git a/docs/chapter_computational_complexity/time_complexity.md b/docs/chapter_computational_complexity/time_complexity.md index e9d9b7528..2a5c2860f 100755 --- a/docs/chapter_computational_complexity/time_complexity.md +++ b/docs/chapter_computational_complexity/time_complexity.md @@ -795,14 +795,7 @@ $$ === "Java" ```java title="time_complexity.java" - /* 常数阶 */ - int constant(int n) { - int count = 0; - int size = 100000; - for (int i = 0; i < size; i++) - count++; - return count; - } + [class]{time_complexity}-[func]{constant} ``` === "C++" @@ -928,13 +921,7 @@ $$ === "Java" ```java title="time_complexity.java" - /* 线性阶 */ - int linear(int n) { - int count = 0; - for (int i = 0; i < n; i++) - count++; - return count; - } + [class]{time_complexity}-[func]{linear} ``` === "C++" @@ -1052,15 +1039,7 @@ $$ === "Java" ```java title="time_complexity.java" - /* 线性阶(遍历数组) */ - int arrayTraversal(int[] nums) { - int count = 0; - // 循环次数与数组长度成正比 - for (int num : nums) { - count++; - } - return count; - } + [class]{time_complexity}-[func]{arrayTraversal} ``` === "C++" @@ -1190,17 +1169,7 @@ $$ === "Java" ```java title="time_complexity.java" - /* 平方阶 */ - int quadratic(int n) { - int count = 0; - // 循环次数与数组长度成平方关系 - for (int i = 0; i < n; i++) { - for (int j = 0; j < n; j++) { - count++; - } - } - return count; - } + [class]{time_complexity}-[func]{quadratic} ``` === "C++" @@ -1355,24 +1324,7 @@ $$ === "Java" ```java title="time_complexity.java" - /* 平方阶(冒泡排序) */ - int bubbleSort(int[] nums) { - int count = 0; // 计数器 - // 外循环:待排序元素数量为 n-1, n-2, ..., 1 - for (int i = nums.length - 1; i > 0; i--) { - // 内循环:冒泡操作 - for (int j = 0; j < i; j++) { - if (nums[j] > nums[j + 1]) { - // 交换 nums[j] 与 nums[j + 1] - int tmp = nums[j]; - nums[j] = nums[j + 1]; - nums[j + 1] = tmp; - count += 3; // 元素交换包含 3 个单元操作 - } - } - } - return count; - } + [class]{time_complexity}-[func]{bubbleSort} ``` === "C++" @@ -1585,19 +1537,7 @@ $$ === "Java" ```java title="time_complexity.java" - /* 指数阶(循环实现) */ - int exponential(int n) { - int count = 0, base = 1; - // cell 每轮一分为二,形成数列 1, 2, 4, 8, ..., 2^(n-1) - for (int i = 0; i < n; i++) { - for (int j = 0; j < base; j++) { - count++; - } - base *= 2; - } - // count = 1 + 2 + 4 + 8 + .. + 2^(n-1) = 2^n - 1 - return count; - } + [class]{time_complexity}-[func]{exponential} ``` === "C++" @@ -1770,11 +1710,7 @@ $$ === "Java" ```java title="time_complexity.java" - /* 指数阶(递归实现) */ - int expRecur(int n) { - if (n == 1) return 1; - return expRecur(n - 1) + expRecur(n - 1) + 1; - } + [class]{time_complexity}-[func]{expRecur} ``` === "C++" @@ -1880,15 +1816,7 @@ $$ === "Java" ```java title="time_complexity.java" - /* 对数阶(循环实现) */ - int logarithmic(float n) { - int count = 0; - while (n > 1) { - n = n / 2; - count++; - } - return count; - } + [class]{time_complexity}-[func]{logarithmic} ``` === "C++" @@ -2024,11 +1952,7 @@ $$ === "Java" ```java title="time_complexity.java" - /* 对数阶(递归实现) */ - int logRecur(float n) { - if (n <= 1) return 0; - return logRecur(n / 2) + 1; - } + [class]{time_complexity}-[func]{logRecur} ``` === "C++" @@ -2132,16 +2056,7 @@ $$ === "Java" ```java title="time_complexity.java" - /* 线性对数阶 */ - int linearLogRecur(float n) { - if (n <= 1) return 1; - int count = linearLogRecur(n / 2) + - linearLogRecur(n / 2); - for (int i = 0; i < n; i++) { - count++; - } - return count; - } + [class]{time_complexity}-[func]{linearLogRecur} ``` === "C++" @@ -2292,16 +2207,7 @@ $$ === "Java" ```java title="time_complexity.java" - /* 阶乘阶(递归实现) */ - int factorialRecur(int n) { - if (n == 0) return 1; - int count = 0; - // 从 1 个分裂出 n 个 - for (int i = 0; i < n; i++) { - count += factorialRecur(n - 1); - } - return count; - } + [class]{time_complexity}-[func]{factorialRecur} ``` === "C++" @@ -2452,35 +2358,9 @@ $$ === "Java" ```java title="worst_best_time_complexity.java" - public class worst_best_time_complexity { - /* 生成一个数组,元素为 { 1, 2, ..., n },顺序被打乱 */ - int[] randomNumbers(int n) { - Integer[] nums = new Integer[n]; - // 生成数组 nums = { 1, 2, 3, ..., n } - for (int i = 0; i < n; i++) { - nums[i] = i + 1; - } - // 随机打乱数组元素 - Collections.shuffle(Arrays.asList(nums)); - // Integer[] -> int[] - int[] res = new int[n]; - for (int i = 0; i < n; i++) { - res[i] = nums[i]; - } - return res; - } + [class]{worst_best_time_complexity}-[func]{randomNumbers} - /* 查找数组 nums 中数字 1 所在索引 */ - int findOne(int[] nums) { - for (int i = 0; i < nums.length; i++) { - // 当元素 1 在数组头部时,达到最佳时间复杂度 O(1) - // 当元素 1 在数组尾部时,达到最差时间复杂度 O(n) - if (nums[i] == 1) - return i; - } - return -1; - } - } + [class]{worst_best_time_complexity}-[func]{findOne} ``` === "C++" diff --git a/docs/chapter_graph/graph_operations.md b/docs/chapter_graph/graph_operations.md index 4b86d4d39..56852565a 100644 --- a/docs/chapter_graph/graph_operations.md +++ b/docs/chapter_graph/graph_operations.md @@ -35,83 +35,7 @@ comments: true === "Java" ```java title="graph_adjacency_matrix.java" - /* 基于邻接矩阵实现的无向图类 */ - class GraphAdjMat { - List vertices; // 顶点列表,元素代表“顶点值”,索引代表“顶点索引” - List> adjMat; // 邻接矩阵,行列索引对应“顶点索引” - - /* 构造函数 */ - public GraphAdjMat(int[] vertices, int[][] edges) { - this.vertices = new ArrayList<>(); - this.adjMat = new ArrayList<>(); - // 添加顶点 - for (int val : vertices) { - addVertex(val); - } - // 添加边 - // 请注意,edges 元素代表顶点索引,即对应 vertices 元素索引 - for (int[] e : edges) { - addEdge(e[0], e[1]); - } - } - - /* 获取顶点数量 */ - public int size() { - return vertices.size(); - } - - /* 添加顶点 */ - public void addVertex(int val) { - int n = size(); - // 向顶点列表中添加新顶点的值 - vertices.add(val); - // 在邻接矩阵中添加一行 - List newRow = new ArrayList<>(n); - for (int j = 0; j < n; j++) { - newRow.add(0); - } - adjMat.add(newRow); - // 在邻接矩阵中添加一列 - for (List row : adjMat) { - row.add(0); - } - } - - /* 删除顶点 */ - public void removeVertex(int index) { - if (index >= size()) - throw new IndexOutOfBoundsException(); - // 在顶点列表中移除索引 index 的顶点 - vertices.remove(index); - // 在邻接矩阵中删除索引 index 的行 - adjMat.remove(index); - // 在邻接矩阵中删除索引 index 的列 - for (List row : adjMat) { - row.remove(index); - } - } - - /* 添加边 */ - // 参数 i, j 对应 vertices 元素索引 - public void addEdge(int i, int j) { - // 索引越界与相等处理 - if (i < 0 || j < 0 || i >= size() || j >= size() || i == j) - throw new IndexOutOfBoundsException(); - // 在无向图中,邻接矩阵沿主对角线对称,即满足 (i, j) == (j, i) - adjMat.get(i).set(j, 1); - adjMat.get(j).set(i, 1); - } - - /* 删除边 */ - // 参数 i, j 对应 vertices 元素索引 - public void removeEdge(int i, int j) { - // 索引越界与相等处理 - if (i < 0 || j < 0 || i >= size() || j >= size() || i == j) - throw new IndexOutOfBoundsException(); - adjMat.get(i).set(j, 0); - adjMat.get(j).set(i, 0); - } - } + [class]{GraphAdjMat}-[func]{} ``` === "C++" @@ -357,73 +281,9 @@ comments: true === "Java" ```java title="graph_adjacency_list.java" - /* 顶点类 */ - class Vertex { - int val; - public Vertex(int val) { - this.val = val; - } - } - - /* 基于邻接表实现的无向图类 */ - class GraphAdjList { - // 请注意,vertices 和 adjList 中存储的都是 Vertex 对象 - Map> adjList; // 邻接表(使用哈希表实现) - - /* 构造函数 */ - public GraphAdjList(Vertex[][] edges) { - this.adjList = new HashMap<>(); - // 添加所有顶点和边 - for (Vertex[] edge : edges) { - addVertex(edge[0]); - addVertex(edge[1]); - addEdge(edge[0], edge[1]); - } - } - - /* 获取顶点数量 */ - public int size() { - return adjList.size(); - } - - /* 添加边 */ - public void addEdge(Vertex vet1, Vertex vet2) { - if (!adjList.containsKey(vet1) || !adjList.containsKey(vet2) || vet1 == vet2) - throw new IllegalArgumentException(); - // 添加边 vet1 - vet2 - adjList.get(vet1).add(vet2); - adjList.get(vet2).add(vet1); - } - - /* 删除边 */ - public void removeEdge(Vertex vet1, Vertex vet2) { - if (!adjList.containsKey(vet1) || !adjList.containsKey(vet2) || vet1 == vet2) - throw new IllegalArgumentException(); - // 删除边 vet1 - vet2 - adjList.get(vet1).remove(vet2); - adjList.get(vet2).remove(vet1); - } - - /* 添加顶点 */ - public void addVertex(Vertex vet) { - if (adjList.containsKey(vet)) - return; - // 在邻接表中添加一个新链表(即 HashSet) - adjList.put(vet, new HashSet<>()); - } - - /* 删除顶点 */ - public void removeVertex(Vertex vet) { - if (!adjList.containsKey(vet)) - throw new IllegalArgumentException(); - // 在邻接表中删除顶点 vet 对应的链表(即 HashSet) - adjList.remove(vet); - // 遍历其它顶点的链表(即 HashSet),删除所有包含 vet 的边 - for (Set set : adjList.values()) { - set.remove(vet); - } - } - } + [class]{Vertex}-[func]{} + + [class]{GraphAdjList}-[func]{} ``` === "C++" diff --git a/docs/chapter_hashing/hash_map.md b/docs/chapter_hashing/hash_map.md index 8708fb38a..3a54103e6 100755 --- a/docs/chapter_hashing/hash_map.md +++ b/docs/chapter_hashing/hash_map.md @@ -416,55 +416,9 @@ $$ === "Java" ```java title="array_hash_map.java" - /* 键值对 int->String */ - class Entry { - public int key; // 键 - public String val; // 值 - public Entry(int key, String val) { - this.key = key; - this.val = val; - } - } - - /* 基于数组简易实现的哈希表 */ - class ArrayHashMap { - private List bucket; - public ArrayHashMap() { - // 初始化一个长度为 100 的桶(数组) - bucket = new ArrayList<>(); - for (int i = 0; i < 100; i++) { - bucket.add(null); - } - } - - /* 哈希函数 */ - private int hashFunc(int key) { - int index = key % 100; - return index; - } - - /* 查询操作 */ - public String get(int key) { - int index = hashFunc(key); - Entry pair = bucket.get(index); - if (pair == null) return null; - return pair.val; - } - - /* 添加操作 */ - public void put(int key, String val) { - Entry pair = new Entry(key, val); - int index = hashFunc(key); - bucket.set(index, pair); - } - - /* 删除操作 */ - public void remove(int key) { - int index = hashFunc(key); - // 置为 null,代表删除 - bucket.set(index, null); - } - } + [class]{Entry}-[func]{} + + [class]{ArrayHashMap}-[func]{} ``` === "C++" diff --git a/docs/chapter_heap/heap.md b/docs/chapter_heap/heap.md index 79c1ded80..082ef9e7b 100644 --- a/docs/chapter_heap/heap.md +++ b/docs/chapter_heap/heap.md @@ -262,26 +262,14 @@ comments: true ```java title="my_heap.java" // 使用列表而非数组,这样无需考虑扩容问题 List maxHeap; - - /* 构造函数,建立空堆 */ - public MaxHeap() { - maxHeap = new ArrayList<>(); - } - - /* 获取左子结点索引 */ - int left(int i) { - return 2 * i + 1; - } - - /* 获取右子结点索引 */ - int right(int i) { - return 2 * i + 2; - } - - /* 获取父结点索引 */ - int parent(int i) { - return (i - 1) / 2; // 向下整除 - } + + [class]{MaxHeap}-[func]{MaxHeap} + + [class]{MaxHeap}-[func]{left} + + [class]{MaxHeap}-[func]{right} + + [class]{MaxHeap}-[func]{parent} ``` === "C++" @@ -407,10 +395,7 @@ comments: true === "Java" ```java title="my_heap.java" - /* 访问堆顶元素 */ - public int peek() { - return maxHeap.get(0); - } + [class]{MaxHeap}-[func]{peek} ``` === "C++" @@ -505,28 +490,9 @@ comments: true === "Java" ```java title="my_heap.java" - /* 元素入堆 */ - void push(int val) { - // 添加结点 - maxHeap.add(val); - // 从底至顶堆化 - siftUp(size() - 1); - } - - /* 从结点 i 开始,从底至顶堆化 */ - void siftUp(int i) { - while (true) { - // 获取结点 i 的父结点 - int p = parent(i); - // 若“越过根结点”或“结点无需修复”,则结束堆化 - if (p < 0 || maxHeap.get(i) <= maxHeap.get(p)) - break; - // 交换两结点 - swap(i, p); - // 循环向上堆化 - i = p; - } - } + [class]{MaxHeap}-[func]{push} + + [class]{MaxHeap}-[func]{siftUp} ``` === "C++" @@ -694,38 +660,9 @@ comments: true === "Java" ```java title="my_heap.java" - /* 元素出堆 */ - int poll() { - // 判空处理 - if (isEmpty()) - throw new EmptyStackException(); - // 交换根结点与最右叶结点(即交换首元素与尾元素) - swap(0, size() - 1); - // 删除结点 - int val = maxHeap.remove(size() - 1); - // 从顶至底堆化 - siftDown(0); - // 返回堆顶元素 - return val; - } - - /* 从结点 i 开始,从顶至底堆化 */ - void siftDown(int i) { - while (true) { - // 判断结点 i, l, r 中值最大的结点,记为 ma - int l = left(i), r = right(i), ma = i; - if (l < size() && maxHeap.get(l) > maxHeap.get(ma)) - ma = l; - if (r < size() && maxHeap.get(r) > maxHeap.get(ma)) - ma = r; - // 若“结点 i 最大”或“越过叶结点”,则结束堆化 - if (ma == i) break; - // 交换两结点 - swap(i, ma); - // 循环向下堆化 - i = ma; - } - } + [class]{MaxHeap}-[func]{poll} + + [class]{MaxHeap}-[func]{siftDown} ``` === "C++" @@ -901,15 +838,7 @@ comments: true === "Java" ```java title="my_heap.java" - /* 构造函数,根据输入列表建堆 */ - public MaxHeap(List nums) { - // 将列表元素原封不动添加进堆 - maxHeap = new ArrayList<>(nums); - // 堆化除叶结点以外的其他所有结点 - for (int i = parent(size() - 1); i >= 0; i--) { - siftDown(i); - } - } + [class]{MaxHeap}-[func]{MaxHeap} ``` === "C++" diff --git a/docs/chapter_searching/binary_search.md b/docs/chapter_searching/binary_search.md index 531d48a28..3cd9a8e37 100755 --- a/docs/chapter_searching/binary_search.md +++ b/docs/chapter_searching/binary_search.md @@ -54,23 +54,7 @@ $$ === "Java" ```java title="binary_search.java" - /* 二分查找(双闭区间) */ - int binarySearch(int[] nums, int target) { - // 初始化双闭区间 [0, n-1] ,即 i, j 分别指向数组首元素、尾元素 - int i = 0, j = nums.length - 1; - // 循环,当搜索区间为空时跳出(当 i > j 时为空) - while (i <= j) { - int m = (i + j) / 2; // 计算中点索引 m - if (nums[m] < target) // 此情况说明 target 在区间 [m+1, j] 中 - i = m + 1; - else if (nums[m] > target) // 此情况说明 target 在区间 [i, m-1] 中 - j = m - 1; - else // 找到目标元素,返回其索引 - return m; - } - // 未找到目标元素,返回 -1 - return -1; - } + [class]{binary_search}-[func]{binarySearch} ``` === "C++" @@ -235,23 +219,7 @@ $$ === "Java" ```java title="binary_search.java" - /* 二分查找(左闭右开) */ - int binarySearch1(int[] nums, int target) { - // 初始化左闭右开 [0, n) ,即 i, j 分别指向数组首元素、尾元素+1 - int i = 0, j = nums.length; - // 循环,当搜索区间为空时跳出(当 i = j 时为空) - while (i < j) { - int m = (i + j) / 2; // 计算中点索引 m - if (nums[m] < target) // 此情况说明 target 在区间 [m+1, j) 中 - i = m + 1; - else if (nums[m] > target) // 此情况说明 target 在区间 [i, m) 中 - j = m; - else // 找到目标元素,返回其索引 - return m; - } - // 未找到目标元素,返回 -1 - return -1; - } + [class]{binary_search}-[func]{binarySearch1} ``` === "C++" diff --git a/docs/chapter_searching/hashing_search.md b/docs/chapter_searching/hashing_search.md index 043106ef0..e3c6c2132 100755 --- a/docs/chapter_searching/hashing_search.md +++ b/docs/chapter_searching/hashing_search.md @@ -19,12 +19,7 @@ comments: true === "Java" ```java title="hashing_search.java" - /* 哈希查找(数组) */ - int hashingSearchArray(Map map, int target) { - // 哈希表的 key: 目标元素,value: 索引 - // 若哈希表中无此 key ,返回 -1 - return map.getOrDefault(target, -1); - } + [class]{hashing_search}-[func]{hashingSearchArray} ``` === "C++" @@ -125,12 +120,7 @@ comments: true === "Java" ```java title="hashing_search.java" - /* 哈希查找(链表) */ - ListNode hashingSearchLinkedList(Map map, int target) { - // 哈希表的 key: 目标结点值,value: 结点对象 - // 若哈希表中无此 key ,返回 null - return map.getOrDefault(target, null); - } + [class]{hashing_search}-[func]{hashingSearchLinkedList} ``` === "C++" diff --git a/docs/chapter_searching/linear_search.md b/docs/chapter_searching/linear_search.md index 1a6e62722..58f0661cc 100755 --- a/docs/chapter_searching/linear_search.md +++ b/docs/chapter_searching/linear_search.md @@ -15,17 +15,7 @@ comments: true === "Java" ```java title="linear_search.java" - /* 线性查找(数组) */ - int linearSearchArray(int[] nums, int target) { - // 遍历数组 - for (int i = 0; i < nums.length; i++) { - // 找到目标元素,返回其索引 - if (nums[i] == target) - return i; - } - // 未找到目标元素,返回 -1 - return -1; - } + [class]{hashing_search}-[func]{linearSearchArray} ``` === "C++" @@ -155,18 +145,7 @@ comments: true === "Java" ```java title="linear_search.java" - /* 线性查找(链表) */ - ListNode linearSearchLinkedList(ListNode head, int target) { - // 遍历链表 - while (head != null) { - // 找到目标结点,返回之 - if (head.val == target) - return head; - head = head.next; - } - // 未找到目标结点,返回 null - return null; - } + [class]{hashing_search}-[func]{linearSearchLinkedList} ``` === "C++" diff --git a/docs/chapter_sorting/bubble_sort.md b/docs/chapter_sorting/bubble_sort.md index 0337ac432..e229e450c 100755 --- a/docs/chapter_sorting/bubble_sort.md +++ b/docs/chapter_sorting/bubble_sort.md @@ -50,21 +50,7 @@ comments: true === "Java" ```java title="bubble_sort.java" - /* 冒泡排序 */ - void bubbleSort(int[] nums) { - // 外循环:待排序元素数量为 n-1, n-2, ..., 1 - for (int i = nums.length - 1; i > 0; i--) { - // 内循环:冒泡操作 - for (int j = 0; j < i; j++) { - if (nums[j] > nums[j + 1]) { - // 交换 nums[j] 与 nums[j + 1] - int tmp = nums[j]; - nums[j] = nums[j + 1]; - nums[j + 1] = tmp; - } - } - } - } + [class]{bubble_sort}-[func]{bubbleSort} ``` === "C++" @@ -243,24 +229,7 @@ comments: true === "Java" ```java title="bubble_sort.java" - /* 冒泡排序(标志优化)*/ - void bubbleSortWithFlag(int[] nums) { - // 外循环:待排序元素数量为 n-1, n-2, ..., 1 - for (int i = nums.length - 1; i > 0; i--) { - boolean flag = false; // 初始化标志位 - // 内循环:冒泡操作 - for (int j = 0; j < i; j++) { - if (nums[j] > nums[j + 1]) { - // 交换 nums[j] 与 nums[j + 1] - int tmp = nums[j]; - nums[j] = nums[j + 1]; - nums[j + 1] = tmp; - flag = true; // 记录交换元素 - } - } - if (!flag) break; // 此轮冒泡未交换任何元素,直接跳出 - } - } + [class]{bubble_sort}-[func]{bubbleSortWithFlag} ``` === "C++" diff --git a/docs/chapter_sorting/insertion_sort.md b/docs/chapter_sorting/insertion_sort.md index 130d2c7cf..3cc791e10 100755 --- a/docs/chapter_sorting/insertion_sort.md +++ b/docs/chapter_sorting/insertion_sort.md @@ -27,19 +27,7 @@ comments: true === "Java" ```java title="insertion_sort.java" - /* 插入排序 */ - void insertionSort(int[] nums) { - // 外循环:base = nums[1], nums[2], ..., nums[n-1] - for (int i = 1; i < nums.length; i++) { - int base = nums[i], j = i - 1; - // 内循环:将 base 插入到左边的正确位置 - while (j >= 0 && nums[j] > base) { - nums[j + 1] = nums[j]; // 1. 将 nums[j] 向右移动一位 - j--; - } - nums[j + 1] = base; // 2. 将 base 赋值到正确位置 - } - } + [class]{insertion_sort}-[func]{insertionSort} ``` === "C++" diff --git a/docs/chapter_sorting/merge_sort.md b/docs/chapter_sorting/merge_sort.md index 7e11a6b22..ec4ec3a93 100755 --- a/docs/chapter_sorting/merge_sort.md +++ b/docs/chapter_sorting/merge_sort.md @@ -62,55 +62,17 @@ comments: true === "Java" ```java title="merge_sort.java" - /** - * 合并左子数组和右子数组 - * 左子数组区间 [left, mid] - * 右子数组区间 [mid + 1, right] - */ - void merge(int[] nums, int left, int mid, int right) { - // 初始化辅助数组 - int[] tmp = Arrays.copyOfRange(nums, left, right + 1); - // 左子数组的起始索引和结束索引 - int leftStart = left - left, leftEnd = mid - left; - // 右子数组的起始索引和结束索引 - int rightStart = mid + 1 - left, rightEnd = right - left; - // i, j 分别指向左子数组、右子数组的首元素 - int i = leftStart, j = rightStart; - // 通过覆盖原数组 nums 来合并左子数组和右子数组 - for (int k = left; k <= right; k++) { - // 若“左子数组已全部合并完”,则选取右子数组元素,并且 j++ - if (i > leftEnd) - nums[k] = tmp[j++]; - // 否则,若“右子数组已全部合并完”或“左子数组元素 <= 右子数组元素”,则选取左子数组元素,并且 i++ - else if (j > rightEnd || tmp[i] <= tmp[j]) - nums[k] = tmp[i++]; - // 否则,若“左右子数组都未全部合并完”且“左子数组元素 > 右子数组元素”,则选取右子数组元素,并且 j++ - else - nums[k] = tmp[j++]; - } - } - - /* 归并排序 */ - void mergeSort(int[] nums, int left, int right) { - // 终止条件 - if (left >= right) return; // 当子数组长度为 1 时终止递归 - // 递归划分 - int mid = (left + right) / 2; // 计算数组中点 - mergeSort(nums, left, mid); // 递归左子数组 - mergeSort(nums, mid + 1, right); // 递归右子数组 - // 回溯合并 - merge(nums, left, mid, right); - } + [class]{merge_sort}-[func]{merge} + + [class]{merge_sort}-[func]{mergeSort} ``` === "C++" ```cpp title="merge_sort.cpp" - /** - * 合并左子数组和右子数组 - * 左子数组区间 [left, mid] - * 右子数组区间 [mid + 1, right] - */ + /* 合并左子数组和右子数组 */ + // 左子数组区间 [left, mid] + // 右子数组区间 [mid + 1, right] void merge(vector& nums, int left, int mid, int right) { // 初始化辅助数组 vector tmp(nums.begin() + left, nums.begin() + right + 1); @@ -210,11 +172,9 @@ comments: true === "JavaScript" ```js title="merge_sort.js" - /** - * 合并左子数组和右子数组 - * 左子数组区间 [left, mid] - * 右子数组区间 [mid + 1, right] - */ + /* 合并左子数组和右子数组 */ + // 左子数组区间 [left, mid] + // 右子数组区间 [mid + 1, right] function merge(nums, left, mid, right) { // 初始化辅助数组 let tmp = nums.slice(left, right + 1); @@ -255,11 +215,9 @@ comments: true === "TypeScript" ```typescript title="merge_sort.ts" - /** - * 合并左子数组和右子数组 - * 左子数组区间 [left, mid] - * 右子数组区间 [mid + 1, right] - */ + /* 合并左子数组和右子数组 */ + // 左子数组区间 [left, mid] + // 右子数组区间 [mid + 1, right] function merge(nums: number[], left: number, mid: number, right: number): void { // 初始化辅助数组 let tmp = nums.slice(left, right + 1); @@ -306,11 +264,9 @@ comments: true === "C#" ```csharp title="merge_sort.cs" - /** - * 合并左子数组和右子数组 - * 左子数组区间 [left, mid] - * 右子数组区间 [mid + 1, right] - */ + /* 合并左子数组和右子数组 */ + // 左子数组区间 [left, mid] + // 右子数组区间 [mid + 1, right] void merge(int[] nums, int left, int mid, int right) { // 初始化辅助数组 diff --git a/docs/chapter_sorting/quick_sort.md b/docs/chapter_sorting/quick_sort.md index e8a97384e..8f694b8f1 100755 --- a/docs/chapter_sorting/quick_sort.md +++ b/docs/chapter_sorting/quick_sort.md @@ -45,28 +45,10 @@ comments: true === "Java" - ``` java title="quick_sort.java" - /* 元素交换 */ - void swap(int[] nums, int i, int j) { - int tmp = nums[i]; - nums[i] = nums[j]; - nums[j] = tmp; - } - - /* 哨兵划分 */ - int partition(int[] nums, int left, int right) { - // 以 nums[left] 作为基准数 - int i = left, j = right; - while (i < j) { - while (i < j && nums[j] >= nums[left]) - j--; // 从右向左找首个小于基准数的元素 - while (i < j && nums[i] <= nums[left]) - i++; // 从左向右找首个大于基准数的元素 - swap(nums, i, j); // 交换这两个元素 - } - swap(nums, i, left); // 将基准数交换至两子数组的分界线 - return i; // 返回基准数的索引 - } + ```java title="quick_sort.java" + [class]{QuickSort}-[func]{swap} + + [class]{QuickSort}-[func]{partition} ``` === "C++" @@ -271,17 +253,7 @@ comments: true === "Java" ```java title="quick_sort.java" - /* 快速排序 */ - void quickSort(int[] nums, int left, int right) { - // 子数组长度为 1 时终止递归 - if (left >= right) - return; - // 哨兵划分 - int pivot = partition(nums, left, right); - // 递归左子数组、右子数组 - quickSort(nums, left, pivot - 1); - quickSort(nums, pivot + 1, right); - } + [class]{QuickSort}-[func]{quickSort} ``` === "C++" @@ -435,27 +407,9 @@ comments: true === "Java" ```java title="quick_sort.java" - /* 选取三个元素的中位数 */ - int medianThree(int[] nums, int left, int mid, int right) { - // 使用了异或操作来简化代码 - // 异或规则为 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 - return right; - } - - /* 哨兵划分(三数取中值) */ - int partition(int[] nums, int left, int right) { - // 选取三个候选元素的中位数 - int med = medianThree(nums, left, (left + right) / 2, right); - // 将中位数交换至数组最左端 - swap(nums, left, med); - // 以 nums[left] 作为基准数 - // 下同省略... - } + [class]{QuickSortMedian}-[func]{medianThree} + + [class]{QuickSortMedian}-[func]{partition} ``` === "C++" @@ -642,22 +596,7 @@ comments: true === "Java" ```java title="quick_sort.java" - /* 快速排序(尾递归优化) */ - void quickSort(int[] nums, int left, int right) { - // 子数组长度为 1 时终止 - while (left < right) { - // 哨兵划分操作 - int pivot = partition(nums, left, right); - // 对两个子数组中较短的那个执行快排 - if (pivot - left < right - pivot) { - quickSort(nums, left, pivot - 1); // 递归排序左子数组 - left = pivot + 1; // 剩余待排序区间为 [pivot + 1, right] - } else { - quickSort(nums, pivot + 1, right); // 递归排序右子数组 - right = pivot - 1; // 剩余待排序区间为 [left, pivot - 1] - } - } - } + [class]{QuickSortTailCall}-[func]{quickSort} ``` === "C++" diff --git a/docs/chapter_stack_and_queue/deque.md b/docs/chapter_stack_and_queue/deque.md index 2ed4c866f..5de04f187 100644 --- a/docs/chapter_stack_and_queue/deque.md +++ b/docs/chapter_stack_and_queue/deque.md @@ -321,119 +321,9 @@ comments: true === "Java" ```java title="linkedlist_deque.java" - /* 双向链表结点 */ - class ListNode { - int val; // 结点值 - ListNode next; // 后继结点引用(指针) - ListNode prev; // 前驱结点引用(指针) - ListNode(int val) { - this.val = val; - prev = next = null; - } - } - - /* 基于双向链表实现的双向队列 */ - class LinkedListDeque { - private ListNode front, rear; // 头结点 front ,尾结点 rear - private int size = 0; // 双向队列的长度 - - public LinkedListDeque() { - front = rear = null; - } - - /* 获取双向队列的长度 */ - public int size() { - return size; - } - - /* 判断双向队列是否为空 */ - public boolean isEmpty() { - return size() == 0; - } - - /* 入队操作 */ - private void push(int num, boolean isFront) { - ListNode node = new ListNode(num); - // 若链表为空,则令 front, rear 都指向 node - if (isEmpty()) - front = rear = node; - // 队首入队操作 - else if (isFront) { - // 将 node 添加至链表头部 - front.prev = node; - node.next = front; - front = node; // 更新头结点 - // 队尾入队操作 - } else { - // 将 node 添加至链表尾部 - rear.next = node; - node.prev = rear; - rear = node; // 更新尾结点 - } - size++; // 更新队列长度 - } - - /* 队首入队 */ - public void pushFirst(int num) { - push(num, true); - } - - /* 队尾入队 */ - public void pushLast(int num) { - push(num, false); - } - - /* 出队操作 */ - private Integer poll(boolean isFront) { - // 若队列为空,直接返回 null - if (isEmpty()) - return null; - int val; - // 队首出队操作 - if (isFront) { - val = front.val; // 暂存头结点值 - // 删除头结点 - ListNode fNext = front.next; - if (fNext != null) { - fNext.prev = null; - front.next = null; - } - front = fNext; // 更新头结点 - // 队尾出队操作 - } else { - val = rear.val; // 暂存尾结点值 - // 删除尾结点 - ListNode rPrev = rear.prev; - if (rPrev != null) { - rPrev.next = null; - rear.prev = null; - } - rear = rPrev; // 更新尾结点 - } - size--; // 更新队列长度 - return val; - } - - /* 队首出队 */ - public Integer pollFirst() { - return poll(true); - } - - /* 队尾出队 */ - public Integer pollLast() { - return poll(false); - } - - /* 访问队首元素 */ - public Integer peekFirst() { - return isEmpty() ? null : front.val; - } - - /* 访问队尾元素 */ - public Integer peekLast() { - return isEmpty() ? null : rear.val; - } - } + [class]{ListNode}-[func]{} + + [class]{LinkedListDeque}-[func]{} ``` === "C++" diff --git a/docs/chapter_stack_and_queue/queue.md b/docs/chapter_stack_and_queue/queue.md index ae4825e83..9860503bd 100755 --- a/docs/chapter_stack_and_queue/queue.md +++ b/docs/chapter_stack_and_queue/queue.md @@ -284,53 +284,7 @@ comments: true === "Java" ```java title="linkedlist_queue.java" - /* 基于链表实现的队列 */ - class LinkedListQueue { - private ListNode front, rear; // 头结点 front ,尾结点 rear - private int queSize = 0; - - public LinkedListQueue() { - front = null; - rear = null; - } - /* 获取队列的长度 */ - public int size() { - return queSize; - } - /* 判断队列是否为空 */ - public boolean isEmpty() { - return size() == 0; - } - /* 入队 */ - public void push(int num) { - // 尾结点后添加 num - ListNode node = new ListNode(num); - // 如果队列为空,则令头、尾结点都指向该结点 - if (front == null) { - front = node; - rear = node; - // 如果队列不为空,则将该结点添加到尾结点后 - } else { - rear.next = node; - rear = node; - } - queSize++; - } - /* 出队 */ - public int poll() { - int num = peek(); - // 删除头结点 - front = front.next; - queSize--; - return num; - } - /* 访问队首元素 */ - public int peek() { - if (size() == 0) - throw new EmptyStackException(); - return front.val; - } - } + [class]{LinkedListQueue}-[func]{} ``` === "C++" @@ -709,62 +663,7 @@ comments: true === "Java" ```java title="array_queue.java" - /* 基于环形数组实现的队列 */ - class ArrayQueue { - private int[] nums; // 用于存储队列元素的数组 - private int front; // 队首指针,指向队首元素 - private int queSize; // 队列长度 - - public ArrayQueue(int capacity) { - nums = new int[capacity]; - front = queSize = 0; - } - - /* 获取队列的容量 */ - public int capacity() { - return nums.length; - } - - /* 获取队列的长度 */ - public int size() { - return queSize; - } - - /* 判断队列是否为空 */ - public boolean isEmpty() { - return queSize == 0; - } - - /* 入队 */ - public void push(int num) { - if (queSize == capacity()) { - System.out.println("队列已满"); - return; - } - // 计算尾指针,指向队尾索引 + 1 - // 通过取余操作,实现 rear 越过数组尾部后回到头部 - int rear = (front + queSize) % capacity(); - // 尾结点后添加 num - nums[rear] = num; - queSize++; - } - - /* 出队 */ - public int poll() { - int num = peek(); - // 队首指针向后移动一位,若越过尾部则返回到数组头部 - front = (front + 1) % capacity(); - queSize--; - return num; - } - - /* 访问队首元素 */ - public int peek() { - if (isEmpty()) - throw new EmptyStackException(); - return nums[front]; - } - } + [class]{ArrayQueue}-[func]{} ``` === "C++" diff --git a/docs/chapter_stack_and_queue/stack.md b/docs/chapter_stack_and_queue/stack.md index 38408fcfc..4c39995b6 100755 --- a/docs/chapter_stack_and_queue/stack.md +++ b/docs/chapter_stack_and_queue/stack.md @@ -287,42 +287,7 @@ comments: true === "Java" ```java title="linkedlist_stack.java" - /* 基于链表实现的栈 */ - class LinkedListStack { - private ListNode stackPeek; // 将头结点作为栈顶 - private int stkSize = 0; // 栈的长度 - public LinkedListStack() { - stackPeek = null; - } - /* 获取栈的长度 */ - public int size() { - return stkSize; - } - /* 判断栈是否为空 */ - public boolean isEmpty() { - return size() == 0; - } - /* 入栈 */ - public void push(int num) { - ListNode node = new ListNode(num); - node.next = stackPeek; - stackPeek = node; - stkSize++; - } - /* 出栈 */ - public int pop() { - int num = peek(); - stackPeek = stackPeek.next; - stkSize--; - return num; - } - /* 访问栈顶元素 */ - public int peek() { - if (size() == 0) - throw new EmptyStackException(); - return stackPeek.val; - } - } + [class]{LinkedListStack}-[func]{} ``` === "C++" @@ -681,38 +646,7 @@ comments: true === "Java" ```java title="array_stack.java" - /* 基于数组实现的栈 */ - class ArrayStack { - private ArrayList stack; - public ArrayStack() { - // 初始化列表(动态数组) - stack = new ArrayList<>(); - } - /* 获取栈的长度 */ - public int size() { - return stack.size(); - } - /* 判断栈是否为空 */ - public boolean isEmpty() { - return size() == 0; - } - /* 入栈 */ - public void push(int num) { - stack.add(num); - } - /* 出栈 */ - public int pop() { - if (isEmpty()) - throw new EmptyStackException(); - return stack.remove(size() - 1); - } - /* 访问栈顶元素 */ - public int peek() { - if (isEmpty()) - throw new EmptyStackException(); - return stack.get(size() - 1); - } - } + [class]{ArrayStack}-[func]{} ``` === "C++" diff --git a/docs/chapter_tree/avl_tree.md b/docs/chapter_tree/avl_tree.md index 80ae659b6..0a4b2d058 100755 --- a/docs/chapter_tree/avl_tree.md +++ b/docs/chapter_tree/avl_tree.md @@ -28,7 +28,7 @@ G. M. Adelson-Velsky 和 E. M. Landis 在其 1962 年发表的论文 "An algorit === "Java" - ```java title="avl_tree.java" + ```java title="" /* AVL 树结点类 */ class TreeNode { public int val; // 结点值 @@ -41,7 +41,7 @@ G. M. Adelson-Velsky 和 E. M. Landis 在其 1962 年发表的论文 "An algorit === "C++" - ```cpp title="avl_tree.cpp" + ```cpp title="" /* AVL 树结点类 */ struct TreeNode { int val{}; // 结点值 @@ -55,7 +55,7 @@ G. M. Adelson-Velsky 和 E. M. Landis 在其 1962 年发表的论文 "An algorit === "Python" - ```python title="avl_tree.py" + ```python title="" """ AVL 树结点类 """ class TreeNode: def __init__(self, val=None, left=None, right=None): @@ -67,7 +67,7 @@ G. M. Adelson-Velsky 和 E. M. Landis 在其 1962 年发表的论文 "An algorit === "Go" - ```go title="avl_tree.go" + ```go title="" /* AVL 树结点类 */ type TreeNode struct { Val int // 结点值 @@ -79,7 +79,7 @@ G. M. Adelson-Velsky 和 E. M. Landis 在其 1962 年发表的论文 "An algorit === "JavaScript" - ```js title="avl_tree.js" + ```js title="" class TreeNode { val; // 结点值 height; //结点高度 @@ -96,7 +96,7 @@ G. M. Adelson-Velsky 和 E. M. Landis 在其 1962 年发表的论文 "An algorit === "TypeScript" - ```typescript title="avl_tree.ts" + ```typescript title="" class TreeNode { val: number; // 结点值 height: number; // 结点高度 @@ -113,13 +113,13 @@ G. M. Adelson-Velsky 和 E. M. Landis 在其 1962 年发表的论文 "An algorit === "C" - ```c title="avl_tree.c" + ```c title="" ``` === "C#" - ```csharp title="avl_tree.cs" + ```csharp title="" /* AVL 树结点类 */ class TreeNode { public int val; // 结点值 @@ -132,7 +132,7 @@ G. M. Adelson-Velsky 和 E. M. Landis 在其 1962 年发表的论文 "An algorit === "Swift" - ```swift title="avl_tree.swift" + ```swift title="" /* AVL 树结点类 */ class TreeNode { var val: Int // 结点值 @@ -149,7 +149,7 @@ G. M. Adelson-Velsky 和 E. M. Landis 在其 1962 年发表的论文 "An algorit === "Zig" - ```zig title="avl_tree.zig" + ```zig title="" ``` @@ -158,17 +158,9 @@ G. M. Adelson-Velsky 和 E. M. Landis 在其 1962 年发表的论文 "An algorit === "Java" ```java title="avl_tree.java" - /* 获取结点高度 */ - int height(TreeNode node) { - // 空结点高度为 -1 ,叶结点高度为 0 - return node == null ? -1 : node.height; - } + [class]{AVLTree}-[func]{height} - /* 更新结点高度 */ - void updateHeight(TreeNode node) { - // 结点高度等于最高子树高度 + 1 - node.height = Math.max(height(node.left), height(node.right)) + 1; - } + [class]{AVLTree}-[func]{updateHeight} ``` === "C++" @@ -305,13 +297,7 @@ G. M. Adelson-Velsky 和 E. M. Landis 在其 1962 年发表的论文 "An algorit === "Java" ```java title="avl_tree.java" - /* 获取结点平衡因子 */ - public int balanceFactor(TreeNode node) { - // 空结点平衡因子为 0 - if (node == null) return 0; - // 结点平衡因子 = 左子树高度 - 右子树高度 - return height(node.left) - height(node.right); - } + [class]{AVLTree}-[func]{balanceFactor} ``` === "C++" @@ -421,7 +407,7 @@ AVL 树的独特之处在于「旋转 Rotation」的操作,其可 **在不影 ### Case 1 - 右旋 -如下图所示(结点下方为「平衡因子」),从底至顶看,二叉树中首个失衡结点是 **结点 3**。我们聚焦在以该失衡结点为根结点的子树上,将该结点记为 `node` ,将其左子节点记为 `child` ,执行「右旋」操作。完成右旋后,该子树已经恢复平衡,并且仍然为二叉搜索树。 +如下图所示(结点下方为「平衡因子」),从底至顶看,二叉树中首个失衡结点是 **结点 3**。我们聚焦在以该失衡结点为根结点的子树上,将该结点记为 `node` ,将其左子结点记为 `child` ,执行「右旋」操作。完成右旋后,该子树已经恢复平衡,并且仍然为二叉搜索树。 === "Step 1" ![right_rotate_step1](avl_tree.assets/right_rotate_step1.png) @@ -444,19 +430,7 @@ AVL 树的独特之处在于「旋转 Rotation」的操作,其可 **在不影 === "Java" ```java title="avl_tree.java" - /* 右旋操作 */ - TreeNode rightRotate(TreeNode node) { - TreeNode child = node.left; - TreeNode grandChild = child.right; - // 以 child 为原点,将 node 向右旋转 - child.right = node; - node.left = grandChild; - // 更新结点高度 - updateHeight(node); - updateHeight(child); - // 返回旋转后子树的根节点 - return child; - } + [class]{AVLTree}-[func]{rightRotate} ``` === "C++" @@ -472,7 +446,7 @@ AVL 树的独特之处在于「旋转 Rotation」的操作,其可 **在不影 // 更新结点高度 updateHeight(node); updateHeight(child); - // 返回旋转后子树的根节点 + // 返回旋转后子树的根结点 return child; } ``` @@ -496,7 +470,7 @@ AVL 树的独特之处在于「旋转 Rotation」的操作,其可 **在不影 // 更新结点高度 updateHeight(node) updateHeight(child) - // 返回旋转后子树的根节点 + // 返回旋转后子树的根结点 return child } ``` @@ -514,7 +488,7 @@ AVL 树的独特之处在于「旋转 Rotation」的操作,其可 **在不影 // 更新结点高度 this.updateHeight(node); this.updateHeight(child); - // 返回旋转后子树的根节点 + // 返回旋转后子树的根结点 return child; } ``` @@ -532,7 +506,7 @@ AVL 树的独特之处在于「旋转 Rotation」的操作,其可 **在不影 // 更新结点高度 this.updateHeight(node); this.updateHeight(child); - // 返回旋转后子树的根节点 + // 返回旋转后子树的根结点 return child; } ``` @@ -557,7 +531,7 @@ AVL 树的独特之处在于「旋转 Rotation」的操作,其可 **在不影 // 更新结点高度 updateHeight(node); updateHeight(child); - // 返回旋转后子树的根节点 + // 返回旋转后子树的根结点 return child; } ``` @@ -575,7 +549,7 @@ AVL 树的独特之处在于「旋转 Rotation」的操作,其可 **在不影 // 更新结点高度 updateHeight(node: node) updateHeight(node: child) - // 返回旋转后子树的根节点 + // 返回旋转后子树的根结点 return child } ``` @@ -601,19 +575,7 @@ AVL 树的独特之处在于「旋转 Rotation」的操作,其可 **在不影 === "Java" ```java title="avl_tree.java" - /* 左旋操作 */ - private TreeNode leftRotate(TreeNode node) { - TreeNode child = node.right; - TreeNode grandChild = child.left; - // 以 child 为原点,将 node 向左旋转 - child.left = node; - node.right = grandChild; - // 更新结点高度 - updateHeight(node); - updateHeight(child); - // 返回旋转后子树的根节点 - return child; - } + [class]{AVLTree}-[func]{leftRotate} ``` === "C++" @@ -629,7 +591,7 @@ AVL 树的独特之处在于「旋转 Rotation」的操作,其可 **在不影 // 更新结点高度 updateHeight(node); updateHeight(child); - // 返回旋转后子树的根节点 + // 返回旋转后子树的根结点 return child; } ``` @@ -653,7 +615,7 @@ AVL 树的独特之处在于「旋转 Rotation」的操作,其可 **在不影 // 更新结点高度 updateHeight(node) updateHeight(child) - // 返回旋转后子树的根节点 + // 返回旋转后子树的根结点 return child } ``` @@ -671,7 +633,7 @@ AVL 树的独特之处在于「旋转 Rotation」的操作,其可 **在不影 // 更新结点高度 this.updateHeight(node); this.updateHeight(child); - // 返回旋转后子树的根节点 + // 返回旋转后子树的根结点 return child; } ``` @@ -689,7 +651,7 @@ AVL 树的独特之处在于「旋转 Rotation」的操作,其可 **在不影 // 更新结点高度 this.updateHeight(node); this.updateHeight(child); - // 返回旋转后子树的根节点 + // 返回旋转后子树的根结点 return child; } ``` @@ -716,7 +678,7 @@ AVL 树的独特之处在于「旋转 Rotation」的操作,其可 **在不影 // 更新结点高度 updateHeight(node); updateHeight(child); - // 返回旋转后子树的根节点 + // 返回旋转后子树的根结点 return child; } ``` @@ -734,7 +696,7 @@ AVL 树的独特之处在于「旋转 Rotation」的操作,其可 **在不影 // 更新结点高度 updateHeight(node: node) updateHeight(node: child) - // 返回旋转后子树的根节点 + // 返回旋转后子树的根结点 return child } @@ -782,35 +744,7 @@ AVL 树的独特之处在于「旋转 Rotation」的操作,其可 **在不影 === "Java" ```java title="avl_tree.java" - /* 执行旋转操作,使该子树重新恢复平衡 */ - TreeNode rotate(TreeNode node) { - // 获取结点 node 的平衡因子 - int balanceFactor = balanceFactor(node); - // 左偏树 - if (balanceFactor > 1) { - if (balanceFactor(node.left) >= 0) { - // 右旋 - return rightRotate(node); - } else { - // 先左旋后右旋 - node.left = leftRotate(node.left); - return rightRotate(node); - } - } - // 右偏树 - if (balanceFactor < -1) { - if (balanceFactor(node.right) <= 0) { - // 左旋 - return leftRotate(node); - } else { - // 先右旋后左旋 - node.right = rightRotate(node.right); - return leftRotate(node); - } - } - // 平衡树,无需旋转,直接返回 - return node; - } + [class]{AVLTree}-[func]{rotate} ``` === "C++" @@ -1054,28 +988,9 @@ AVL 树的独特之处在于「旋转 Rotation」的操作,其可 **在不影 === "Java" ```java title="avl_tree.java" - /* 插入结点 */ - TreeNode insert(int val) { - root = insertHelper(root, val); - return root; - } + [class]{AVLTree}-[func]{insert} - /* 递归插入结点(辅助函数) */ - TreeNode insertHelper(TreeNode node, int val) { - if (node == null) return new TreeNode(val); - /* 1. 查找插入位置,并插入结点 */ - if (val < node.val) - node.left = insertHelper(node.left, val); - else if (val > node.val) - node.right = insertHelper(node.right, val); - else - return node; // 重复结点不插入,直接返回 - updateHeight(node); // 更新结点高度 - /* 2. 执行旋转操作,使该子树重新恢复平衡 */ - node = rotate(node); - // 返回子树的根节点 - return node; - } + [class]{AVLTree}-[func]{insertHelper} ``` === "C++" @@ -1100,7 +1015,7 @@ AVL 树的独特之处在于「旋转 Rotation」的操作,其可 **在不影 updateHeight(node); // 更新结点高度 /* 2. 执行旋转操作,使该子树重新恢复平衡 */ node = rotate(node); - // 返回子树的根节点 + // 返回子树的根结点 return node; } ``` @@ -1139,7 +1054,7 @@ AVL 树的独特之处在于「旋转 Rotation」的操作,其可 **在不影 updateHeight(node) /* 2. 执行旋转操作,使该子树重新恢复平衡 */ node = rotate(node) - // 返回子树的根节点 + // 返回子树的根结点 return node } ``` @@ -1163,7 +1078,7 @@ AVL 树的独特之处在于「旋转 Rotation」的操作,其可 **在不影 this.updateHeight(node); // 更新结点高度 /* 2. 执行旋转操作,使该子树重新恢复平衡 */ node = this.rotate(node); - // 返回子树的根节点 + // 返回子树的根结点 return node; } ``` @@ -1191,7 +1106,7 @@ AVL 树的独特之处在于「旋转 Rotation」的操作,其可 **在不影 this.updateHeight(node); // 更新结点高度 /* 2. 执行旋转操作,使该子树重新恢复平衡 */ node = this.rotate(node); - // 返回子树的根节点 + // 返回子树的根结点 return node; } ``` @@ -1228,7 +1143,7 @@ AVL 树的独特之处在于「旋转 Rotation」的操作,其可 **在不影 updateHeight(node); // 更新结点高度 /* 2. 执行旋转操作,使该子树重新恢复平衡 */ node = rotate(node); - // 返回子树的根节点 + // 返回子树的根结点 return node; } ``` @@ -1260,7 +1175,7 @@ AVL 树的独特之处在于「旋转 Rotation」的操作,其可 **在不影 updateHeight(node: node) // 更新结点高度 /* 2. 执行旋转操作,使该子树重新恢复平衡 */ node = rotate(node: node) - // 返回子树的根节点 + // 返回子树的根结点 return node } ``` @@ -1278,42 +1193,11 @@ AVL 树的独特之处在于「旋转 Rotation」的操作,其可 **在不影 === "Java" ```java title="avl_tree.java" - /* 删除结点 */ - TreeNode remove(int val) { - root = removeHelper(root, val); - return root; - } + [class]{AVLTree}-[func]{remove} - /* 递归删除结点(辅助函数) */ - TreeNode removeHelper(TreeNode node, int val) { - if (node == null) return null; - /* 1. 查找结点,并删除之 */ - if (val < node.val) - node.left = removeHelper(node.left, val); - else if (val > node.val) - node.right = removeHelper(node.right, val); - else { - if (node.left == null || node.right == null) { - TreeNode child = node.left != null ? node.left : node.right; - // 子结点数量 = 0 ,直接删除 node 并返回 - if (child == null) - return null; - // 子结点数量 = 1 ,直接删除 node - else - node = child; - } else { - // 子结点数量 = 2 ,则将中序遍历的下个结点删除,并用该结点替换当前结点 - TreeNode temp = getInOrderNext(node.right); - node.right = removeHelper(node.right, temp.val); - node.val = temp.val; - } - } - updateHeight(node); // 更新结点高度 - /* 2. 执行旋转操作,使该子树重新恢复平衡 */ - node = rotate(node); - // 返回子树的根节点 - return node; - } + [class]{AVLTree}-[func]{removeHelper} + + [class]{AVLTree}-[func]{getInOrderNext} ``` === "C++" @@ -1356,7 +1240,7 @@ AVL 树的独特之处在于「旋转 Rotation」的操作,其可 **在不影 updateHeight(node); // 更新结点高度 /* 2. 执行旋转操作,使该子树重新恢复平衡 */ node = rotate(node); - // 返回子树的根节点 + // 返回子树的根结点 return node; } ``` @@ -1412,7 +1296,7 @@ AVL 树的独特之处在于「旋转 Rotation」的操作,其可 **在不影 updateHeight(node) /* 2. 执行旋转操作,使该子树重新恢复平衡 */ node = rotate(node) - // 返回子树的根节点 + // 返回子树的根结点 return node } ``` @@ -1449,7 +1333,17 @@ AVL 树的独特之处在于「旋转 Rotation」的操作,其可 **在不影 this.updateHeight(node); // 更新结点高度 /* 2. 执行旋转操作,使该子树重新恢复平衡 */ node = this.rotate(node); - // 返回子树的根节点 + // 返回子树的根结点 + return node; + } + + /* 获取中序遍历中的下一个结点(仅适用于 root 有左子结点的情况) */ + getInOrderNext(node) { + if (node === null) return node; + // 循环访问左子结点,直到叶结点时为最小结点,跳出 + while (node.left !== null) { + node = node.left; + } return node; } @@ -1501,7 +1395,7 @@ AVL 树的独特之处在于「旋转 Rotation」的操作,其可 **在不影 this.updateHeight(node); // 更新结点高度 /* 2. 执行旋转操作,使该子树重新恢复平衡 */ node = this.rotate(node); - // 返回子树的根节点 + // 返回子树的根结点 return node; } @@ -1564,7 +1458,7 @@ AVL 树的独特之处在于「旋转 Rotation」的操作,其可 **在不影 updateHeight(node); // 更新结点高度 /* 2. 执行旋转操作,使该子树重新恢复平衡 */ node = rotate(node); - // 返回子树的根节点 + // 返回子树的根结点 return node; } ``` @@ -1611,7 +1505,7 @@ AVL 树的独特之处在于「旋转 Rotation」的操作,其可 **在不影 updateHeight(node: node) // 更新结点高度 /* 2. 执行旋转操作,使该子树重新恢复平衡 */ node = rotate(node: node) - // 返回子树的根节点 + // 返回子树的根结点 return node } ``` diff --git a/docs/chapter_tree/binary_search_tree.md b/docs/chapter_tree/binary_search_tree.md index 15e1052fb..25f605580 100755 --- a/docs/chapter_tree/binary_search_tree.md +++ b/docs/chapter_tree/binary_search_tree.md @@ -38,21 +38,7 @@ comments: true === "Java" ```java title="binary_search_tree.java" - /* 查找结点 */ - TreeNode search(int num) { - TreeNode cur = root; - // 循环查找,越过叶结点后跳出 - while (cur != null) { - // 目标结点在 cur 的右子树中 - if (cur.val < num) cur = cur.right; - // 目标结点在 cur 的左子树中 - else if (cur.val > num) cur = cur.left; - // 找到目标结点,跳出循环 - else break; - } - // 返回目标结点 - return cur; - } + [class]{BinarySearchTree}-[func]{search} ``` === "C++" @@ -220,27 +206,7 @@ comments: true === "Java" ```java title="binary_search_tree.java" - /* 插入结点 */ - TreeNode insert(int num) { - // 若树为空,直接提前返回 - if (root == null) return null; - TreeNode cur = root, pre = null; - // 循环查找,越过叶结点后跳出 - while (cur != null) { - // 找到重复结点,直接返回 - if (cur.val == num) return null; - pre = cur; - // 插入位置在 cur 的右子树中 - if (cur.val < num) cur = cur.right; - // 插入位置在 cur 的左子树中 - else cur = cur.left; - } - // 插入结点 val - TreeNode node = new TreeNode(num); - if (pre.val < num) pre.right = node; - else pre.left = node; - return node; - } + [class]{BinarySearchTree}-[func]{insert} ``` === "C++" @@ -491,55 +457,9 @@ comments: true === "Java" ```java title="binary_search_tree.java" - /* 删除结点 */ - TreeNode remove(int num) { - // 若树为空,直接提前返回 - if (root == null) return null; - TreeNode cur = root, pre = null; - // 循环查找,越过叶结点后跳出 - while (cur != null) { - // 找到待删除结点,跳出循环 - if (cur.val == num) break; - pre = cur; - // 待删除结点在 cur 的右子树中 - if (cur.val < num) cur = cur.right; - // 待删除结点在 cur 的左子树中 - else cur = cur.left; - } - // 若无待删除结点,则直接返回 - if (cur == null) return null; - // 子结点数量 = 0 or 1 - if (cur.left == null || cur.right == null) { - // 当子结点数量 = 0 / 1 时, child = null / 该子结点 - TreeNode child = cur.left != null ? cur.left : cur.right; - // 删除结点 cur - if (pre.left == cur) pre.left = child; - else pre.right = child; - // 释放内存 - delete cur; - } - // 子结点数量 = 2 - else { - // 获取中序遍历中 cur 的下一个结点 - TreeNode nex = getInOrderNext(cur.right); - int tmp = nex.val; - // 递归删除结点 nex - remove(nex.val); - // 将 nex 的值复制给 cur - cur.val = tmp; - } - return cur; - } + [class]{BinarySearchTree}-[func]{remove} - /* 获取中序遍历中的下一个结点(仅适用于 root 有左子结点的情况) */ - public TreeNode getInOrderNext(TreeNode root) { - if (root == null) return root; - // 循环访问左子结点,直到叶结点时为最小结点,跳出 - while (root.left != null) { - root = root.left; - } - return root; - } + [class]{BinarySearchTree}-[func]{getInOrderNext} ``` === "C++" diff --git a/docs/chapter_tree/binary_tree.md b/docs/chapter_tree/binary_tree.md index 2e876d539..c82750b45 100644 --- a/docs/chapter_tree/binary_tree.md +++ b/docs/chapter_tree/binary_tree.md @@ -197,7 +197,7 @@ comments: true ```python title="binary_tree.py" """ 初始化二叉树 """ - # 初始化节点 + # 初始化结点 n1 = TreeNode(val=1) n2 = TreeNode(val=2) n3 = TreeNode(val=3) @@ -343,7 +343,7 @@ comments: true # 在 n1 -> n2 中间插入结点 P n1.left = p p.left = n2 - # 删除节点 P + # 删除结点 P n1.left = n2 ``` diff --git a/docs/chapter_tree/binary_tree_traversal.md b/docs/chapter_tree/binary_tree_traversal.md index 7714b3904..895d4852a 100755 --- a/docs/chapter_tree/binary_tree_traversal.md +++ b/docs/chapter_tree/binary_tree_traversal.md @@ -21,22 +21,7 @@ comments: true === "Java" ```java title="binary_tree_bfs.java" - /* 层序遍历 */ - List hierOrder(TreeNode root) { - // 初始化队列,加入根结点 - Queue queue = new LinkedList<>() {{ add(root); }}; - // 初始化一个列表,用于保存遍历序列 - List list = new ArrayList<>(); - while (!queue.isEmpty()) { - TreeNode node = queue.poll(); // 队列出队 - list.add(node.val); // 保存结点值 - if (node.left != null) - queue.offer(node.left); // 左子结点入队 - if (node.right != null) - queue.offer(node.right); // 右子结点入队 - } - return list; - } + [class]{binary_tree_bfs}-[func]{hierOrder} ``` === "C++" @@ -52,7 +37,7 @@ comments: true while (!queue.empty()) { TreeNode* node = queue.front(); queue.pop(); // 队列出队 - vec.push_back(node->val); // 保存结点 + vec.push_back(node->val); // 保存结点值 if (node->left != nullptr) queue.push(node->left); // 左子结点入队 if (node->right != nullptr) @@ -81,7 +66,7 @@ comments: true for queue.Len() > 0 { // poll node := queue.Remove(queue.Front()).(*TreeNode) - // 保存结点 + // 保存结点值 nums = append(nums, node.Val) if node.Left != nil { // 左子结点入队 @@ -107,7 +92,7 @@ comments: true let list = []; while (queue.length) { let node = queue.shift(); // 队列出队 - list.push(node.val); // 保存结点 + list.push(node.val); // 保存结点值 if (node.left) queue.push(node.left); // 左子结点入队 if (node.right) @@ -128,7 +113,7 @@ comments: true const list: number[] = []; while (queue.length) { let node = queue.shift() as TreeNode; // 队列出队 - list.push(node.val); // 保存结点 + list.push(node.val); // 保存结点值 if (node.left) { queue.push(node.left); // 左子结点入队 } @@ -182,7 +167,7 @@ comments: true var list: [Int] = [] while !queue.isEmpty { let node = queue.removeFirst() // 队列出队 - list.append(node.val) // 保存结点 + list.append(node.val) // 保存结点值 if let left = node.left { queue.append(left) // 左子结点入队 } @@ -223,32 +208,11 @@ comments: true === "Java" ```java title="binary_tree_dfs.java" - /* 前序遍历 */ - void preOrder(TreeNode root) { - if (root == null) return; - // 访问优先级:根结点 -> 左子树 -> 右子树 - list.add(root.val); - preOrder(root.left); - preOrder(root.right); - } - - /* 中序遍历 */ - void inOrder(TreeNode root) { - if (root == null) return; - // 访问优先级:左子树 -> 根结点 -> 右子树 - inOrder(root.left); - list.add(root.val); - inOrder(root.right); - } - - /* 后序遍历 */ - void postOrder(TreeNode root) { - if (root == null) return; - // 访问优先级:左子树 -> 右子树 -> 根结点 - postOrder(root.left); - postOrder(root.right); - list.add(root.val); - } + [class]{binary_tree_dfs}-[func]{preOrder} + + [class]{binary_tree_dfs}-[func]{inOrder} + + [class]{binary_tree_dfs}-[func]{postOrder} ``` === "C++" diff --git a/docs/stylesheets/extra.css b/docs/stylesheets/extra.css index 4f153c794..7171f2ed1 100644 --- a/docs/stylesheets/extra.css +++ b/docs/stylesheets/extra.css @@ -67,4 +67,10 @@ body { --md-text-font-family: -apple-system,BlinkMacSystemFont,var(--md-text-font,_),Helvetica,Arial,sans-serif; --md-code-font-family: var(--md-code-font,_),SFMono-Regular,Consolas,Menlo,-apple-system,BlinkMacSystemFont,var(--md-text-font,_),monospace; -} \ No newline at end of file +} + +/* max height of code block */ +/* https://github.com/squidfunk/mkdocs-material/issues/3444 */ +.md-typeset pre > code { + max-height: 30rem; +} diff --git a/docs/utils/build_markdown.py b/docs/utils/build_markdown.py index 6b119b29e..41078af16 100755 --- a/docs/utils/build_markdown.py +++ b/docs/utils/build_markdown.py @@ -11,6 +11,8 @@ import re import glob import shutil from docs.utils.extract_code_python import ExtractCodeBlocksPython +from docs.utils.extract_code_java import ExtractCodeBlocksJava + def build_markdown(md_path): with open(md_path, "r") as f: @@ -19,6 +21,7 @@ def build_markdown(md_path): code_blocks_dict = {} file_pattern = re.compile(r'\s*```(\w+)\s+title="(.+)"') src_pattern = re.compile(r'\s*\[class\]\{(.*?)\}-\[func\]\{(.*?)\}') + for i in range(len(lines)): # Find the line target to the source codes src_match = src_pattern.match(lines[i]) @@ -28,48 +31,43 @@ def build_markdown(md_path): file_match = file_pattern.match(lines[j]) if file_match is not None: break - - # Get code blocks + # Get the coresponding language code extractor lang = file_match[1] file_name = file_match[2] + extractor = extractor_dict[lang] + # Get code blocks if file_name not in code_blocks_dict: - code_blocks_dict[file_name] = ExtractCodeBlocksPython( + code_blocks_dict[file_name] = extractor.extract( file_path=osp.dirname(md_path).replace("docs/", f"codes/{lang}/") + f"/{file_name}") header_line = i - class_label = src_match[1] + class_label = src_match[1] func_label = src_match[2] code_blocks = code_blocks_dict[file_name] - src_info = { - "line_number": i, - "class_label": src_match[1], - "func_label": src_match[2], - "code_blocks": code_blocks_dict[file_name] - } # Add the class to the doc if not func_label and class_label: - if class_label in code_blocks.classes: + if class_label in code_blocks["classes"]: lines.pop(header_line) - class_block = code_blocks.classes[class_label]["block"] + class_block = code_blocks["classes"][class_label]["block"] for code_line in class_block[::-1]: ind = " " * 4 if code_line != "\n" else "" lines.insert(header_line, ind + code_line) # Add the function to the doc elif func_label and not class_label: - if func_label in code_blocks.functions: + if func_label in code_blocks["funcs"]: lines.pop(header_line) - func_block = code_blocks.functions[func_label] + func_block = code_blocks["funcs"][func_label] for code_line in func_block["block"][::-1]: ind = " " * 4 if code_line != "\n" else "" lines.insert(header_line, ind + code_line) # Add the class method to the doc elif func_label and class_label: - if class_label in code_blocks.classes: - class_dict = code_blocks.classes[class_label] - if func_label in class_dict["functions"]: + if class_label in code_blocks["classes"]: + class_dict = code_blocks["classes"][class_label] + if func_label in class_dict["funcs"]: lines.pop(header_line) - func_block = class_dict["functions"][func_label] + func_block = class_dict["funcs"][func_label] for code_line in func_block["block"][::-1]: lines.insert(header_line, code_line) @@ -78,10 +76,17 @@ def build_markdown(md_path): print(f"Built {md_path}") +extractor_dict = { + "java": ExtractCodeBlocksJava(), + "python": ExtractCodeBlocksPython(), +} + + if __name__ == "__main__": # Copy files to the build dir shutil.copytree("docs", "build", dirs_exist_ok=True) shutil.rmtree("build/utils") + # Build docs - for md_path in glob.glob("docs/chapter_*/*.md"): + for md_path in glob.glob("docs/chapter_*/*.md"): build_markdown(md_path) diff --git a/docs/utils/extract_code_java.py b/docs/utils/extract_code_java.py new file mode 100644 index 000000000..46d0c85de --- /dev/null +++ b/docs/utils/extract_code_java.py @@ -0,0 +1,145 @@ +""" +File: extract_code_python.py +Created Time: 2023-02-07 +Author: Krahets (krahets@163.com) +""" + +import re +import os +import os.path as osp + +class ExtractCodeBlocksJava: + def __init__(self) -> None: + self.langs = ["java"] + # Pattern to match function names and class names + self.func_pattern = r'(\s+)(public|private|)\s*(static|)\s*(\S+)\s+(\w+)(\(.*\))\s+\{' + self.class_pattern = r'(public|)\s*class\s+(\w+)\s*\{' + # Pattern to match the start and end of a block + self.block_end_pattern = '^\s{ind}\}' + self.block_start_pattern = '^\s{ind}\/\*.+\*\/' + + def extract(self, file_path): + self.file_path = file_path + with open(file_path) as f: + self.lines = f.readlines() + self.content = "".join(self.lines) + # Detect and extract all the classes along with its fucntions + classes = self.extract_class_blocks() + # Remove 'static' + self.post_process(classes) + + return { + "classes": classes + } + + def post_process(self, classes): + for clas in classes.values(): + funcs = clas["funcs"] + for func in funcs.values(): + for i, line in enumerate(func["block"]): + if "static " in line: + func["block"][i] = line.replace("static ", "") + break + + + def search_block(self, header_line, indentation): + """ + Search class/function block given the header_line and indentation + """ + start_line, end_line = 0, len(self.lines) + + block_end_pattern = re.compile(self.block_end_pattern.replace("ind", str(indentation))) + block_start_pattern = re.compile(self.block_start_pattern.replace("ind", str(indentation))) + + # Search the code + for i in range(header_line + 1, len(self.lines)): + if re.match(block_end_pattern, self.lines[i]) is not None: + end_line = i + break + # Search the header comment + for i in range(header_line - 1, -1, -1): + if re.search(block_start_pattern, self.lines[i]) is not None: + start_line = i + break + code_block = self.lines[start_line:end_line + 1] + # Remove empty lines at bottom + for i in range(len(code_block) - 1, -1, -1): + if re.search("^\s*\n", code_block[i]) is None: + break + end_line -= 1 + + return start_line, end_line, self.lines[start_line:end_line + 1] + + + def extract_function_blocks(self, indentation=4, start_line=-1, end_line=-1): + """ + Extract all the functions with given indentation + """ + funcs = {} + + if start_line == -1: + start_line = 0 + if end_line == -1: + end_line = len(self.lines) - 1 + + func_pattern = re.compile(self.func_pattern) + + for line_num in range(start_line, end_line + 1): + # Search the function header + func_match = func_pattern.match(self.lines[line_num]) + if func_match is None: continue + # The function should match the input indentation + if len(func_match.group(1)) != indentation: continue + header_line = line_num + + # Search the block from the header line + start_line, end_line, func_block = self.search_block(header_line, indentation) + # Construct the funcs dict + func_label = func_match.group(5) + funcs[func_label] = { + "indentation": indentation, + "line_number": { + "start": start_line, + "end": end_line, + "header": header_line, + }, + "block": func_block, + } + + return funcs + + def extract_class_blocks(self): + """ + Extract all the classes with given indentation + """ + classes = {} + + class_pattern = re.compile(self.class_pattern) + + for line_num, line in enumerate(self.lines): + # Search the class header + class_match = class_pattern.match(line) + if class_match is None: continue + header_line = line_num + + # Search the block from the header line + start_line, end_line, class_block = self.search_block(header_line, 0) + # Construct the classes dict + class_label = class_match.group(2) + classes[class_label] = { + "indentation": 0, + "line_number": { + "start": start_line, + "end": end_line, + "header": header_line, + }, + "block": class_block, + "funcs": self.extract_function_blocks( + indentation=4, start_line=start_line, end_line=end_line) + } + + return classes + +# ext = ExtractCodeBlocksJava() +# ext.extract("codes/java/chapter_array_and_linkedlist/array.java") +# ext.extract("codes/java/chapter_array_and_linkedlist/my_list.java") diff --git a/docs/utils/extract_code_python.py b/docs/utils/extract_code_python.py index fb660bca7..db7eb2aa4 100755 --- a/docs/utils/extract_code_python.py +++ b/docs/utils/extract_code_python.py @@ -1,44 +1,55 @@ """ File: extract_code_python.py -Created Time: 2023-02-06 +Created Time: 2023-02-07 Author: Krahets (krahets@163.com) """ import re import os import os.path as osp -import glob class ExtractCodeBlocksPython: - def __init__(self, file_path) -> None: + def __init__(self) -> None: + self.langs = ["python"] + # Pattern to match function names and class names + self.func_pattern = r'(\s*)def\s+(\w+)\s*\(' + self.class_pattern = r'class\s+(\w+)' + # Pattern to match the start and end of a block + self.block_end_pattern = '^\s{0,ind}\S+.*\n' + self.block_start_pattern = '^\s{ind}""".+' + + def extract(self, file_path): self.file_path = file_path with open(file_path) as f: self.lines = f.readlines() self.content = "".join(self.lines) - - # Regular expression pattern to match function names and class names - self.func_pattern = re.compile(r'(\s*)def\s+(\w+)\s*\(') - self.class_pattern = re.compile(r'class\s+(\w+)') # Detect and extract all the classes and fucntions - self.classes = self.extract_class_blocks() - self.functions = self.extract_function_blocks() + classes = self.extract_class_blocks() + funcs = self.extract_function_blocks() + + return { + "classes": classes, + "funcs": funcs, + } def search_block(self, header_line, indentation): """ Search class/function block given the header_line and indentation """ start_line, end_line = 0, len(self.lines) + + block_end_pattern = re.compile(self.block_end_pattern.replace("ind", str(indentation))) + block_start_pattern = re.compile(self.block_start_pattern.replace("ind", str(indentation))) + # Search the code for i in range(header_line + 1, len(self.lines)): - if re.search("^\s*\n|^\s{ind}\s+.+\n".replace("ind", str(indentation)), - self.lines[i]) is None: + if re.match(block_end_pattern, self.lines[i]) is not None: end_line = i break # Search the header comment for i in range(header_line - 1, -1, -1): - if re.search('^\s{ind}""".+'.replace("ind", str(indentation)), - self.lines[i]) is not None: + if re.search(block_start_pattern, self.lines[i]) is not None: start_line = i break func_block = self.lines[start_line:end_line] @@ -55,16 +66,18 @@ class ExtractCodeBlocksPython: """ Extract all the functions with given indentation """ - functions = {} + funcs = {} if start_line == -1: start_line = 0 if end_line == -1: end_line = len(self.lines) - 1 - + + func_pattern = re.compile(self.func_pattern) + for line_num in range(start_line, end_line + 1): # Search the function header - func_match = self.func_pattern.match(self.lines[line_num]) + func_match = func_pattern.match(self.lines[line_num]) if func_match is None: continue # The function should match the input indentation if len(func_match.group(1)) != indentation: continue @@ -72,9 +85,9 @@ class ExtractCodeBlocksPython: # Search the block from the header line start_line, end_line, func_block = self.search_block(header_line, indentation) - # Construct the functions dict + # Construct the funcs dict func_label = func_match.group(2) - functions[func_label] = { + funcs[func_label] = { "indentation": indentation, "line_number": { "start": start_line, @@ -84,7 +97,7 @@ class ExtractCodeBlocksPython: "block": func_block, } - return functions + return funcs def extract_class_blocks(self): """ @@ -92,9 +105,11 @@ class ExtractCodeBlocksPython: """ classes = {} + class_pattern = re.compile(self.class_pattern) + for line_num, line in enumerate(self.lines): # Search the class header - class_match = self.class_pattern.match(line) + class_match = class_pattern.match(line) if class_match is None: continue header_line = line_num @@ -110,7 +125,7 @@ class ExtractCodeBlocksPython: "header": header_line, }, "block": class_block, - "functions": self.extract_function_blocks( + "funcs": self.extract_function_blocks( indentation=4, start_line=start_line, end_line=end_line) }