From 1ca5c731f7002b3bddaeb1f9db3b8177cfc905c2 Mon Sep 17 00:00:00 2001 From: krahets Date: Tue, 7 Feb 2023 17:17:14 +0800 Subject: [PATCH] build --- build/chapter_array_and_linkedlist/array.md | 3 +- .../linked_list.md | 2 +- build/chapter_array_and_linkedlist/list.md | 11 + .../space_complexity.md | 3 +- .../space_time_tradeoff.md | 2 + .../time_complexity.md | 58 ++-- build/chapter_graph/graph_operations.md | 45 ++- build/chapter_hashing/hash_map.md | 53 +++- build/chapter_heap/heap.md | 24 +- build/chapter_sorting/merge_sort.md | 48 ++- build/chapter_sorting/quick_sort.md | 17 +- build/chapter_stack_and_queue/deque.md | 43 ++- build/chapter_stack_and_queue/queue.md | 28 +- build/chapter_stack_and_queue/stack.md | 27 ++ build/chapter_tree/avl_tree.md | 291 ++++++++++++++---- build/chapter_tree/binary_search_tree.md | 4 +- build/chapter_tree/binary_tree.md | 4 +- build/chapter_tree/binary_tree_traversal.md | 22 +- build/stylesheets/extra.css | 8 +- 19 files changed, 501 insertions(+), 192 deletions(-) diff --git a/build/chapter_array_and_linkedlist/array.md b/build/chapter_array_and_linkedlist/array.md index fa4418ee8..c4f0d920d 100755 --- a/build/chapter_array_and_linkedlist/array.md +++ b/build/chapter_array_and_linkedlist/array.md @@ -122,6 +122,7 @@ elementAddr = firtstElementAddr + elementLength * elementIndex // 在区间 [0, nums.length) 中随机抽取一个数字 int randomIndex = ThreadLocalRandom.current(). nextInt(0, nums.length); + // 获取并返回随机元素 int randomNum = nums[randomIndex]; return randomNum; } @@ -417,7 +418,7 @@ elementAddr = firtstElementAddr + elementLength * elementIndex // 将 num 赋给 index 处元素 nums[index] = num; } - + /* 删除索引 index 处元素 */ void remove(int[] nums, int index) { // 把索引 index 之后的所有元素向前移动一位 diff --git a/build/chapter_array_and_linkedlist/linked_list.md b/build/chapter_array_and_linkedlist/linked_list.md index 0e17954a5..271b0dcc7 100755 --- a/build/chapter_array_and_linkedlist/linked_list.md +++ b/build/chapter_array_and_linkedlist/linked_list.md @@ -331,7 +331,7 @@ comments: true n0.next = P; P.next = n1; } - + /* 删除链表的结点 n0 之后的首个结点 */ void remove(ListNode n0) { if (n0.next == null) diff --git a/build/chapter_array_and_linkedlist/list.md b/build/chapter_array_and_linkedlist/list.md index 5887e6f3f..76c521435 100755 --- a/build/chapter_array_and_linkedlist/list.md +++ b/build/chapter_array_and_linkedlist/list.md @@ -801,6 +801,17 @@ comments: true // 更新列表容量 capacity = nums.length; } + + /* 将列表转换为数组 */ + public int[] toArray() { + int size = size(); + // 仅转换有效长度范围内的列表元素 + int[] nums = new int[size]; + for (int i = 0; i < size; i++) { + nums[i] = get(i); + } + return nums; + } } ``` diff --git a/build/chapter_computational_complexity/space_complexity.md b/build/chapter_computational_complexity/space_complexity.md index 61a217f6e..1d987ac6e 100755 --- a/build/chapter_computational_complexity/space_complexity.md +++ b/build/chapter_computational_complexity/space_complexity.md @@ -1094,7 +1094,7 @@ $$ /* 平方阶 */ void quadratic(int n) { // 矩阵占用 O(n^2) 空间 - int [][]numMatrix = new int[n][n]; + int[][] numMatrix = new int[n][n]; // 二维列表占用 O(n^2) 空间 List> numList = new ArrayList<>(); for (int i = 0; i < n; i++) { @@ -1253,6 +1253,7 @@ $$ 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/build/chapter_computational_complexity/space_time_tradeoff.md b/build/chapter_computational_complexity/space_time_tradeoff.md index 07eea2e1a..552b8d085 100755 --- a/build/chapter_computational_complexity/space_time_tradeoff.md +++ b/build/chapter_computational_complexity/space_time_tradeoff.md @@ -33,6 +33,7 @@ comments: true === "Java" ```java title="leetcode_two_sum.java" + /* 方法一:暴力枚举 */ class SolutionBruteForce { public int[] twoSum(int[] nums, int target) { int size = nums.length; @@ -207,6 +208,7 @@ comments: true === "Java" ```java title="leetcode_two_sum.java" + /* 方法二:辅助哈希表 */ class SolutionHashMap { public int[] twoSum(int[] nums, int target) { int size = nums.length; diff --git a/build/chapter_computational_complexity/time_complexity.md b/build/chapter_computational_complexity/time_complexity.md index dd8df29b2..e2883be48 100755 --- a/build/chapter_computational_complexity/time_complexity.md +++ b/build/chapter_computational_complexity/time_complexity.md @@ -2193,7 +2193,7 @@ $$ /* 线性对数阶 */ int linearLogRecur(float n) { if (n <= 1) return 1; - int count = linearLogRecur(n / 2) + + int count = linearLogRecur(n / 2) + linearLogRecur(n / 2); for (int i = 0; i < n; i++) { count++; @@ -2524,34 +2524,32 @@ $$ === "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; + /* 生成一个数组,元素为 { 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; + } - /* 查找数组 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; + /* 查找数组 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; } ``` @@ -2640,7 +2638,7 @@ $$ ```js title="worst_best_time_complexity.js" /* 生成一个数组,元素为 { 1, 2, ..., n },顺序被打乱 */ function randomNumbers(n) { - let nums = Array(n); + const nums = Array(n); // 生成数组 nums = { 1, 2, 3, ..., n } for (let i = 0; i < n; i++) { nums[i] = i + 1; @@ -2673,15 +2671,15 @@ $$ ```typescript title="worst_best_time_complexity.ts" /* 生成一个数组,元素为 { 1, 2, ..., n },顺序被打乱 */ function randomNumbers(n: number): number[] { - let nums = Array(n); + const nums = Array(n); // 生成数组 nums = { 1, 2, 3, ..., n } for (let i = 0; i < n; i++) { nums[i] = i + 1; } // 随机打乱数组元素 for (let i = 0; i < n; i++) { - let r = Math.floor(Math.random() * (i + 1)); - let temp = nums[i]; + const r = Math.floor(Math.random() * (i + 1)); + const temp = nums[i]; nums[i] = nums[r]; nums[r] = temp; } diff --git a/build/chapter_graph/graph_operations.md b/build/chapter_graph/graph_operations.md index 4b86d4d39..6800193e0 100644 --- a/build/chapter_graph/graph_operations.md +++ b/build/chapter_graph/graph_operations.md @@ -39,7 +39,7 @@ comments: true class GraphAdjMat { List vertices; // 顶点列表,元素代表“顶点值”,索引代表“顶点索引” List> adjMat; // 邻接矩阵,行列索引对应“顶点索引” - + /* 构造函数 */ public GraphAdjMat(int[] vertices, int[][] edges) { this.vertices = new ArrayList<>(); @@ -54,12 +54,12 @@ comments: true addEdge(e[0], e[1]); } } - + /* 获取顶点数量 */ public int size() { return vertices.size(); } - + /* 添加顶点 */ public void addVertex(int val) { int n = size(); @@ -76,7 +76,7 @@ comments: true row.add(0); } } - + /* 删除顶点 */ public void removeVertex(int index) { if (index >= size()) @@ -90,7 +90,7 @@ comments: true row.remove(index); } } - + /* 添加边 */ // 参数 i, j 对应 vertices 元素索引 public void addEdge(int i, int j) { @@ -101,7 +101,7 @@ comments: true adjMat.get(i).set(j, 1); adjMat.get(j).set(i, 1); } - + /* 删除边 */ // 参数 i, j 对应 vertices 元素索引 public void removeEdge(int i, int j) { @@ -111,6 +111,14 @@ comments: true adjMat.get(i).set(j, 0); adjMat.get(j).set(i, 0); } + + /* 打印邻接矩阵 */ + public void print() { + System.out.print("顶点列表 = "); + System.out.println(vertices); + System.out.println("邻接矩阵 ="); + PrintUtil.printMatrix(adjMat); + } } ``` @@ -364,12 +372,12 @@ comments: true this.val = val; } } - + /* 基于邻接表实现的无向图类 */ class GraphAdjList { // 请注意,vertices 和 adjList 中存储的都是 Vertex 对象 Map> adjList; // 邻接表(使用哈希表实现) - + /* 构造函数 */ public GraphAdjList(Vertex[][] edges) { this.adjList = new HashMap<>(); @@ -380,12 +388,12 @@ comments: true 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) @@ -394,7 +402,7 @@ comments: true 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) @@ -403,7 +411,7 @@ comments: true adjList.get(vet1).remove(vet2); adjList.get(vet2).remove(vet1); } - + /* 添加顶点 */ public void addVertex(Vertex vet) { if (adjList.containsKey(vet)) @@ -411,7 +419,7 @@ comments: true // 在邻接表中添加一个新链表(即 HashSet) adjList.put(vet, new HashSet<>()); } - + /* 删除顶点 */ public void removeVertex(Vertex vet) { if (!adjList.containsKey(vet)) @@ -423,6 +431,17 @@ comments: true set.remove(vet); } } + + /* 打印邻接表 */ + public void print() { + System.out.println("邻接表 ="); + for (Map.Entry> entry : adjList.entrySet()) { + List tmp = new ArrayList<>(); + for (Vertex vertex : entry.getValue()) + tmp.add(vertex.val); + System.out.println(entry.getKey().val + ": " + tmp + ","); + } + } } ``` diff --git a/build/chapter_hashing/hash_map.md b/build/chapter_hashing/hash_map.md index 40913ec14..4943b4440 100755 --- a/build/chapter_hashing/hash_map.md +++ b/build/chapter_hashing/hash_map.md @@ -418,14 +418,14 @@ $$ ```java title="array_hash_map.java" /* 键值对 int->String */ class Entry { - public int key; // 键 - public String val; // 值 + public int key; + public String val; public Entry(int key, String val) { this.key = key; this.val = val; } } - + /* 基于数组简易实现的哈希表 */ class ArrayHashMap { private List bucket; @@ -436,13 +436,13 @@ $$ bucket.add(null); } } - + /* 哈希函数 */ private int hashFunc(int key) { int index = key % 100; return index; } - + /* 查询操作 */ public String get(int key) { int index = hashFunc(key); @@ -450,20 +450,57 @@ $$ 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,代表删除 + // 置为 null ,代表删除 bucket.set(index, null); } + + /* 获取所有键值对 */ + public List entrySet() { + List entrySet = new ArrayList<>(); + for (Entry pair : bucket) { + if (pair != null) + entrySet.add(pair); + } + return entrySet; + } + + /* 获取所有键 */ + public List keySet() { + List keySet = new ArrayList<>(); + for (Entry pair : bucket) { + if (pair != null) + keySet.add(pair.key); + } + return keySet; + } + + /* 获取所有值 */ + public List valueSet() { + List valueSet = new ArrayList<>(); + for (Entry pair : bucket) { + if (pair != null) + valueSet.add(pair.val); + } + return valueSet; + } + + /* 打印哈希表 */ + public void print() { + for (Entry kv: entrySet()) { + System.out.println(kv.key + " -> " + kv.val); + } + } } ``` diff --git a/build/chapter_heap/heap.md b/build/chapter_heap/heap.md index 79c1ded80..efbac2365 100644 --- a/build/chapter_heap/heap.md +++ b/build/chapter_heap/heap.md @@ -260,24 +260,16 @@ comments: true === "Java" ```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; // 向下整除 @@ -408,7 +400,7 @@ comments: true ```java title="my_heap.java" /* 访问堆顶元素 */ - public int peek() { + int peek() { return maxHeap.get(0); } ``` @@ -512,13 +504,13 @@ comments: true // 从底至顶堆化 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; // 交换两结点 @@ -708,7 +700,7 @@ comments: true // 返回堆顶元素 return val; } - + /* 从结点 i 开始,从顶至底堆化 */ void siftDown(int i) { while (true) { @@ -718,7 +710,7 @@ comments: true ma = l; if (r < size() && maxHeap.get(r) > maxHeap.get(ma)) ma = r; - // 若“结点 i 最大”或“越过叶结点”,则结束堆化 + // 若结点 i 最大或索引 l, r 越界,则无需继续堆化,跳出 if (ma == i) break; // 交换两结点 swap(i, ma); @@ -902,7 +894,7 @@ comments: true ```java title="my_heap.java" /* 构造函数,根据输入列表建堆 */ - public MaxHeap(List nums) { + MaxHeap(List nums) { // 将列表元素原封不动添加进堆 maxHeap = new ArrayList<>(nums); // 堆化除叶结点以外的其他所有结点 diff --git a/build/chapter_sorting/merge_sort.md b/build/chapter_sorting/merge_sort.md index cf2854917..16ea46563 100755 --- a/build/chapter_sorting/merge_sort.md +++ b/build/chapter_sorting/merge_sort.md @@ -62,11 +62,9 @@ comments: true === "Java" ```java title="merge_sort.java" - /** - * 合并左子数组和右子数组 - * 左子数组区间 [left, mid] - * 右子数组区间 [mid + 1, right] - */ + /* 合并左子数组和右子数组 */ + // 左子数组区间 [left, mid] + // 右子数组区间 [mid + 1, right] void merge(int[] nums, int left, int mid, int right) { // 初始化辅助数组 int[] tmp = Arrays.copyOfRange(nums, left, right + 1); @@ -89,16 +87,16 @@ comments: true nums[k] = tmp[j++]; } } - + /* 归并排序 */ void mergeSort(int[] nums, int left, int right) { // 终止条件 if (left >= right) return; // 当子数组长度为 1 时终止递归 - // 递归划分 - int mid = (left + right) / 2; // 计算数组中点 + // 划分阶段 + int mid = (left + right) / 2; // 计算中点 mergeSort(nums, left, mid); // 递归左子数组 mergeSort(nums, mid + 1, right); // 递归右子数组 - // 回溯合并 + // 合并阶段 merge(nums, left, mid, right); } ``` @@ -106,11 +104,9 @@ comments: true === "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); @@ -245,11 +241,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); @@ -290,11 +284,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); @@ -341,11 +333,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/build/chapter_sorting/quick_sort.md b/build/chapter_sorting/quick_sort.md index 7ef7cd9c1..1c4ab2a34 100755 --- a/build/chapter_sorting/quick_sort.md +++ b/build/chapter_sorting/quick_sort.md @@ -45,14 +45,14 @@ comments: true === "Java" - ``` java title="quick_sort.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] 作为基准数 @@ -468,7 +468,7 @@ comments: true else return right; } - + /* 哨兵划分(三数取中值) */ int partition(int[] nums, int left, int right) { // 选取三个候选元素的中位数 @@ -476,7 +476,16 @@ comments: true // 将中位数交换至数组最左端 swap(nums, left, med); // 以 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; // 返回基准数的索引 } ``` diff --git a/build/chapter_stack_and_queue/deque.md b/build/chapter_stack_and_queue/deque.md index 2ed4c866f..b49f3b20d 100644 --- a/build/chapter_stack_and_queue/deque.md +++ b/build/chapter_stack_and_queue/deque.md @@ -331,26 +331,26 @@ comments: true prev = next = null; } } - + /* 基于双向链表实现的双向队列 */ class LinkedListDeque { - private ListNode front, rear; // 头结点 front ,尾结点 rear - private int size = 0; // 双向队列的长度 - + 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); @@ -372,17 +372,17 @@ comments: true } size++; // 更新队列长度 } - + /* 队首入队 */ public void pushFirst(int num) { push(num, true); } - + /* 队尾入队 */ public void pushLast(int num) { push(num, false); } - + /* 出队操作 */ private Integer poll(boolean isFront) { // 若队列为空,直接返回 null @@ -413,26 +413,41 @@ comments: true 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; } + + /* 打印双向队列 */ + public void print() { + if (isEmpty()) { + System.out.println("[ ]"); + return; + } + List list = new ArrayList<>(); + ListNode head = front; + while (head != null) { + list.add(String.valueOf(head.val)); + head = head.next; + } + System.out.println("[" + String.join(", ", list) + "]"); + } } ``` diff --git a/build/chapter_stack_and_queue/queue.md b/build/chapter_stack_and_queue/queue.md index 88de0a0bf..c3a58d284 100755 --- a/build/chapter_stack_and_queue/queue.md +++ b/build/chapter_stack_and_queue/queue.md @@ -288,19 +288,22 @@ comments: true 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 @@ -316,6 +319,7 @@ comments: true } queSize++; } + /* 出队 */ public int poll() { int num = peek(); @@ -324,12 +328,24 @@ comments: true queSize--; return num; } + /* 访问队首元素 */ public int peek() { if (size() == 0) throw new EmptyStackException(); return front.val; } + + /* 将链表转化为 Array 并返回 */ + public int[] toArray() { + ListNode node = front; + int[] res = new int[size()]; + for (int i = 0; i < res.length; i++) { + res[i] = node.val; + node = node.next; + } + return res; + } } ``` @@ -815,6 +831,16 @@ comments: true throw new EmptyStackException(); return nums[front]; } + + /* 返回数组 */ + public int[] toArray() { + // 仅转换有效长度范围内的列表元素 + int[] res = new int[queSize]; + for (int i = 0, j = front; i < queSize; i++, j++) { + res[i] = nums[j % capacity()]; + } + return res; + } } ``` diff --git a/build/chapter_stack_and_queue/stack.md b/build/chapter_stack_and_queue/stack.md index 3eda1a4df..894c03552 100755 --- a/build/chapter_stack_and_queue/stack.md +++ b/build/chapter_stack_and_queue/stack.md @@ -291,17 +291,21 @@ comments: true 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); @@ -309,6 +313,7 @@ comments: true stackPeek = node; stkSize++; } + /* 出栈 */ public int pop() { int num = peek(); @@ -316,12 +321,24 @@ comments: true stkSize--; return num; } + /* 访问栈顶元素 */ public int peek() { if (size() == 0) throw new EmptyStackException(); return stackPeek.val; } + + /* 将 List 转化为 Array 并返回 */ + public int[] toArray() { + ListNode node = stackPeek; + int[] res = new int[size()]; + for (int i = res.length - 1; i >= 0; i--) { + res[i] = node.val; + node = node.next; + } + return res; + } } ``` @@ -730,30 +747,40 @@ comments: true // 初始化列表(动态数组) 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); } + + /* 将 List 转化为 Array 并返回 */ + public Object[] toArray() { + return stack.toArray(); + } } ``` diff --git a/build/chapter_tree/avl_tree.md b/build/chapter_tree/avl_tree.md index b1b2adb52..0d4a36fea 100755 --- a/build/chapter_tree/avl_tree.md +++ b/build/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,36 +79,47 @@ G. M. Adelson-Velsky 和 E. M. Landis 在其 1962 年发表的论文 "An algorit === "JavaScript" - ```js title="avl_tree.js" + ```js title="" class TreeNode { val; // 结点值 + height; //结点高度 left; // 左子结点指针 right; // 右子结点指针 - height; //结点高度 constructor(val, left, right, height) { this.val = val === undefined ? 0 : val; + this.height = height === undefined ? 0 : height; this.left = left === undefined ? null : left; this.right = right === undefined ? null : right; - this.height = height === undefined ? 0 : height; } } ``` === "TypeScript" - ```typescript title="avl_tree.ts" - + ```typescript title="" + class TreeNode { + val: number; // 结点值 + height: number; // 结点高度 + left: TreeNode | null; // 左子结点指针 + right: TreeNode | null; // 右子结点指针 + constructor(val?: number, height?: number, left?: TreeNode | null, right?: TreeNode | null) { + this.val = val === undefined ? 0 : val; + this.height = height === undefined ? 0 : height; + this.left = left === undefined ? null : left; + this.right = right === undefined ? null : right; + } + } ``` === "C" - ```c title="avl_tree.c" + ```c title="" ``` === "C#" - ```csharp title="avl_tree.cs" + ```csharp title="" /* AVL 树结点类 */ class TreeNode { public int val; // 结点值 @@ -121,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 // 结点值 @@ -138,7 +149,7 @@ G. M. Adelson-Velsky 和 E. M. Landis 在其 1962 年发表的论文 "An algorit === "Zig" - ```zig title="avl_tree.zig" + ```zig title="" ``` @@ -236,7 +247,17 @@ G. M. Adelson-Velsky 和 E. M. Landis 在其 1962 年发表的论文 "An algorit === "TypeScript" ```typescript title="avl_tree.ts" + /* 获取结点高度 */ + height(node: TreeNode): number { + // 空结点高度为 -1 ,叶结点高度为 0 + return node === null ? -1 : node.height; + } + /* 更新结点高度 */ + updateHeight(node: TreeNode): void { + // 结点高度等于最高子树高度 + 1 + node.height = Math.max(this.height(node.left), this.height(node.right)) + 1; + } ``` === "C" @@ -292,8 +313,8 @@ G. M. Adelson-Velsky 和 E. M. Landis 在其 1962 年发表的论文 "An algorit === "Java" ```java title="avl_tree.java" - /* 获取结点平衡因子 */ - public int balanceFactor(TreeNode node) { + /* 获取平衡因子 */ + int balanceFactor(TreeNode node) { // 空结点平衡因子为 0 if (node == null) return 0; // 结点平衡因子 = 左子树高度 - 右子树高度 @@ -354,7 +375,13 @@ G. M. Adelson-Velsky 和 E. M. Landis 在其 1962 年发表的论文 "An algorit === "TypeScript" ```typescript title="avl_tree.ts" - + /* 获取平衡因子 */ + balanceFactor(node: TreeNode): number { + // 空结点平衡因子为 0 + if (node === null) return 0; + // 结点平衡因子 = 左子树高度 - 右子树高度 + return this.height(node.left) - this.height(node.right); + } ``` === "C" @@ -408,7 +435,7 @@ AVL 树的独特之处在于「旋转 Rotation」的操作,其可 **在不影 ### Case 1 - 右旋 -如下图所示(结点下方为「平衡因子」),从底至顶看,二叉树中首个失衡结点是 **结点 3**。我们聚焦在以该失衡结点为根结点的子树上,将该结点记为 `node` ,将其左子节点记为 `child` ,执行「右旋」操作。完成右旋后,该子树已经恢复平衡,并且仍然为二叉搜索树。 +如下图所示(结点下方为「平衡因子」),从底至顶看,二叉树中首个失衡结点是 **结点 3**。我们聚焦在以该失衡结点为根结点的子树上,将该结点记为 `node` ,将其左子结点记为 `child` ,执行「右旋」操作。完成右旋后,该子树已经恢复平衡,并且仍然为二叉搜索树。 === "Step 1" ![right_rotate_step1](avl_tree.assets/right_rotate_step1.png) @@ -441,7 +468,7 @@ AVL 树的独特之处在于「旋转 Rotation」的操作,其可 **在不影 // 更新结点高度 updateHeight(node); updateHeight(child); - // 返回旋转后子树的根节点 + // 返回旋转后子树的根结点 return child; } ``` @@ -459,7 +486,7 @@ AVL 树的独特之处在于「旋转 Rotation」的操作,其可 **在不影 // 更新结点高度 updateHeight(node); updateHeight(child); - // 返回旋转后子树的根节点 + // 返回旋转后子树的根结点 return child; } ``` @@ -477,7 +504,7 @@ AVL 树的独特之处在于「旋转 Rotation」的操作,其可 **在不影 # 更新结点高度 self.__update_height(node) self.__update_height(child) - # 返回旋转后子树的根节点 + # 返回旋转后子树的根结点 return child ``` @@ -494,7 +521,7 @@ AVL 树的独特之处在于「旋转 Rotation」的操作,其可 **在不影 // 更新结点高度 updateHeight(node) updateHeight(child) - // 返回旋转后子树的根节点 + // 返回旋转后子树的根结点 return child } ``` @@ -504,15 +531,15 @@ AVL 树的独特之处在于「旋转 Rotation」的操作,其可 **在不影 ```js title="avl_tree.js" /* 右旋操作 */ rightRotate(node) { - let child = node.left; - let grandChild = child.right; + const child = node.left; + const grandChild = child.right; // 以 child 为原点,将 node 向右旋转 child.right = node; node.left = grandChild; // 更新结点高度 this.updateHeight(node); this.updateHeight(child); - // 返回旋转后子树的根节点 + // 返回旋转后子树的根结点 return child; } ``` @@ -520,7 +547,19 @@ AVL 树的独特之处在于「旋转 Rotation」的操作,其可 **在不影 === "TypeScript" ```typescript title="avl_tree.ts" - + /* 右旋操作 */ + rightRotate(node: TreeNode): TreeNode { + const child = node.left; + const grandChild = child.right; + // 以 child 为原点,将 node 向右旋转 + child.right = node; + node.left = grandChild; + // 更新结点高度 + this.updateHeight(node); + this.updateHeight(child); + // 返回旋转后子树的根结点 + return child; + } ``` === "C" @@ -543,7 +582,7 @@ AVL 树的独特之处在于「旋转 Rotation」的操作,其可 **在不影 // 更新结点高度 updateHeight(node); updateHeight(child); - // 返回旋转后子树的根节点 + // 返回旋转后子树的根结点 return child; } ``` @@ -561,7 +600,7 @@ AVL 树的独特之处在于「旋转 Rotation」的操作,其可 **在不影 // 更新结点高度 updateHeight(node: node) updateHeight(node: child) - // 返回旋转后子树的根节点 + // 返回旋转后子树的根结点 return child } ``` @@ -588,7 +627,7 @@ AVL 树的独特之处在于「旋转 Rotation」的操作,其可 **在不影 ```java title="avl_tree.java" /* 左旋操作 */ - private TreeNode leftRotate(TreeNode node) { + TreeNode leftRotate(TreeNode node) { TreeNode child = node.right; TreeNode grandChild = child.left; // 以 child 为原点,将 node 向左旋转 @@ -597,7 +636,7 @@ AVL 树的独特之处在于「旋转 Rotation」的操作,其可 **在不影 // 更新结点高度 updateHeight(node); updateHeight(child); - // 返回旋转后子树的根节点 + // 返回旋转后子树的根结点 return child; } ``` @@ -615,7 +654,7 @@ AVL 树的独特之处在于「旋转 Rotation」的操作,其可 **在不影 // 更新结点高度 updateHeight(node); updateHeight(child); - // 返回旋转后子树的根节点 + // 返回旋转后子树的根结点 return child; } ``` @@ -633,7 +672,7 @@ AVL 树的独特之处在于「旋转 Rotation」的操作,其可 **在不影 # 更新结点高度 self.__update_height(node) self.__update_height(child) - # 返回旋转后子树的根节点 + # 返回旋转后子树的根结点 return child ``` @@ -650,7 +689,7 @@ AVL 树的独特之处在于「旋转 Rotation」的操作,其可 **在不影 // 更新结点高度 updateHeight(node) updateHeight(child) - // 返回旋转后子树的根节点 + // 返回旋转后子树的根结点 return child } ``` @@ -660,15 +699,15 @@ AVL 树的独特之处在于「旋转 Rotation」的操作,其可 **在不影 ```js title="avl_tree.js" /* 左旋操作 */ leftRotate(node) { - let child = node.right; - let grandChild = child.left; + const child = node.right; + const grandChild = child.left; // 以 child 为原点,将 node 向左旋转 child.left = node; node.right = grandChild; // 更新结点高度 this.updateHeight(node); this.updateHeight(child); - // 返回旋转后子树的根节点 + // 返回旋转后子树的根结点 return child; } ``` @@ -676,7 +715,19 @@ AVL 树的独特之处在于「旋转 Rotation」的操作,其可 **在不影 === "TypeScript" ```typescript title="avl_tree.ts" - + /* 左旋操作 */ + leftRotate(node: TreeNode): TreeNode { + const child = node.right; + const grandChild = child.left; + // 以 child 为原点,将 node 向左旋转 + child.left = node; + node.right = grandChild; + // 更新结点高度 + this.updateHeight(node); + this.updateHeight(child); + // 返回旋转后子树的根结点 + return child; + } ``` === "C" @@ -701,7 +752,7 @@ AVL 树的独特之处在于「旋转 Rotation」的操作,其可 **在不影 // 更新结点高度 updateHeight(node); updateHeight(child); - // 返回旋转后子树的根节点 + // 返回旋转后子树的根结点 return child; } ``` @@ -719,7 +770,7 @@ AVL 树的独特之处在于「旋转 Rotation」的操作,其可 **在不影 // 更新结点高度 updateHeight(node: node) updateHeight(node: child) - // 返回旋转后子树的根节点 + // 返回旋转后子树的根结点 return child } @@ -902,7 +953,7 @@ AVL 树的独特之处在于「旋转 Rotation」的操作,其可 **在不影 /* 执行旋转操作,使该子树重新恢复平衡 */ rotate(node) { // 获取结点 node 的平衡因子 - let balanceFactor = this.balanceFactor(node); + const balanceFactor = this.balanceFactor(node); // 左偏树 if (balanceFactor > 1) { if (this.balanceFactor(node.left) >= 0) { @@ -933,7 +984,35 @@ AVL 树的独特之处在于「旋转 Rotation」的操作,其可 **在不影 === "TypeScript" ```typescript title="avl_tree.ts" - + /* 执行旋转操作,使该子树重新恢复平衡 */ + rotate(node: TreeNode): TreeNode { + // 获取结点 node 的平衡因子 + const balanceFactor = this.balanceFactor(node); + // 左偏树 + if (balanceFactor > 1) { + if (this.balanceFactor(node.left) >= 0) { + // 右旋 + return this.rightRotate(node); + } else { + // 先左旋后右旋 + node.left = this.leftRotate(node.left); + return this.rightRotate(node); + } + } + // 右偏树 + if (balanceFactor < -1) { + if (this.balanceFactor(node.right) <= 0) { + // 左旋 + return this.leftRotate(node); + } else { + // 先右旋后左旋 + node.right = this.rightRotate(node.right); + return this.leftRotate(node); + } + } + // 平衡树,无需旋转,直接返回 + return node; + } ``` === "C" @@ -1049,11 +1128,11 @@ AVL 树的独特之处在于「旋转 Rotation」的操作,其可 **在不影 else if (val > node.val) node.right = insertHelper(node.right, val); else - return node; // 重复结点不插入,直接返回 - updateHeight(node); // 更新结点高度 + return node; // 重复结点不插入,直接返回 + updateHeight(node); // 更新结点高度 /* 2. 执行旋转操作,使该子树重新恢复平衡 */ node = rotate(node); - // 返回子树的根节点 + // 返回子树的根结点 return node; } ``` @@ -1080,7 +1159,7 @@ AVL 树的独特之处在于「旋转 Rotation」的操作,其可 **在不影 updateHeight(node); // 更新结点高度 /* 2. 执行旋转操作,使该子树重新恢复平衡 */ node = rotate(node); - // 返回子树的根节点 + // 返回子树的根结点 return node; } ``` @@ -1137,7 +1216,7 @@ AVL 树的独特之处在于「旋转 Rotation」的操作,其可 **在不影 updateHeight(node) /* 2. 执行旋转操作,使该子树重新恢复平衡 */ node = rotate(node) - // 返回子树的根节点 + // 返回子树的根结点 return node } ``` @@ -1161,7 +1240,7 @@ AVL 树的独特之处在于「旋转 Rotation」的操作,其可 **在不影 this.updateHeight(node); // 更新结点高度 /* 2. 执行旋转操作,使该子树重新恢复平衡 */ node = this.rotate(node); - // 返回子树的根节点 + // 返回子树的根结点 return node; } ``` @@ -1169,7 +1248,29 @@ AVL 树的独特之处在于「旋转 Rotation」的操作,其可 **在不影 === "TypeScript" ```typescript title="avl_tree.ts" + /* 插入结点 */ + insert(val: number): TreeNode { + this.root = this.insertHelper(this.root, val); + return this.root; + } + /* 递归插入结点(辅助函数) */ + insertHelper(node: TreeNode, val: number): TreeNode { + 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 { + return node; // 重复结点不插入,直接返回 + } + this.updateHeight(node); // 更新结点高度 + /* 2. 执行旋转操作,使该子树重新恢复平衡 */ + node = this.rotate(node); + // 返回子树的根结点 + return node; + } ``` === "C" @@ -1204,7 +1305,7 @@ AVL 树的独特之处在于「旋转 Rotation」的操作,其可 **在不影 updateHeight(node); // 更新结点高度 /* 2. 执行旋转操作,使该子树重新恢复平衡 */ node = rotate(node); - // 返回子树的根节点 + // 返回子树的根结点 return node; } ``` @@ -1236,7 +1337,7 @@ AVL 树的独特之处在于「旋转 Rotation」的操作,其可 **在不影 updateHeight(node: node) // 更新结点高度 /* 2. 执行旋转操作,使该子树重新恢复平衡 */ node = rotate(node: node) - // 返回子树的根节点 + // 返回子树的根结点 return node } ``` @@ -1284,10 +1385,20 @@ AVL 树的独特之处在于「旋转 Rotation」的操作,其可 **在不影 node.val = temp.val; } } - updateHeight(node); // 更新结点高度 + updateHeight(node); // 更新结点高度 /* 2. 执行旋转操作,使该子树重新恢复平衡 */ node = rotate(node); - // 返回子树的根节点 + // 返回子树的根结点 + return node; + } + + /* 获取中序遍历中的下一个结点(仅适用于 root 有左子结点的情况) */ + TreeNode getInOrderNext(TreeNode node) { + if (node == null) return node; + // 循环访问左子结点,直到叶结点时为最小结点,跳出 + while (node.left != null) { + node = node.left; + } return node; } ``` @@ -1332,7 +1443,7 @@ AVL 树的独特之处在于「旋转 Rotation」的操作,其可 **在不影 updateHeight(node); // 更新结点高度 /* 2. 执行旋转操作,使该子树重新恢复平衡 */ node = rotate(node); - // 返回子树的根节点 + // 返回子树的根结点 return node; } ``` @@ -1416,7 +1527,7 @@ AVL 树的独特之处在于「旋转 Rotation」的操作,其可 **在不影 updateHeight(node) /* 2. 执行旋转操作,使该子树重新恢复平衡 */ node = rotate(node) - // 返回子树的根节点 + // 返回子树的根结点 return node } ``` @@ -1438,14 +1549,14 @@ AVL 树的独特之处在于「旋转 Rotation」的操作,其可 **在不影 else if (val > node.val) node.right = this.removeHelper(node.right, val); else { if (node.left === null || node.right === null) { - let child = node.left !== null ? node.left : node.right; + const child = node.left !== null ? node.left : node.right; // 子结点数量 = 0 ,直接删除 node 并返回 if (child === null) return null; // 子结点数量 = 1 ,直接删除 node else node = child; } else { // 子结点数量 = 2 ,则将中序遍历的下个结点删除,并用该结点替换当前结点 - let temp = this.getInOrderNext(node.right); + const temp = this.getInOrderNext(node.right); node.right = this.removeHelper(node.right, temp.val); node.val = temp.val; } @@ -1453,7 +1564,27 @@ 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; + } + + /* 获取中序遍历中的下一个结点(仅适用于 root 有左子结点的情况) */ + getInOrderNext(node) { + if (node === null) return node; + // 循环访问左子结点,直到叶结点时为最小结点,跳出 + while (node.left !== null) { + node = node.left; + } return node; } ``` @@ -1461,7 +1592,53 @@ AVL 树的独特之处在于「旋转 Rotation」的操作,其可 **在不影 === "TypeScript" ```typescript title="avl_tree.ts" + /* 删除结点 */ + remove(val: number): TreeNode { + this.root = this.removeHelper(this.root, val); + return this.root; + } + /* 递归删除结点(辅助函数) */ + removeHelper(node: TreeNode, val: number): TreeNode { + 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 (node.left === null || node.right === null) { + const child = node.left !== null ? node.left : node.right; + // 子结点数量 = 0 ,直接删除 node 并返回 + if (child === null) { + return null; + } else { + // 子结点数量 = 1 ,直接删除 node + node = child; + } + } else { + // 子结点数量 = 2 ,则将中序遍历的下个结点删除,并用该结点替换当前结点 + const temp = this.getInOrderNext(node.right); + node.right = this.removeHelper(node.right, temp.val); + node.val = temp.val; + } + } + this.updateHeight(node); // 更新结点高度 + /* 2. 执行旋转操作,使该子树重新恢复平衡 */ + node = this.rotate(node); + // 返回子树的根结点 + return node; + } + + /* 获取中序遍历中的下一个结点(仅适用于 root 有左子结点的情况) */ + getInOrderNext(node: TreeNode): TreeNode { + if (node === null) return node; + // 循环访问左子结点,直到叶结点时为最小结点,跳出 + while (node.left !== null) { + node = node.left; + } + return node; + } ``` === "C" @@ -1512,7 +1689,7 @@ AVL 树的独特之处在于「旋转 Rotation」的操作,其可 **在不影 updateHeight(node); // 更新结点高度 /* 2. 执行旋转操作,使该子树重新恢复平衡 */ node = rotate(node); - // 返回子树的根节点 + // 返回子树的根结点 return node; } ``` @@ -1559,7 +1736,7 @@ AVL 树的独特之处在于「旋转 Rotation」的操作,其可 **在不影 updateHeight(node: node) // 更新结点高度 /* 2. 执行旋转操作,使该子树重新恢复平衡 */ node = rotate(node: node) - // 返回子树的根节点 + // 返回子树的根结点 return node } ``` diff --git a/build/chapter_tree/binary_search_tree.md b/build/chapter_tree/binary_search_tree.md index df69cecc2..11d70a0d2 100755 --- a/build/chapter_tree/binary_search_tree.md +++ b/build/chapter_tree/binary_search_tree.md @@ -556,8 +556,6 @@ comments: true // 删除结点 cur if (pre.left == cur) pre.left = child; else pre.right = child; - // 释放内存 - delete cur; } // 子结点数量 = 2 else { @@ -573,7 +571,7 @@ comments: true } /* 获取中序遍历中的下一个结点(仅适用于 root 有左子结点的情况) */ - public TreeNode getInOrderNext(TreeNode root) { + TreeNode getInOrderNext(TreeNode root) { if (root == null) return root; // 循环访问左子结点,直到叶结点时为最小结点,跳出 while (root.left != null) { diff --git a/build/chapter_tree/binary_tree.md b/build/chapter_tree/binary_tree.md index 2e876d539..c82750b45 100644 --- a/build/chapter_tree/binary_tree.md +++ b/build/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/build/chapter_tree/binary_tree_traversal.md b/build/chapter_tree/binary_tree_traversal.md index 197cb0bb5..eb19b9451 100755 --- a/build/chapter_tree/binary_tree_traversal.md +++ b/build/chapter_tree/binary_tree_traversal.md @@ -52,7 +52,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) @@ -74,7 +74,7 @@ comments: true 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: @@ -95,7 +95,7 @@ comments: true for queue.Len() > 0 { // poll node := queue.Remove(queue.Front()).(*TreeNode) - // 保存结点 + // 保存结点值 nums = append(nums, node.Val) if node.Left != nil { // 左子结点入队 @@ -120,12 +120,12 @@ comments: true // 初始化一个列表,用于保存遍历序列 let list = []; while (queue.length) { - let node = queue.shift(); // 队列出队 - list.push(node.val); // 保存结点 + let node = queue.shift(); // 队列出队 + list.push(node.val); // 保存结点值 if (node.left) - queue.push(node.left); // 左子结点入队 + queue.push(node.left); // 左子结点入队 if (node.right) - queue.push(node.right); // 右子结点入队 + queue.push(node.right); // 右子结点入队 } return list; } @@ -142,7 +142,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); // 左子结点入队 } @@ -196,7 +196,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) // 左子结点入队 } @@ -245,7 +245,7 @@ comments: true preOrder(root.left); preOrder(root.right); } - + /* 中序遍历 */ void inOrder(TreeNode root) { if (root == null) return; @@ -254,7 +254,7 @@ comments: true list.add(root.val); inOrder(root.right); } - + /* 后序遍历 */ void postOrder(TreeNode root) { if (root == null) return; diff --git a/build/stylesheets/extra.css b/build/stylesheets/extra.css index 4f153c794..7171f2ed1 100644 --- a/build/stylesheets/extra.css +++ b/build/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; +}