diff --git a/codes/c/chapter_array_and_linkedlist/linked_list.c b/codes/c/chapter_array_and_linkedlist/linked_list.c index c414e1b6..17f0a752 100644 --- a/codes/c/chapter_array_and_linkedlist/linked_list.c +++ b/codes/c/chapter_array_and_linkedlist/linked_list.c @@ -6,14 +6,14 @@ #include "../include/include.h" -/* 在链表的结点 n0 之后插入结点 P */ +/* 在链表的节点 n0 之后插入节点 P */ void insert(ListNode* n0, ListNode* P) { ListNode *n1 = n0->next; P->next = n1; n0->next = P; } -/* 删除链表的结点 n0 之后的首个结点 */ +/* 删除链表的节点 n0 之后的首个节点 */ // 由于引入了 stdio.h ,此处无法使用 remove 关键词 // 详见 https://github.com/krahets/hello-algo/pull/244#discussion_r1067863888 void removeNode(ListNode* n0) { @@ -27,7 +27,7 @@ void removeNode(ListNode* n0) { free(P); } -/* 访问链表中索引为 index 的结点 */ +/* 访问链表中索引为 index 的节点 */ ListNode* access(ListNode* head, int index) { while (head && head->next && index) { head = head->next; @@ -36,7 +36,7 @@ ListNode* access(ListNode* head, int index) { return head; } -/* 在链表中查找值为 target 的首个结点 */ +/* 在链表中查找值为 target 的首个节点 */ int find(ListNode* head, int target) { int index = 0; while (head) { @@ -52,7 +52,7 @@ int find(ListNode* head, int target) { /* Driver Code */ int main() { /* 初始化链表 */ - // 初始化各个结点 + // 初始化各个节点 ListNode* n0 = newListNode(1); ListNode* n1 = newListNode(3); ListNode* n2 = newListNode(2); @@ -66,23 +66,23 @@ int main() { printf("初始化的链表为\r\n"); printLinkedList(n0); - /* 插入结点 */ + /* 插入节点 */ insert(n0, newListNode(0)); - printf("插入结点后的链表为\r\n"); + printf("插入节点后的链表为\r\n"); printLinkedList(n0); - /* 删除结点 */ + /* 删除节点 */ removeNode(n0); - printf("删除结点后的链表为\r\n"); + printf("删除节点后的链表为\r\n"); printLinkedList(n0); - /* 访问结点 */ + /* 访问节点 */ ListNode* node = access(n0, 3); - printf("链表中索引 3 处的结点的值 = %d\r\n", node->val); + printf("链表中索引 3 处的节点的值 = %d\r\n", node->val); - /* 查找结点 */ + /* 查找节点 */ int index = find(n0, 2); - printf("链表中值为 2 的结点的索引 = %d\r\n", index); + printf("链表中值为 2 的节点的索引 = %d\r\n", index); return 0; } diff --git a/codes/c/chapter_heap/my_heap.c b/codes/c/chapter_heap/my_heap.c index afb8ce36..2febac8a 100644 --- a/codes/c/chapter_heap/my_heap.c +++ b/codes/c/chapter_heap/my_heap.c @@ -27,23 +27,23 @@ maxHeap *newMaxHeap(int nums[], int size) { h->size = size; memcpy(h->data, nums, size * sizeof(int)); for (int i = size - 1; i >= 0; i--) { - // 堆化除叶结点以外的其他所有结点 + // 堆化除叶节点以外的其他所有节点 siftDown(h, i); } return h; } -/* 获取左子结点索引 */ +/* 获取左子节点索引 */ int left(maxHeap *h, int i) { return 2 * i + 1; } -/* 获取右子结点索引 */ +/* 获取右子节点索引 */ int right(maxHeap *h, int i) { return 2 * i + 2; } -/* 获取父结点索引 */ +/* 获取父节点索引 */ int parent(maxHeap *h, int i) { return (i - 1) / 2; } @@ -72,12 +72,12 @@ int peek(maxHeap *h) { /* 元素入堆 */ int push(maxHeap *h, int val) { - // 默认情况下,不应该添加这么多结点 + // 默认情况下,不应该添加这么多节点 if (h->size == MAX_SIZE) { printf("heap is full!"); return NIL; } - // 添加结点 + // 添加节点 h->data[h->size] = val; h->size++; @@ -92,9 +92,9 @@ int pop(maxHeap *h) { printf("heap is empty!"); return NIL; } - // 交换根结点与最右叶结点(即交换首元素与尾元素) + // 交换根节点与最右叶节点(即交换首元素与尾元素) swap(h, 0, size(h) - 1); - // 删除结点 + // 删除节点 int val = h->data[h->size - 1]; h->size--; // 从顶至底堆化 @@ -105,10 +105,10 @@ int pop(maxHeap *h) { } -/* 从结点 i 开始,从顶至底堆化 */ +/* 从节点 i 开始,从顶至底堆化 */ void siftDown(maxHeap *h, int i) { while (true) { - // 判断结点 i, l, r 中值最大的结点,记为 max + // 判断节点 i, l, r 中值最大的节点,记为 max int l = left(h, i); int r = right(h, i); int max = i; @@ -118,27 +118,27 @@ void siftDown(maxHeap *h, int i) { if (r < size(h) && h->data[r] > h->data[max]) { max = r; } - // 若结点 i 最大或索引 l, r 越界,则无需继续堆化,跳出 + // 若节点 i 最大或索引 l, r 越界,则无需继续堆化,跳出 if (max == i) { break; } - // 交换两结点 + // 交换两节点 swap(h, i, max); // 循环向下堆化 i = max; } } -/* 从结点 i 开始,从底至顶堆化 */ +/* 从节点 i 开始,从底至顶堆化 */ void siftUp(maxHeap *h, int i) { while (true) { - // 获取结点 i 的父结点 + // 获取节点 i 的父节点 int p = parent(h, i); - // 当“越过根结点”或“结点无需修复”时,结束堆化 + // 当“越过根节点”或“节点无需修复”时,结束堆化 if (p < 0 || h->data[i] <= h->data[p]) { break; } - // 交换两结点 + // 交换两节点 swap(h, i, p); // 循环向上堆化 i = p; diff --git a/codes/c/chapter_searching/linear_search.c b/codes/c/chapter_searching/linear_search.c index 3edbe084..bd5c773f 100644 --- a/codes/c/chapter_searching/linear_search.c +++ b/codes/c/chapter_searching/linear_search.c @@ -22,12 +22,12 @@ int linearSearchArray(int *nums, int len, int target) { ListNode* linearSearchLinkedList(ListNode* head, int target) { // 遍历链表 while (head != NULL) { - // 找到目标结点,返回之 + // 找到目标节点,返回之 if (head->val == target) return head; head = head->next; } - // 未找到目标结点,返回 NULL + // 未找到目标节点,返回 NULL return NULL; } @@ -44,9 +44,9 @@ int main() { ListNode* head = arrToLinkedList(nums, 10); ListNode* node = linearSearchLinkedList(head, target); if(node == NULL) { - printf("目标结点值 3 的对应结点对象为 NULL\n"); + printf("目标节点值 3 的对应节点对象为 NULL\n"); } else { - printf("目标结点值 3 的对应结点对象为 addr: %p val: %d\n", node, node->val); + printf("目标节点值 3 的对应节点对象为 addr: %p val: %d\n", node, node->val); } return 0; diff --git a/codes/c/chapter_stack_and_queue/linkedlist_deque.c b/codes/c/chapter_stack_and_queue/linkedlist_deque.c index 309752fe..d8f1392c 100644 --- a/codes/c/chapter_stack_and_queue/linkedlist_deque.c +++ b/codes/c/chapter_stack_and_queue/linkedlist_deque.c @@ -6,16 +6,16 @@ #include "../include/include.h" -/* 双向链表结点 */ +/* 双向链表节点 */ struct DoublyListNode { - int val; // 结点值 - struct DoublyListNode *next; // 后继结点 - struct DoublyListNode *prev; // 前驱结点 + int val; // 节点值 + struct DoublyListNode *next; // 后继节点 + struct DoublyListNode *prev; // 前驱节点 }; typedef struct DoublyListNode DoublyListNode; -/* 双向链表结点构造方法 */ +/* 双向链表节点构造方法 */ DoublyListNode *newDoublyListNode(int num) { DoublyListNode* new = (DoublyListNode *) malloc(sizeof(DoublyListNode)); new->val = num; @@ -24,14 +24,14 @@ DoublyListNode *newDoublyListNode(int num) { return new; } -/* 双向链表结点析构方法 */ +/* 双向链表节点析构方法 */ void delDoublyListNode(DoublyListNode *node) { free(node); } /* 基于双向链表实现的双向队列 */ struct LinkedListDeque { - DoublyListNode *front, *rear; // 头结点 front ,尾结点 rear + DoublyListNode *front, *rear; // 头节点 front ,尾节点 rear int queSize; // 双向队列的长度 }; @@ -47,7 +47,7 @@ LinkedListDeque *newLinkedListDeque() { /* 析构方法 */ void delLinkedListdeque(LinkedListDeque *deque) { - // 释放所有结点 + // 释放所有节点 for (int i=0; iqueSize && deque->front != NULL; i++) { DoublyListNode *tmp = deque->front; deque->front = deque->front->next; @@ -79,7 +79,7 @@ void push(LinkedListDeque *deque, int num, bool isFront) { // 将 node 添加至链表头部 deque->front->prev = node; node->next = deque->front; - deque->front = node;// 更新头结点 + deque->front = node;// 更新头节点 } // 对尾入队操作 else { @@ -120,25 +120,25 @@ int pop(LinkedListDeque *deque, bool isFront) { int val; // 队首出队操作 if(isFront) { - val = peekFirst(deque); // 暂存头结点值 + val = peekFirst(deque); // 暂存头节点值 DoublyListNode *fNext = deque->front->next; if (fNext) { fNext->prev = NULL; deque->front->next = NULL; delDoublyListNode(deque->front); } - deque->front = fNext; // 更新头结点 + deque->front = fNext; // 更新头节点 } // 队尾出队操作 else { - val = peekLast(deque); // 暂存尾结点值 + val = peekLast(deque); // 暂存尾节点值 DoublyListNode *rPrev = deque->rear->prev; if (rPrev) { rPrev->next = NULL; deque->rear->prev = NULL; delDoublyListNode(deque->rear); } - deque->rear = rPrev; // 更新尾结点 + deque->rear = rPrev; // 更新尾节点 } deque->queSize--; // 更新队列长度 return val; diff --git a/codes/c/chapter_stack_and_queue/linkedlist_queue.c b/codes/c/chapter_stack_and_queue/linkedlist_queue.c index 4e66588e..5f1c4ce0 100644 --- a/codes/c/chapter_stack_and_queue/linkedlist_queue.c +++ b/codes/c/chapter_stack_and_queue/linkedlist_queue.c @@ -24,7 +24,7 @@ LinkedListQueue *newLinkedListQueue() { /* 析构方法 */ void delLinkedListQueue(LinkedListQueue *queue) { - // 释放所有结点 + // 释放所有节点 for (int i=0; iqueSize && queue->front != NULL; i++) { ListNode *tmp = queue->front; queue->front = queue->front->next; @@ -46,14 +46,14 @@ bool empty(LinkedListQueue *queue) { /* 入队 */ void push(LinkedListQueue *queue, int num) { - // 尾结点处添加 node + // 尾节点处添加 node ListNode *node = newListNode(num); - // 如果队列为空,则令头、尾结点都指向该结点 + // 如果队列为空,则令头、尾节点都指向该节点 if (queue->front == NULL) { queue->front = node; queue->rear = node; } - // 如果队列不为空,则将该结点添加到尾结点后 + // 如果队列不为空,则将该节点添加到尾节点后 else { queue->rear->next = node; queue->rear = node; diff --git a/codes/c/chapter_stack_and_queue/linkedlist_stack.c b/codes/c/chapter_stack_and_queue/linkedlist_stack.c index 71d86f8e..24ee04a8 100644 --- a/codes/c/chapter_stack_and_queue/linkedlist_stack.c +++ b/codes/c/chapter_stack_and_queue/linkedlist_stack.c @@ -8,7 +8,7 @@ /* 基于链表实现的栈 */ struct linkedListStack { - ListNode *top; // 将头结点作为栈顶 + ListNode *top; // 将头节点作为栈顶 int size; // 栈的长度 }; @@ -55,8 +55,8 @@ int peek(linkedListStack *s) { void push(linkedListStack *s, int num) { assert(s); ListNode *node = (ListNode *) malloc(sizeof(ListNode)); - node->next = s->top; // 更新新加结点指针域 - node->val = num; // 更新新加结点数据域 + node->next = s->top; // 更新新加节点指针域 + node->val = num; // 更新新加节点数据域 s->top = node; // 更新栈顶 s->size++; // 更新栈大小 } diff --git a/codes/c/chapter_tree/avl_tree.c b/codes/c/chapter_tree/avl_tree.c index 6b64deb0..432cd5d7 100644 --- a/codes/c/chapter_tree/avl_tree.c +++ b/codes/c/chapter_tree/avl_tree.c @@ -21,18 +21,18 @@ avlTree *newAVLTree() { } int height(TreeNode *node) { - // 空结点高度为 -1 ,叶结点高度为 0 + // 空节点高度为 -1 ,叶节点高度为 0 if (node != NULL) { return node->height; } return -1; } -/* 更新结点高度 */ +/* 更新节点高度 */ int updateHeight(TreeNode *node) { int lh = height(node->left); int rh = height(node->right); - // 结点高度等于最高子树高度 + 1 + // 节点高度等于最高子树高度 + 1 if (lh > rh) { node->height = lh + 1; } else { @@ -42,11 +42,11 @@ int updateHeight(TreeNode *node) { /* 获取平衡因子 */ int balanceFactor(TreeNode *node) { - // 空结点平衡因子为 0 + // 空节点平衡因子为 0 if (node == NULL) { return 0; } - // 结点平衡因子 = 左子树高度 - 右子树高度 + // 节点平衡因子 = 左子树高度 - 右子树高度 return height(node->left) - height(node->right); } @@ -58,10 +58,10 @@ TreeNode *rightRotate(TreeNode *node) { // 以 child 为原点,将 node 向右旋转 child->right = node; node->left = grandChild; - // 更新结点高度 + // 更新节点高度 updateHeight(node); updateHeight(child); - // 返回旋转后子树的根结点 + // 返回旋转后子树的根节点 return child; } @@ -73,16 +73,16 @@ TreeNode *leftRotate(TreeNode *node) { // 以 child 为原点,将 node 向左旋转 child->left = node; node->right = grandChild; - // 更新结点高度 + // 更新节点高度 updateHeight(node); updateHeight(child); - // 返回旋转后子树的根结点 + // 返回旋转后子树的根节点 return child; } /* 执行旋转操作,使该子树重新恢复平衡 */ TreeNode *rotate(TreeNode *node) { - // 获取结点 node 的平衡因子 + // 获取节点 node 的平衡因子 int bf = balanceFactor(node); // 左偏树 if (bf > 1) { @@ -110,54 +110,54 @@ TreeNode *rotate(TreeNode *node) { return node; } -/* 递归插入结点(辅助方法) */ +/* 递归插入节点(辅助方法) */ TreeNode *insertHelper(TreeNode *node, int val) { if (node == NULL) { return newTreeNode(val); } - /* 1. 查找插入位置,并插入结点 */ + /* 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; } -/* 插入结点 */ +/* 插入节点 */ TreeNode *insert(avlTree *tree, int val) { tree->root = insertHelper(tree->root, val); return tree->root; } -/* 获取中序遍历中的下一个结点(仅适用于 root 有左子结点的情况) */ +/* 获取中序遍历中的下一个节点(仅适用于 root 有左子节点的情况) */ TreeNode *getInOrderNext(TreeNode *node) { if (node == NULL) { return node; } - // 循环访问左子结点,直到叶结点时为最小结点,跳出 + // 循环访问左子节点,直到叶节点时为最小节点,跳出 while (node->left != NULL) { node = node->left; } return node; } -/* 递归删除结点(辅助方法) */ +/* 递归删除节点(辅助方法) */ TreeNode *removeHelper(TreeNode *node, int val) { TreeNode *child, *grandChild, *temp; if (node == NULL) { return NULL; } - /* 1. 查找结点,并删除之 */ + /* 1. 查找节点,并删除之 */ if (val < node->val) { node->left = removeHelper(node->left, val); } else if (val > node->val) { @@ -168,64 +168,64 @@ TreeNode *removeHelper(TreeNode *node, int val) { if (node->right != NULL) { child = node->right; } - // 子结点数量 = 0 ,直接删除 node 并返回 + // 子节点数量 = 0 ,直接删除 node 并返回 if (child == NULL) { return NULL; } else { - // 子结点数量 = 1 ,直接删除 node + // 子节点数量 = 1 ,直接删除 node node = child; } } else { - // 子结点数量 = 2 ,则将中序遍历的下个结点删除,并用该结点替换当前结点 + // 子节点数量 = 2 ,则将中序遍历的下个节点删除,并用该节点替换当前节点 temp = getInOrderNext(node->right); node->right = removeHelper(node->right, temp->val); node->val = temp->val; } } - // 更新结点高度 + // 更新节点高度 updateHeight(node); /* 2. 执行旋转操作,使该子树重新恢复平衡 */ node = rotate(node); - // 返回子树的根结点 + // 返回子树的根节点 return node; } -/* 删除结点 */ +/* 删除节点 */ // 由于引入了 stdio.h ,此处无法使用 remove 关键词 TreeNode *removeNode(avlTree *tree, int val) { TreeNode *root = removeHelper(tree->root, val); return root; } -/* 查找结点 */ +/* 查找节点 */ TreeNode *search(avlTree *tree, int val) { TreeNode *cur = tree->root; - // 循环查找,越过叶结点后跳出 + // 循环查找,越过叶节点后跳出 while (cur != NULL) { if (cur->val < val) { - // 目标结点在 cur 的右子树中 + // 目标节点在 cur 的右子树中 cur = cur->right; } else if (cur->val > val) { - // 目标结点在 cur 的左子树中 + // 目标节点在 cur 的左子树中 cur = cur->left; } else { - // 找到目标结点,跳出循环 + // 找到目标节点,跳出循环 break; } } - // 找到目标结点,跳出循环 + // 找到目标节点,跳出循环 return cur; } void testInsert(avlTree *tree, int val) { insert(tree, val); - printf("\n插入结点 %d 后,AVL 树为 \n", val); + printf("\n插入节点 %d 后,AVL 树为 \n", val); printTree(tree->root); } void testRemove(avlTree *tree, int val) { removeNode(tree, val); - printf("\n删除结点 %d 后,AVL 树为 \n", val); + printf("\n删除节点 %d 后,AVL 树为 \n", val); printTree(tree->root); } @@ -233,8 +233,8 @@ void testRemove(avlTree *tree, int val) { int main() { /* 初始化空 AVL 树 */ avlTree *tree = (avlTree *) newAVLTree(); - /* 插入结点 */ - // 请关注插入结点后,AVL 树是如何保持平衡的 + /* 插入节点 */ + // 请关注插入节点后,AVL 树是如何保持平衡的 testInsert(tree, 1); testInsert(tree, 2); testInsert(tree, 3); @@ -246,16 +246,16 @@ int main() { testInsert(tree, 10); testInsert(tree, 6); - /* 插入重复结点 */ + /* 插入重复节点 */ testInsert(tree, 7); - /* 删除结点 */ - // 请关注删除结点后,AVL 树是如何保持平衡的 - testRemove(tree, 8); // 删除度为 0 的结点 - testRemove(tree, 5); // 删除度为 1 的结点 - testRemove(tree, 4); // 删除度为 2 的结点 + /* 删除节点 */ + // 请关注删除节点后,AVL 树是如何保持平衡的 + testRemove(tree, 8); // 删除度为 0 的节点 + testRemove(tree, 5); // 删除度为 1 的节点 + testRemove(tree, 4); // 删除度为 2 的节点 - /* 查询结点 */ + /* 查询节点 */ TreeNode *node = search(tree, 7); - printf("\n查找到的结点对象结点值 = %d \n", node->val); + printf("\n查找到的节点对象节点值 = %d \n", node->val); } \ No newline at end of file diff --git a/codes/c/chapter_tree/binary_search_tree.c b/codes/c/chapter_tree/binary_search_tree.c index b8ddddf4..1039c24f 100644 --- a/codes/c/chapter_tree/binary_search_tree.c +++ b/codes/c/chapter_tree/binary_search_tree.c @@ -23,7 +23,7 @@ TreeNode *buildTree(int nums[], int i, int j) { if (i > j) { return NULL; } - // 将数组中间结点作为根结点 + // 将数组中间节点作为根节点 int mid = (i + j) / 2; TreeNode *root = newTreeNode(nums[mid]); // 递归建立左子树和右子树 @@ -43,39 +43,39 @@ binarySearchTree *newBinarySearchTree(int nums[], int size) { return bst; } -/* 获取二叉树根结点 */ +/* 获取二叉树根节点 */ TreeNode *getRoot(binarySearchTree *bst) { return bst->root; } -/* 查找结点 */ +/* 查找节点 */ TreeNode *search(binarySearchTree *bst, int num) { TreeNode *cur = bst->root; - // 循环查找,越过叶结点后跳出 + // 循环查找,越过叶节点后跳出 while (cur != NULL) { if (cur->val < num) { - // 目标结点在 cur 的右子树中 + // 目标节点在 cur 的右子树中 cur = cur->right; } else if (cur->val > num) { - // 目标结点在 cur 的左子树中 + // 目标节点在 cur 的左子树中 cur = cur->left; } else { - // 找到目标结点,跳出循环 + // 找到目标节点,跳出循环 break; } } - // 返回目标结点 + // 返回目标节点 return cur; } -/* 插入结点 */ +/* 插入节点 */ TreeNode *insert(binarySearchTree *bst, int num) { // 若树为空,直接提前返回 if (bst->root == NULL) return NULL; TreeNode *cur = bst->root, *pre = NULL; - // 循环查找,越过叶结点后跳出 + // 循环查找,越过叶节点后跳出 while (cur != NULL) { - // 找到重复结点,直接返回 + // 找到重复节点,直接返回 if (cur->val == num) { return NULL; } @@ -88,7 +88,7 @@ TreeNode *insert(binarySearchTree *bst, int num) { cur = cur->left; } } - // 插入结点 val + // 插入节点 val TreeNode *node = newTreeNode(num); if (pre->val < num) { pre->right = node; @@ -98,56 +98,56 @@ TreeNode *insert(binarySearchTree *bst, int num) { return node; } -/* 获取中序遍历中的下一个结点(仅适用于 root 有左子结点的情况) */ +/* 获取中序遍历中的下一个节点(仅适用于 root 有左子节点的情况) */ TreeNode *getInOrderNext(TreeNode *root) { if (root == NULL) return root; - // 循环访问左子结点,直到叶结点时为最小结点,跳出 + // 循环访问左子节点,直到叶节点时为最小节点,跳出 while (root->left != NULL) { root = root->left; } return root; } -/* 删除结点 */ +/* 删除节点 */ // 由于引入了 stdio.h ,此处无法使用 remove 关键词 TreeNode *removeNode(binarySearchTree *bst, int num) { // 若树为空,直接提前返回 if (bst->root == NULL) return NULL; TreeNode *cur = bst->root, *pre = NULL; - // 循环查找,越过叶结点后跳出 + // 循环查找,越过叶节点后跳出 while (cur != NULL) { - // 找到待删除结点,跳出循环 + // 找到待删除节点,跳出循环 if (cur->val == num) break; pre = cur; if (cur->val < num) { - // 待删除结点在 root 的右子树中 + // 待删除节点在 root 的右子树中 cur = cur->right; } else { - // 待删除结点在 root 的左子树中 + // 待删除节点在 root 的左子树中 cur = cur->left; } } - // 若无待删除结点,则直接返回 + // 若无待删除节点,则直接返回 if (cur == NULL) { return NULL; } - // 判断待删除结点是否存在子结点 + // 判断待删除节点是否存在子节点 if (cur->left == NULL || cur->right == NULL) { - /* 子结点数量 = 0 or 1 */ - // 当子结点数量 = 0 / 1 时, child = nullptr / 该子结点 + /* 子节点数量 = 0 or 1 */ + // 当子节点数量 = 0 / 1 时, child = nullptr / 该子节点 TreeNode *child = cur->left != NULL ? cur->left : cur->right; - // 删除结点 cur + // 删除节点 cur if (pre->left == cur) { pre->left = child; } else { pre->right = child; } } else { - /* 子结点数量 = 2 */ - // 获取中序遍历中 cur 的下一个结点 + /* 子节点数量 = 2 */ + // 获取中序遍历中 cur 的下一个节点 TreeNode *nex = getInOrderNext(cur->right); int tmp = nex->val; - // 递归删除结点 nex + // 递归删除节点 nex removeNode(bst, nex->val); // 将 nex 的值复制给 cur cur->val = tmp; @@ -163,26 +163,26 @@ int main() { printf("初始化的二叉树为\n"); printTree(getRoot(bst)); - /* 查找结点 */ + /* 查找节点 */ TreeNode *node = search(bst, 7); - printf("查找到的结点对象的结点值 = %d\n", node->val); + printf("查找到的节点对象的节点值 = %d\n", node->val); - /* 插入结点 */ + /* 插入节点 */ insert(bst, 16); - printf("插入结点 16 后,二叉树为\n"); + printf("插入节点 16 后,二叉树为\n"); printTree(getRoot(bst)); - /* 删除结点 */ + /* 删除节点 */ removeNode(bst, 1); - printf("删除结点 1 后,二叉树为\n"); + printf("删除节点 1 后,二叉树为\n"); printTree(getRoot(bst)); removeNode(bst, 2); - printf("删除结点 2 后,二叉树为\n"); + printf("删除节点 2 后,二叉树为\n"); printTree(getRoot(bst)); removeNode(bst, 4); - printf("删除结点 4 后,二叉树为\n"); + printf("删除节点 4 后,二叉树为\n"); printTree(getRoot(bst)); // 释放内存 diff --git a/codes/c/chapter_tree/binary_tree.c b/codes/c/chapter_tree/binary_tree.c index 1eb8e846..fccb1c63 100644 --- a/codes/c/chapter_tree/binary_tree.c +++ b/codes/c/chapter_tree/binary_tree.c @@ -9,7 +9,7 @@ /* Driver Code */ int main() { /* 初始化二叉树 */ - // 初始化结点 + // 初始化节点 TreeNode* n1 = newTreeNode(1); TreeNode* n2 = newTreeNode(2); TreeNode* n3 = newTreeNode(3); @@ -23,19 +23,19 @@ int main() { printf("初始化二叉树\n"); printTree(n1); - /* 插入与删除结点 */ + /* 插入与删除节点 */ TreeNode* P = newTreeNode(0); - // 在 n1 -> n2 中间插入结点 P + // 在 n1 -> n2 中间插入节点 P n1->left = P; P->left = n2; - printf("插入结点 P 后\n"); + printf("插入节点 P 后\n"); printTree(n1); - // 删除结点 P + // 删除节点 P n1->left = n2; // 释放内存 free(P); - printf("删除结点 P 后\n"); + printf("删除节点 P 后\n"); printTree(n1); return 0; diff --git a/codes/c/chapter_tree/binary_tree_bfs.c b/codes/c/chapter_tree/binary_tree_bfs.c index fe2604eb..338fef1a 100644 --- a/codes/c/chapter_tree/binary_tree_bfs.c +++ b/codes/c/chapter_tree/binary_tree_bfs.c @@ -18,7 +18,7 @@ int *levelOrder(TreeNode *root, int *size) { queue = (TreeNode **) malloc(sizeof(TreeNode) * MAX_NODE_SIZE); // 队列指针 front = 0, rear = 0; - // 加入根结点 + // 加入根节点 queue[rear++] = root; // 初始化一个列表,用于保存遍历序列 /* 辅助数组 */ @@ -28,14 +28,14 @@ int *levelOrder(TreeNode *root, int *size) { while (front < rear) { // 队列出队 node = queue[front++]; - // 保存结点值 + // 保存节点值 arr[index++] = node->val; if (node->left != NULL) { - // 左子结点入队 + // 左子节点入队 queue[rear++] = node->left; } if (node->right != NULL) { - // 右子结点入队 + // 右子节点入队 queue[rear++] = node->right; } } @@ -59,7 +59,7 @@ int main() { /* 层序遍历 */ // 需要传入数组的长度 int *arr = levelOrder(root, &size); - printf("层序遍历的结点打印序列 = "); + printf("层序遍历的节点打印序列 = "); printArray(arr, size); return 0; diff --git a/codes/c/chapter_tree/binary_tree_dfs.c b/codes/c/chapter_tree/binary_tree_dfs.c index 4b259624..810210d6 100644 --- a/codes/c/chapter_tree/binary_tree_dfs.c +++ b/codes/c/chapter_tree/binary_tree_dfs.c @@ -12,7 +12,7 @@ int *arr; /* 前序遍历 */ void preOrder(TreeNode *root, int *size) { if (root == NULL) return; - // 访问优先级:根结点 -> 左子树 -> 右子树 + // 访问优先级:根节点 -> 左子树 -> 右子树 arr[(*size)++] = root->val; preOrder(root->left, size); preOrder(root->right, size); @@ -21,7 +21,7 @@ void preOrder(TreeNode *root, int *size) { /* 中序遍历 */ void inOrder(TreeNode *root, int *size) { if (root == NULL) return; - // 访问优先级:左子树 -> 根结点 -> 右子树 + // 访问优先级:左子树 -> 根节点 -> 右子树 inOrder(root->left, size); arr[(*size)++] = root->val; inOrder(root->right, size); @@ -30,7 +30,7 @@ void inOrder(TreeNode *root, int *size) { /* 后序遍历 */ void postOrder(TreeNode *root, int *size) { if (root == NULL) return; - // 访问优先级:左子树 -> 右子树 -> 根结点 + // 访问优先级:左子树 -> 右子树 -> 根节点 postOrder(root->left, size); postOrder(root->right, size); arr[(*size)++] = root->val; @@ -52,19 +52,19 @@ int main() { arr = (int *) malloc(sizeof(int) * MAX_NODE_SIZE); size = 0; preOrder(root, &size); - printf("前序遍历的结点打印序列 = "); + printf("前序遍历的节点打印序列 = "); printArray(arr, size); /* 中序遍历 */ size = 0; inOrder(root, &size); - printf("中序遍历的结点打印序列 = "); + printf("中序遍历的节点打印序列 = "); printArray(arr, size); /* 后序遍历 */ size = 0; postOrder(root, &size); - printf("后序遍历的结点打印序列 = "); + printf("后序遍历的节点打印序列 = "); printArray(arr, size); return 0; diff --git a/codes/c/include/list_node.h b/codes/c/include/list_node.h index 035a4568..16ee7385 100644 --- a/codes/c/include/list_node.h +++ b/codes/c/include/list_node.h @@ -10,16 +10,16 @@ extern "C" { #endif -/* 链表结点结构体 */ +/* 链表节点结构体 */ struct ListNode { - int val; // 结点值 - struct ListNode *next; // 指向下一结点的指针(引用) + int val; // 节点值 + struct ListNode *next; // 指向下一节点的指针(引用) }; // typedef 作用是为一种数据类型定义一个新名字 typedef struct ListNode ListNode; -/* 构造函数,初始化一个新结点 */ +/* 构造函数,初始化一个新节点 */ ListNode *newListNode(int val) { ListNode *node, *next; node = (ListNode *) malloc(sizeof(ListNode)); diff --git a/codes/c/include/tree_node.h b/codes/c/include/tree_node.h index c0438c43..f9252f4a 100644 --- a/codes/c/include/tree_node.h +++ b/codes/c/include/tree_node.h @@ -52,18 +52,18 @@ TreeNode *arrToTree(const int *arr, size_t size) { TreeNode *root, *node; TreeNode **queue; - /* 根结点 */ + /* 根节点 */ root = newTreeNode(arr[0]); /* 辅助队列 */ queue = (TreeNode **) malloc(sizeof(TreeNode) * MAX_NODE_SIZE); // 队列指针 front = 0, rear = 0; - // 将根结点放入队尾 + // 将根节点放入队尾 queue[rear++] = root; // 记录遍历数组的索引 index = 0; while (front < rear) { - // 取队列中的头结点,并让头结点出队 + // 取队列中的头节点,并让头节点出队 node = queue[front++]; index++; if (index < size) { @@ -103,14 +103,14 @@ int *treeToArr(TreeNode *root) { queue = (TreeNode **) malloc(sizeof(TreeNode) * MAX_NODE_SIZE); // 队列指针 front = 0, rear = 0; - // 将根结点放入队尾 + // 将根节点放入队尾 queue[rear++] = root; /* 辅助数组 */ arr = (int *) malloc(sizeof(int) * MAX_NODE_SIZE); // 数组指针 index = 0; while (front < rear) { - // 取队列中的头结点,并让头结点出队 + // 取队列中的头节点,并让头节点出队 node = queue[front++]; if (node != NULL) { arr[index] = node->val; diff --git a/codes/cpp/chapter_array_and_linkedlist/linked_list.cpp b/codes/cpp/chapter_array_and_linkedlist/linked_list.cpp index 8392fcb5..a98fc058 100644 --- a/codes/cpp/chapter_array_and_linkedlist/linked_list.cpp +++ b/codes/cpp/chapter_array_and_linkedlist/linked_list.cpp @@ -6,14 +6,14 @@ #include "../include/include.hpp" -/* 在链表的结点 n0 之后插入结点 P */ +/* 在链表的节点 n0 之后插入节点 P */ void insert(ListNode* n0, ListNode* P) { ListNode* n1 = n0->next; P->next = n1; n0->next = P; } -/* 删除链表的结点 n0 之后的首个结点 */ +/* 删除链表的节点 n0 之后的首个节点 */ void remove(ListNode* n0) { if (n0->next == nullptr) return; @@ -25,7 +25,7 @@ void remove(ListNode* n0) { delete P; } -/* 访问链表中索引为 index 的结点 */ +/* 访问链表中索引为 index 的节点 */ ListNode* access(ListNode* head, int index) { for (int i = 0; i < index; i++) { if (head == nullptr) @@ -35,7 +35,7 @@ ListNode* access(ListNode* head, int index) { return head; } -/* 在链表中查找值为 target 的首个结点 */ +/* 在链表中查找值为 target 的首个节点 */ int find(ListNode* head, int target) { int index = 0; while (head != nullptr) { @@ -51,7 +51,7 @@ int find(ListNode* head, int target) { /* Driver Code */ int main() { /* 初始化链表 */ - // 初始化各个结点 + // 初始化各个节点 ListNode* n0 = new ListNode(1); ListNode* n1 = new ListNode(3); ListNode* n2 = new ListNode(2); @@ -65,23 +65,23 @@ int main() { cout << "初始化的链表为" << endl; PrintUtil::printLinkedList(n0); - /* 插入结点 */ + /* 插入节点 */ insert(n0, new ListNode(0)); - cout << "插入结点后的链表为" << endl; + cout << "插入节点后的链表为" << endl; PrintUtil::printLinkedList(n0); - /* 删除结点 */ + /* 删除节点 */ remove(n0); - cout << "删除结点后的链表为" << endl; + cout << "删除节点后的链表为" << endl; PrintUtil::printLinkedList(n0); - /* 访问结点 */ + /* 访问节点 */ ListNode* node = access(n0, 3); - cout << "链表中索引 3 处的结点的值 = " << node->val << endl; + cout << "链表中索引 3 处的节点的值 = " << node->val << endl; - /* 查找结点 */ + /* 查找节点 */ int index = find(n0, 2); - cout << "链表中值为 2 的结点的索引 = " << index << endl; + cout << "链表中值为 2 的节点的索引 = " << index << endl; // 释放内存 freeMemoryLinkedList(n0); diff --git a/codes/cpp/chapter_graph/graph_adjacency_list.cpp b/codes/cpp/chapter_graph/graph_adjacency_list.cpp index cef9746d..174b31d9 100644 --- a/codes/cpp/chapter_graph/graph_adjacency_list.cpp +++ b/codes/cpp/chapter_graph/graph_adjacency_list.cpp @@ -12,7 +12,7 @@ public: // 邻接表,key: 顶点,value:该顶点的所有邻接顶点 unordered_map> adjList; - /* 在 vector 中删除指定结点 */ + /* 在 vector 中删除指定节点 */ void remove(vector &vec, Vertex *vet) { for (int i = 0; i < vec.size(); i++) { if (vec[i] == vet) { diff --git a/codes/cpp/chapter_heap/my_heap.cpp b/codes/cpp/chapter_heap/my_heap.cpp index 96f628cb..4a008f86 100644 --- a/codes/cpp/chapter_heap/my_heap.cpp +++ b/codes/cpp/chapter_heap/my_heap.cpp @@ -12,47 +12,47 @@ private: // 使用动态数组,这样无需考虑扩容问题 vector maxHeap; - /* 获取左子结点索引 */ + /* 获取左子节点索引 */ int left(int i) { return 2 * i + 1; } - /* 获取右子结点索引 */ + /* 获取右子节点索引 */ int right(int i) { return 2 * i + 2; } - /* 获取父结点索引 */ + /* 获取父节点索引 */ int parent(int i) { return (i - 1) / 2; // 向下取整 } - /* 从结点 i 开始,从底至顶堆化 */ + /* 从节点 i 开始,从底至顶堆化 */ void siftUp(int i) { while (true) { - // 获取结点 i 的父结点 + // 获取节点 i 的父节点 int p = parent(i); - // 当“越过根结点”或“结点无需修复”时,结束堆化 + // 当“越过根节点”或“节点无需修复”时,结束堆化 if (p < 0 || maxHeap[i] <= maxHeap[p]) break; - // 交换两结点 + // 交换两节点 swap(maxHeap[i], maxHeap[p]); // 循环向上堆化 i = p; } } - /* 从结点 i 开始,从顶至底堆化 */ + /* 从节点 i 开始,从顶至底堆化 */ void siftDown(int i) { while (true) { - // 判断结点 i, l, r 中值最大的结点,记为 ma + // 判断节点 i, l, r 中值最大的节点,记为 ma int l = left(i), r = right(i), ma = i; - // 若结点 i 最大或索引 l, r 越界,则无需继续堆化,跳出 + // 若节点 i 最大或索引 l, r 越界,则无需继续堆化,跳出 if (l < size() && maxHeap[l] > maxHeap[ma]) ma = l; if (r < size() && maxHeap[r] > maxHeap[ma]) ma = r; - // 若结点 i 最大或索引 l, r 越界,则无需继续堆化,跳出 + // 若节点 i 最大或索引 l, r 越界,则无需继续堆化,跳出 if (ma == i) break; swap(maxHeap[i], maxHeap[ma]); @@ -66,7 +66,7 @@ public: MaxHeap(vector nums) { // 将列表元素原封不动添加进堆 maxHeap = nums; - // 堆化除叶结点以外的其他所有结点 + // 堆化除叶节点以外的其他所有节点 for (int i = parent(size() - 1); i >= 0; i--) { siftDown(i); } @@ -89,7 +89,7 @@ public: /* 元素入堆 */ void push(int val) { - // 添加结点 + // 添加节点 maxHeap.push_back(val); // 从底至顶堆化 siftUp(size() - 1); @@ -101,9 +101,9 @@ public: if (empty()) { throw out_of_range("堆为空"); } - // 交换根结点与最右叶结点(即交换首元素与尾元素) + // 交换根节点与最右叶节点(即交换首元素与尾元素) swap(maxHeap[0], maxHeap[size() - 1]); - // 删除结点 + // 删除节点 maxHeap.pop_back(); // 从顶至底堆化 siftDown(0); diff --git a/codes/cpp/chapter_searching/hashing_search.cpp b/codes/cpp/chapter_searching/hashing_search.cpp index dcd1faa0..47914955 100644 --- a/codes/cpp/chapter_searching/hashing_search.cpp +++ b/codes/cpp/chapter_searching/hashing_search.cpp @@ -17,7 +17,7 @@ int hashingSearchArray(unordered_map map, int target) { /* 哈希查找(链表) */ ListNode* hashingSearchLinkedList(unordered_map map, int target) { - // 哈希表的 key: 目标结点值,value: 结点对象 + // 哈希表的 key: 目标节点值,value: 节点对象 // 若哈希表中无此 key ,返回 nullptr if (map.find(target) == map.end()) return nullptr; @@ -44,11 +44,11 @@ int main() { // 初始化哈希表 unordered_map map1; while (head != nullptr) { - map1[head->val] = head; // key: 结点值,value: 结点 + map1[head->val] = head; // key: 节点值,value: 节点 head = head->next; } ListNode* node = hashingSearchLinkedList(map1, target); - cout << "目标结点值 3 的对应结点对象为 " << node << endl; + cout << "目标节点值 3 的对应节点对象为 " << node << endl; return 0; } diff --git a/codes/cpp/chapter_searching/linear_search.cpp b/codes/cpp/chapter_searching/linear_search.cpp index 2b3dba09..60a08d00 100644 --- a/codes/cpp/chapter_searching/linear_search.cpp +++ b/codes/cpp/chapter_searching/linear_search.cpp @@ -22,12 +22,12 @@ int linearSearchArray(vector& nums, int target) { ListNode* linearSearchLinkedList(ListNode* head, int target) { // 遍历链表 while (head != nullptr) { - // 找到目标结点,返回之 + // 找到目标节点,返回之 if (head->val == target) return head; head = head->next; } - // 未找到目标结点,返回 nullptr + // 未找到目标节点,返回 nullptr return nullptr; } @@ -44,7 +44,7 @@ int main() { /* 在链表中执行线性查找 */ ListNode* head = vecToLinkedList(nums); ListNode* node = linearSearchLinkedList(head, target); - cout << "目标结点值 3 的对应结点对象为 " << node << endl; + cout << "目标节点值 3 的对应节点对象为 " << node << endl; return 0; } diff --git a/codes/cpp/chapter_stack_and_queue/linkedlist_deque.cpp b/codes/cpp/chapter_stack_and_queue/linkedlist_deque.cpp index 76a10cbd..32d36141 100644 --- a/codes/cpp/chapter_stack_and_queue/linkedlist_deque.cpp +++ b/codes/cpp/chapter_stack_and_queue/linkedlist_deque.cpp @@ -7,18 +7,18 @@ #include "../include/include.hpp" -/* 双向链表结点 */ +/* 双向链表节点 */ struct DoublyListNode { - int val; // 结点值 - DoublyListNode *next; // 后继结点指针 - DoublyListNode *prev; // 前驱结点指针 + int val; // 节点值 + DoublyListNode *next; // 后继节点指针 + DoublyListNode *prev; // 前驱节点指针 DoublyListNode(int val) : val(val), prev(nullptr), next(nullptr) {} }; /* 基于双向链表实现的双向队列 */ class LinkedListDeque { private: - DoublyListNode *front, *rear; // 头结点 front ,尾结点 rear + DoublyListNode *front, *rear; // 头节点 front ,尾节点 rear int queSize = 0; // 双向队列的长度 public: @@ -27,7 +27,7 @@ public: /* 析构方法 */ ~LinkedListDeque() { - // 遍历链表删除结点,释放内存 + // 遍历链表删除节点,释放内存 DoublyListNode *pre, *cur = front; while (cur != nullptr) { pre = cur; @@ -57,13 +57,13 @@ public: // 将 node 添加至链表头部 front->prev = node; node->next = front; - front = node; // 更新头结点 + front = node; // 更新头节点 // 队尾入队操作 } else { // 将 node 添加至链表尾部 rear->next = node; node->prev = rear; - rear = node; // 更新尾结点 + rear = node; // 更新尾节点 } queSize++; // 更新队列长度 } @@ -86,26 +86,26 @@ public: int val; // 队首出队操作 if (isFront) { - val = front->val; // 暂存头结点值 - // 删除头结点 + val = front->val; // 暂存头节点值 + // 删除头节点 DoublyListNode *fNext = front->next; if (fNext != nullptr) { fNext->prev = nullptr; front->next = nullptr; delete front; } - front = fNext; // 更新头结点 + front = fNext; // 更新头节点 // 队尾出队操作 } else { - val = rear->val; // 暂存尾结点值 - // 删除尾结点 + val = rear->val; // 暂存尾节点值 + // 删除尾节点 DoublyListNode *rPrev = rear->prev; if (rPrev != nullptr) { rPrev->next = nullptr; rear->prev = nullptr; delete rear; } - rear = rPrev; // 更新尾结点 + rear = rPrev; // 更新尾节点 } queSize--; // 更新队列长度 return val; diff --git a/codes/cpp/chapter_stack_and_queue/linkedlist_queue.cpp b/codes/cpp/chapter_stack_and_queue/linkedlist_queue.cpp index 1e89a2c2..6408bc75 100644 --- a/codes/cpp/chapter_stack_and_queue/linkedlist_queue.cpp +++ b/codes/cpp/chapter_stack_and_queue/linkedlist_queue.cpp @@ -9,7 +9,7 @@ /* 基于链表实现的队列 */ class LinkedListQueue { private: - ListNode *front, *rear; // 头结点 front ,尾结点 rear + ListNode *front, *rear; // 头节点 front ,尾节点 rear int queSize; public: @@ -20,7 +20,7 @@ public: } ~LinkedListQueue() { - // 遍历链表删除结点,释放内存 + // 遍历链表删除节点,释放内存 freeMemoryLinkedList(front); } @@ -36,14 +36,14 @@ public: /* 入队 */ void push(int num) { - // 尾结点后添加 num + // 尾节点后添加 num ListNode* node = new ListNode(num); - // 如果队列为空,则令头、尾结点都指向该结点 + // 如果队列为空,则令头、尾节点都指向该节点 if (front == nullptr) { front = node; rear = node; } - // 如果队列不为空,则将该结点添加到尾结点后 + // 如果队列不为空,则将该节点添加到尾节点后 else { rear->next = node; rear = node; @@ -54,7 +54,7 @@ public: /* 出队 */ void pop() { int num = peek(); - // 删除头结点 + // 删除头节点 ListNode *tmp = front; front = front->next; // 释放内存 diff --git a/codes/cpp/chapter_stack_and_queue/linkedlist_stack.cpp b/codes/cpp/chapter_stack_and_queue/linkedlist_stack.cpp index 1fd06be0..ba25e922 100644 --- a/codes/cpp/chapter_stack_and_queue/linkedlist_stack.cpp +++ b/codes/cpp/chapter_stack_and_queue/linkedlist_stack.cpp @@ -9,7 +9,7 @@ /* 基于链表实现的栈 */ class LinkedListStack { private: - ListNode* stackTop; // 将头结点作为栈顶 + ListNode* stackTop; // 将头节点作为栈顶 int stkSize; // 栈的长度 public: @@ -19,7 +19,7 @@ public: } ~LinkedListStack() { - // 遍历链表删除结点,释放内存 + // 遍历链表删除节点,释放内存 freeMemoryLinkedList(stackTop); } diff --git a/codes/cpp/chapter_tree/avl_tree.cpp b/codes/cpp/chapter_tree/avl_tree.cpp index 3f4cf52d..527cf978 100644 --- a/codes/cpp/chapter_tree/avl_tree.cpp +++ b/codes/cpp/chapter_tree/avl_tree.cpp @@ -9,11 +9,11 @@ /* AVL 树 */ class AVLTree { public: - TreeNode* root; // 根结点 + TreeNode* root; // 根节点 private: - /* 更新结点高度 */ + /* 更新节点高度 */ void updateHeight(TreeNode* node) { - // 结点高度等于最高子树高度 + 1 + // 节点高度等于最高子树高度 + 1 node->height = max(height(node->left), height(node->right)) + 1; } @@ -24,10 +24,10 @@ private: // 以 child 为原点,将 node 向右旋转 child->right = node; node->left = grandChild; - // 更新结点高度 + // 更新节点高度 updateHeight(node); updateHeight(child); - // 返回旋转后子树的根结点 + // 返回旋转后子树的根节点 return child; } @@ -38,16 +38,16 @@ private: // 以 child 为原点,将 node 向左旋转 child->left = node; node->right = grandChild; - // 更新结点高度 + // 更新节点高度 updateHeight(node); updateHeight(child); - // 返回旋转后子树的根结点 + // 返回旋转后子树的根节点 return child; } /* 执行旋转操作,使该子树重新恢复平衡 */ TreeNode* rotate(TreeNode* node) { - // 获取结点 node 的平衡因子 + // 获取节点 node 的平衡因子 int _balanceFactor = balanceFactor(node); // 左偏树 if (_balanceFactor > 1) { @@ -75,40 +75,40 @@ private: return node; } - /* 递归插入结点(辅助方法) */ + /* 递归插入节点(辅助方法) */ TreeNode* insertHelper(TreeNode* node, int val) { if (node == nullptr) return new TreeNode(val); - /* 1. 查找插入位置,并插入结点 */ + /* 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); // 更新结点高度 + return node; // 重复节点不插入,直接返回 + updateHeight(node); // 更新节点高度 /* 2. 执行旋转操作,使该子树重新恢复平衡 */ node = rotate(node); - // 返回子树的根结点 + // 返回子树的根节点 return node; } - /* 获取中序遍历中的下一个结点(仅适用于 root 有左子结点的情况) */ + /* 获取中序遍历中的下一个节点(仅适用于 root 有左子节点的情况) */ TreeNode* getInOrderNext(TreeNode* node) { if (node == nullptr) return node; - // 循环访问左子结点,直到叶结点时为最小结点,跳出 + // 循环访问左子节点,直到叶节点时为最小节点,跳出 while (node->left != nullptr) { node = node->left; } return node; } - /* 递归删除结点(辅助方法) */ + /* 递归删除节点(辅助方法) */ TreeNode* removeHelper(TreeNode* node, int val) { if (node == nullptr) return nullptr; - /* 1. 查找结点,并删除之 */ + /* 1. 查找节点,并删除之 */ if (val < node->val) node->left = removeHelper(node->left, val); else if (val > node->val) @@ -116,74 +116,74 @@ private: else { if (node->left == nullptr || node->right == nullptr) { TreeNode* child = node->left != nullptr ? node->left : node->right; - // 子结点数量 = 0 ,直接删除 node 并返回 + // 子节点数量 = 0 ,直接删除 node 并返回 if (child == nullptr) { delete node; return nullptr; } - // 子结点数量 = 1 ,直接删除 node + // 子节点数量 = 1 ,直接删除 node else { delete node; node = child; } } else { - // 子结点数量 = 2 ,则将中序遍历的下个结点删除,并用该结点替换当前结点 + // 子节点数量 = 2 ,则将中序遍历的下个节点删除,并用该节点替换当前节点 TreeNode* temp = getInOrderNext(node->right); int tempVal = temp->val; node->right = removeHelper(node->right, temp->val); node->val = tempVal; } } - updateHeight(node); // 更新结点高度 + updateHeight(node); // 更新节点高度 /* 2. 执行旋转操作,使该子树重新恢复平衡 */ node = rotate(node); - // 返回子树的根结点 + // 返回子树的根节点 return node; } public: - /* 获取结点高度 */ + /* 获取节点高度 */ int height(TreeNode* node) { - // 空结点高度为 -1 ,叶结点高度为 0 + // 空节点高度为 -1 ,叶节点高度为 0 return node == nullptr ? -1 : node->height; } /* 获取平衡因子 */ int balanceFactor(TreeNode* node) { - // 空结点平衡因子为 0 + // 空节点平衡因子为 0 if (node == nullptr) return 0; - // 结点平衡因子 = 左子树高度 - 右子树高度 + // 节点平衡因子 = 左子树高度 - 右子树高度 return height(node->left) - height(node->right); } - /* 插入结点 */ + /* 插入节点 */ TreeNode* insert(int val) { root = insertHelper(root, val); return root; } - /* 删除结点 */ + /* 删除节点 */ TreeNode* remove(int val) { root = removeHelper(root, val); return root; } - /* 查找结点 */ + /* 查找节点 */ TreeNode* search(int val) { TreeNode* cur = root; - // 循环查找,越过叶结点后跳出 + // 循环查找,越过叶节点后跳出 while (cur != nullptr) { - // 目标结点在 cur 的右子树中 + // 目标节点在 cur 的右子树中 if (cur->val < val) cur = cur->right; - // 目标结点在 cur 的左子树中 + // 目标节点在 cur 的左子树中 else if (cur->val > val) cur = cur->left; - // 找到目标结点,跳出循环 + // 找到目标节点,跳出循环 else break; } - // 返回目标结点 + // 返回目标节点 return cur; } @@ -198,21 +198,21 @@ public: void testInsert(AVLTree& tree, int val) { tree.insert(val); - cout << "\n插入结点 " << val << " 后,AVL 树为" << endl; + cout << "\n插入节点 " << val << " 后,AVL 树为" << endl; PrintUtil::printTree(tree.root); } void testRemove(AVLTree& tree, int val) { tree.remove(val); - cout << "\n删除结点 " << val << " 后,AVL 树为" << endl; + cout << "\n删除节点 " << val << " 后,AVL 树为" << endl; PrintUtil::printTree(tree.root); } int main() { /* 初始化空 AVL 树 */ AVLTree avlTree; - /* 插入结点 */ - // 请关注插入结点后,AVL 树是如何保持平衡的 + /* 插入节点 */ + // 请关注插入节点后,AVL 树是如何保持平衡的 testInsert(avlTree, 1); testInsert(avlTree, 2); testInsert(avlTree, 3); @@ -224,16 +224,16 @@ int main() { testInsert(avlTree, 10); testInsert(avlTree, 6); - /* 插入重复结点 */ + /* 插入重复节点 */ testInsert(avlTree, 7); - /* 删除结点 */ - // 请关注删除结点后,AVL 树是如何保持平衡的 - testRemove(avlTree, 8); // 删除度为 0 的结点 - testRemove(avlTree, 5); // 删除度为 1 的结点 - testRemove(avlTree, 4); // 删除度为 2 的结点 + /* 删除节点 */ + // 请关注删除节点后,AVL 树是如何保持平衡的 + testRemove(avlTree, 8); // 删除度为 0 的节点 + testRemove(avlTree, 5); // 删除度为 1 的节点 + testRemove(avlTree, 4); // 删除度为 2 的节点 - /* 查询结点 */ + /* 查询节点 */ TreeNode* node = avlTree.search(7); - cout << "\n查找到的结点对象为 " << node << ",结点值 = " << node->val << endl; + cout << "\n查找到的节点对象为 " << node << ",节点值 = " << node->val << endl; } diff --git a/codes/cpp/chapter_tree/binary_search_tree.cpp b/codes/cpp/chapter_tree/binary_search_tree.cpp index 69acb87f..fdb8f075 100644 --- a/codes/cpp/chapter_tree/binary_search_tree.cpp +++ b/codes/cpp/chapter_tree/binary_search_tree.cpp @@ -21,7 +21,7 @@ public: freeMemoryTree(root); } - /* 获取二叉树根结点 */ + /* 获取二叉树根节点 */ TreeNode* getRoot() { return root; } @@ -29,7 +29,7 @@ public: /* 构建二叉搜索树 */ TreeNode* buildTree(vector nums, int i, int j) { if (i > j) return nullptr; - // 将数组中间结点作为根结点 + // 将数组中间节点作为根节点 int mid = (i + j) / 2; TreeNode* root = new TreeNode(nums[mid]); // 递归建立左子树和右子树 @@ -38,30 +38,30 @@ public: return root; } - /* 查找结点 */ + /* 查找节点 */ TreeNode* search(int num) { TreeNode* cur = root; - // 循环查找,越过叶结点后跳出 + // 循环查找,越过叶节点后跳出 while (cur != nullptr) { - // 目标结点在 cur 的右子树中 + // 目标节点在 cur 的右子树中 if (cur->val < num) cur = cur->right; - // 目标结点在 cur 的左子树中 + // 目标节点在 cur 的左子树中 else if (cur->val > num) cur = cur->left; - // 找到目标结点,跳出循环 + // 找到目标节点,跳出循环 else break; } - // 返回目标结点 + // 返回目标节点 return cur; } - /* 插入结点 */ + /* 插入节点 */ TreeNode* insert(int num) { // 若树为空,直接提前返回 if (root == nullptr) return nullptr; TreeNode *cur = root, *pre = nullptr; - // 循环查找,越过叶结点后跳出 + // 循环查找,越过叶节点后跳出 while (cur != nullptr) { - // 找到重复结点,直接返回 + // 找到重复节点,直接返回 if (cur->val == num) return nullptr; pre = cur; // 插入位置在 cur 的右子树中 @@ -69,46 +69,46 @@ public: // 插入位置在 cur 的左子树中 else cur = cur->left; } - // 插入结点 val + // 插入节点 val TreeNode* node = new TreeNode(num); if (pre->val < num) pre->right = node; else pre->left = node; return node; } - /* 删除结点 */ + /* 删除节点 */ TreeNode* remove(int num) { // 若树为空,直接提前返回 if (root == nullptr) return nullptr; TreeNode *cur = root, *pre = nullptr; - // 循环查找,越过叶结点后跳出 + // 循环查找,越过叶节点后跳出 while (cur != nullptr) { - // 找到待删除结点,跳出循环 + // 找到待删除节点,跳出循环 if (cur->val == num) break; pre = cur; - // 待删除结点在 cur 的右子树中 + // 待删除节点在 cur 的右子树中 if (cur->val < num) cur = cur->right; - // 待删除结点在 cur 的左子树中 + // 待删除节点在 cur 的左子树中 else cur = cur->left; } - // 若无待删除结点,则直接返回 + // 若无待删除节点,则直接返回 if (cur == nullptr) return nullptr; - // 子结点数量 = 0 or 1 + // 子节点数量 = 0 or 1 if (cur->left == nullptr || cur->right == nullptr) { - // 当子结点数量 = 0 / 1 时, child = nullptr / 该子结点 + // 当子节点数量 = 0 / 1 时, child = nullptr / 该子节点 TreeNode* child = cur->left != nullptr ? cur->left : cur->right; - // 删除结点 cur + // 删除节点 cur if (pre->left == cur) pre->left = child; else pre->right = child; // 释放内存 delete cur; } - // 子结点数量 = 2 + // 子节点数量 = 2 else { - // 获取中序遍历中 cur 的下一个结点 + // 获取中序遍历中 cur 的下一个节点 TreeNode* nex = getInOrderNext(cur->right); int tmp = nex->val; - // 递归删除结点 nex + // 递归删除节点 nex remove(nex->val); // 将 nex 的值复制给 cur cur->val = tmp; @@ -116,10 +116,10 @@ public: return cur; } - /* 获取中序遍历中的下一个结点(仅适用于 root 有左子结点的情况) */ + /* 获取中序遍历中的下一个节点(仅适用于 root 有左子节点的情况) */ TreeNode* getInOrderNext(TreeNode* root) { if (root == nullptr) return root; - // 循环访问左子结点,直到叶结点时为最小结点,跳出 + // 循环访问左子节点,直到叶节点时为最小节点,跳出 while (root->left != nullptr) { root = root->left; } @@ -136,24 +136,24 @@ int main() { cout << endl << "初始化的二叉树为\n" << endl; PrintUtil::printTree(bst->getRoot()); - /* 查找结点 */ + /* 查找节点 */ TreeNode* node = bst->search(7); - cout << endl << "查找到的结点对象为 " << node << ",结点值 = " << node->val << endl; + cout << endl << "查找到的节点对象为 " << node << ",节点值 = " << node->val << endl; - /* 插入结点 */ + /* 插入节点 */ node = bst->insert(16); - cout << endl << "插入结点 16 后,二叉树为\n" << endl; + cout << endl << "插入节点 16 后,二叉树为\n" << endl; PrintUtil::printTree(bst->getRoot()); - /* 删除结点 */ + /* 删除节点 */ bst->remove(1); - cout << endl << "删除结点 1 后,二叉树为\n" << endl; + cout << endl << "删除节点 1 后,二叉树为\n" << endl; PrintUtil::printTree(bst->getRoot()); bst->remove(2); - cout << endl << "删除结点 2 后,二叉树为\n" << endl; + cout << endl << "删除节点 2 后,二叉树为\n" << endl; PrintUtil::printTree(bst->getRoot()); bst->remove(4); - cout << endl << "删除结点 4 后,二叉树为\n" << endl; + cout << endl << "删除节点 4 后,二叉树为\n" << endl; PrintUtil::printTree(bst->getRoot()); // 释放内存 diff --git a/codes/cpp/chapter_tree/binary_tree.cpp b/codes/cpp/chapter_tree/binary_tree.cpp index f6a0a5d8..8ed9dbf4 100644 --- a/codes/cpp/chapter_tree/binary_tree.cpp +++ b/codes/cpp/chapter_tree/binary_tree.cpp @@ -10,7 +10,7 @@ /* Driver Code */ int main() { /* 初始化二叉树 */ - // 初始化结点 + // 初始化节点 TreeNode* n1 = new TreeNode(1); TreeNode* n2 = new TreeNode(2); TreeNode* n3 = new TreeNode(3); @@ -24,17 +24,17 @@ int main() { cout << endl << "初始化二叉树\n" << endl; PrintUtil::printTree(n1); - /* 插入与删除结点 */ + /* 插入与删除节点 */ TreeNode* P = new TreeNode(0); - // 在 n1 -> n2 中间插入结点 P + // 在 n1 -> n2 中间插入节点 P n1->left = P; P->left = n2; - cout << endl << "插入结点 P 后\n" << endl; + cout << endl << "插入节点 P 后\n" << endl; PrintUtil::printTree(n1); - // 删除结点 P + // 删除节点 P n1->left = n2; delete P; // 释放内存 - cout << endl << "删除结点 P 后\n" << endl; + cout << endl << "删除节点 P 后\n" << endl; PrintUtil::printTree(n1); // 释放内存 diff --git a/codes/cpp/chapter_tree/binary_tree_bfs.cpp b/codes/cpp/chapter_tree/binary_tree_bfs.cpp index 8b2ba2d2..e932ba86 100644 --- a/codes/cpp/chapter_tree/binary_tree_bfs.cpp +++ b/codes/cpp/chapter_tree/binary_tree_bfs.cpp @@ -8,7 +8,7 @@ /* 层序遍历 */ vector levelOrder(TreeNode* root) { - // 初始化队列,加入根结点 + // 初始化队列,加入根节点 queue queue; queue.push(root); // 初始化一个列表,用于保存遍历序列 @@ -16,11 +16,11 @@ vector levelOrder(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); // 左子结点入队 + queue.push(node->left); // 左子节点入队 if (node->right != nullptr) - queue.push(node->right); // 右子结点入队 + queue.push(node->right); // 右子节点入队 } return vec; } @@ -36,7 +36,7 @@ int main() { /* 层序遍历 */ vector vec = levelOrder(root); - cout << endl << "层序遍历的结点打印序列 = "; + cout << endl << "层序遍历的节点打印序列 = "; PrintUtil::printVector(vec); return 0; diff --git a/codes/cpp/chapter_tree/binary_tree_dfs.cpp b/codes/cpp/chapter_tree/binary_tree_dfs.cpp index 5ed5b78f..c464b5f0 100644 --- a/codes/cpp/chapter_tree/binary_tree_dfs.cpp +++ b/codes/cpp/chapter_tree/binary_tree_dfs.cpp @@ -12,7 +12,7 @@ vector vec; /* 前序遍历 */ void preOrder(TreeNode* root) { if (root == nullptr) return; - // 访问优先级:根结点 -> 左子树 -> 右子树 + // 访问优先级:根节点 -> 左子树 -> 右子树 vec.push_back(root->val); preOrder(root->left); preOrder(root->right); @@ -21,7 +21,7 @@ void preOrder(TreeNode* root) { /* 中序遍历 */ void inOrder(TreeNode* root) { if (root == nullptr) return; - // 访问优先级:左子树 -> 根结点 -> 右子树 + // 访问优先级:左子树 -> 根节点 -> 右子树 inOrder(root->left); vec.push_back(root->val); inOrder(root->right); @@ -30,7 +30,7 @@ void inOrder(TreeNode* root) { /* 后序遍历 */ void postOrder(TreeNode* root) { if (root == nullptr) return; - // 访问优先级:左子树 -> 右子树 -> 根结点 + // 访问优先级:左子树 -> 右子树 -> 根节点 postOrder(root->left); postOrder(root->right); vec.push_back(root->val); @@ -48,19 +48,19 @@ int main() { /* 前序遍历 */ vec.clear(); preOrder(root); - cout << endl << "前序遍历的结点打印序列 = "; + cout << endl << "前序遍历的节点打印序列 = "; PrintUtil::printVector(vec); /* 中序遍历 */ vec.clear(); inOrder(root); - cout << endl << "中序遍历的结点打印序列 = "; + cout << endl << "中序遍历的节点打印序列 = "; PrintUtil::printVector(vec); /* 后序遍历 */ vec.clear(); postOrder(root); - cout << endl << "后序遍历的结点打印序列 = "; + cout << endl << "后序遍历的节点打印序列 = "; PrintUtil::printVector(vec); return 0; diff --git a/codes/csharp/chapter_array_and_linkedlist/linked_list.cs b/codes/csharp/chapter_array_and_linkedlist/linked_list.cs index 6ca3f141..1b616dd6 100644 --- a/codes/csharp/chapter_array_and_linkedlist/linked_list.cs +++ b/codes/csharp/chapter_array_and_linkedlist/linked_list.cs @@ -9,7 +9,7 @@ namespace hello_algo.chapter_array_and_linkedlist; public class linked_list { - /* 在链表的结点 n0 之后插入结点 P */ + /* 在链表的节点 n0 之后插入节点 P */ public static void insert(ListNode n0, ListNode P) { ListNode? n1 = n0.next; @@ -17,7 +17,7 @@ public class linked_list n0.next = P; } - /* 删除链表的结点 n0 之后的首个结点 */ + /* 删除链表的节点 n0 之后的首个节点 */ public static void remove(ListNode n0) { if (n0.next == null) @@ -28,7 +28,7 @@ public class linked_list n0.next = n1; } - /* 访问链表中索引为 index 的结点 */ + /* 访问链表中索引为 index 的节点 */ public static ListNode? access(ListNode head, int index) { for (int i = 0; i < index; i++) @@ -40,7 +40,7 @@ public class linked_list return head; } - /* 在链表中查找值为 target 的首个结点 */ + /* 在链表中查找值为 target 的首个节点 */ public static int find(ListNode head, int target) { int index = 0; @@ -59,7 +59,7 @@ public class linked_list public void Test() { // 初始化链表 - // 初始化各个结点 + // 初始化各个节点 ListNode n0 = new ListNode(1); ListNode n1 = new ListNode(3); ListNode n2 = new ListNode(2); @@ -72,20 +72,20 @@ public class linked_list n3.next = n4; Console.WriteLine($"初始化的链表为{n0}"); - // 插入结点 + // 插入节点 insert(n0, new ListNode(0)); - Console.WriteLine($"插入结点后的链表为{n0}"); + Console.WriteLine($"插入节点后的链表为{n0}"); - // 删除结点 + // 删除节点 remove(n0); - Console.WriteLine($"删除结点后的链表为{n0}"); + Console.WriteLine($"删除节点后的链表为{n0}"); - // 访问结点 + // 访问节点 ListNode? node = access(n0, 3); - Console.WriteLine($"链表中索引 3 处的结点的值 = {node?.val}"); + Console.WriteLine($"链表中索引 3 处的节点的值 = {node?.val}"); - // 查找结点 + // 查找节点 int index = find(n0, 2); - Console.WriteLine($"链表中值为 2 的结点的索引 = {index}"); + Console.WriteLine($"链表中值为 2 的节点的索引 = {index}"); } } diff --git a/codes/csharp/chapter_heap/my_heap.cs b/codes/csharp/chapter_heap/my_heap.cs index 5321c92e..3fb7c4fe 100644 --- a/codes/csharp/chapter_heap/my_heap.cs +++ b/codes/csharp/chapter_heap/my_heap.cs @@ -26,7 +26,7 @@ class MaxHeap { // 将列表元素原封不动添加进堆 maxHeap = new List(nums); - // 堆化除叶结点以外的其他所有结点 + // 堆化除叶节点以外的其他所有节点 var size = parent(this.size() - 1); for (int i = size; i >= 0; i--) { @@ -34,19 +34,19 @@ class MaxHeap } } - /* 获取左子结点索引 */ + /* 获取左子节点索引 */ int left(int i) { return 2 * i + 1; } - /* 获取右子结点索引 */ + /* 获取右子节点索引 */ int right(int i) { return 2 * i + 2; } - /* 获取父结点索引 */ + /* 获取父节点索引 */ int parent(int i) { return (i - 1) / 2; // 向下整除 @@ -61,7 +61,7 @@ class MaxHeap /* 元素入堆 */ public void push(int val) { - // 添加结点 + // 添加节点 maxHeap.Add(val); // 从底至顶堆化 siftUp(size() - 1); @@ -79,17 +79,17 @@ class MaxHeap return size() == 0; } - /* 从结点 i 开始,从底至顶堆化 */ + /* 从节点 i 开始,从底至顶堆化 */ void siftUp(int i) { while (true) { - // 获取结点 i 的父结点 + // 获取节点 i 的父节点 int p = parent(i); - // 若“越过根结点”或“结点无需修复”,则结束堆化 + // 若“越过根节点”或“节点无需修复”,则结束堆化 if (p < 0 || maxHeap[i] <= maxHeap[p]) break; - // 交换两结点 + // 交换两节点 swap(i, p); // 循环向上堆化 i = p; @@ -102,9 +102,9 @@ class MaxHeap // 判空处理 if (isEmpty()) throw new IndexOutOfRangeException(); - // 交换根结点与最右叶结点(即交换首元素与尾元素) + // 交换根节点与最右叶节点(即交换首元素与尾元素) swap(0, size() - 1); - // 删除结点 + // 删除节点 int val = maxHeap.Last(); maxHeap.RemoveAt(size() - 1); // 从顶至底堆化 @@ -113,20 +113,20 @@ class MaxHeap return val; } - /* 从结点 i 开始,从顶至底堆化 */ + /* 从节点 i 开始,从顶至底堆化 */ void siftDown(int i) { while (true) { - // 判断结点 i, l, r 中值最大的结点,记为 ma + // 判断节点 i, l, r 中值最大的节点,记为 ma int l = left(i), r = right(i), ma = i; if (l < size() && maxHeap[l] > maxHeap[ma]) ma = l; if (r < size() && maxHeap[r] > maxHeap[ma]) ma = r; - // 若“结点 i 最大”或“越过叶结点”,则结束堆化 + // 若“节点 i 最大”或“越过叶节点”,则结束堆化 if (ma == i) break; - // 交换两结点 + // 交换两节点 swap(i, ma); // 循环向下堆化 i = ma; diff --git a/codes/csharp/chapter_searching/hashing_search.cs b/codes/csharp/chapter_searching/hashing_search.cs index 1986ef86..c0f7eb57 100644 --- a/codes/csharp/chapter_searching/hashing_search.cs +++ b/codes/csharp/chapter_searching/hashing_search.cs @@ -23,7 +23,7 @@ public class hashing_search static ListNode? hashingSearchLinkedList(Dictionary map, int target) { - // 哈希表的 key: 目标结点值,value: 结点对象 + // 哈希表的 key: 目标节点值,value: 节点对象 // 若哈希表中无此 key ,返回 null return map.GetValueOrDefault(target); } @@ -50,10 +50,10 @@ public class hashing_search Dictionary map1 = new(); while (head != null) { - map1[head.val] = head; // key: 结点值,value: 结点 + map1[head.val] = head; // key: 节点值,value: 节点 head = head.next; } ListNode? node = hashingSearchLinkedList(map1, target); - Console.WriteLine("目标结点值 3 的对应结点对象为 " + node); + Console.WriteLine("目标节点值 3 的对应节点对象为 " + node); } } diff --git a/codes/csharp/chapter_searching/linear_search.cs b/codes/csharp/chapter_searching/linear_search.cs index 3123de85..0d99287b 100644 --- a/codes/csharp/chapter_searching/linear_search.cs +++ b/codes/csharp/chapter_searching/linear_search.cs @@ -31,12 +31,12 @@ public class linear_search // 遍历链表 while (head != null) { - // 找到目标结点,返回之 + // 找到目标节点,返回之 if (head.val == target) return head; head = head.next; } - // 未找到目标结点,返回 null + // 未找到目标节点,返回 null return null; } @@ -53,6 +53,6 @@ public class linear_search /* 在链表中执行线性查找 */ ListNode head = ListNode.ArrToLinkedList(nums); ListNode? node = linearSearchLinkedList(head, target); - Console.WriteLine("目标结点值 3 的对应结点对象为 " + node); + Console.WriteLine("目标节点值 3 的对应节点对象为 " + node); } } diff --git a/codes/csharp/chapter_stack_and_queue/linkedlist_deque.cs b/codes/csharp/chapter_stack_and_queue/linkedlist_deque.cs index 79e6d4b8..5badc7fa 100644 --- a/codes/csharp/chapter_stack_and_queue/linkedlist_deque.cs +++ b/codes/csharp/chapter_stack_and_queue/linkedlist_deque.cs @@ -8,12 +8,12 @@ using NUnit.Framework; namespace hello_algo.chapter_stack_and_queue { - /* 双向链表结点 */ + /* 双向链表节点 */ public class ListNode { - public int val; // 结点值 - public ListNode? next; // 后继结点引用(指针) - public ListNode? prev; // 前驱结点引用(指针) + public int val; // 节点值 + public ListNode? next; // 后继节点引用(指针) + public ListNode? prev; // 前驱节点引用(指针) public ListNode(int val) { @@ -26,7 +26,7 @@ namespace hello_algo.chapter_stack_and_queue /* 基于双向链表实现的双向队列 */ public class LinkedListDeque { - private ListNode? front, rear; // 头结点 front, 尾结点 rear + private ListNode? front, rear; // 头节点 front, 尾节点 rear private int queSize = 0; // 双向队列的长度 public LinkedListDeque() @@ -63,7 +63,7 @@ namespace hello_algo.chapter_stack_and_queue // 将 node 添加至链表头部 front.prev = node; node.next = front; - front = node; // 更新头结点 + front = node; // 更新头节点 } // 队尾入队操作 else @@ -71,7 +71,7 @@ namespace hello_algo.chapter_stack_and_queue // 将 node 添加至链表尾部 rear.next = node; node.prev = rear; - rear = node; // 更新尾结点 + rear = node; // 更新尾节点 } queSize++; // 更新队列长度 @@ -102,8 +102,8 @@ namespace hello_algo.chapter_stack_and_queue // 队首出队操作 if (isFront) { - val = front.val; // 暂存头结点值 - // 删除头结点 + val = front.val; // 暂存头节点值 + // 删除头节点 ListNode fNext = front.next; if (fNext != null) { @@ -111,13 +111,13 @@ namespace hello_algo.chapter_stack_and_queue front.next = null; } - front = fNext; // 更新头结点 + front = fNext; // 更新头节点 } // 队尾出队操作 else { - val = rear.val; // 暂存尾结点值 - // 删除尾结点 + val = rear.val; // 暂存尾节点值 + // 删除尾节点 ListNode rPrev = rear.prev; if (rPrev != null) { @@ -125,7 +125,7 @@ namespace hello_algo.chapter_stack_and_queue rear.prev = null; } - rear = rPrev; // 更新尾结点 + rear = rPrev; // 更新尾节点 } queSize--; // 更新队列长度 diff --git a/codes/csharp/chapter_stack_and_queue/linkedlist_queue.cs b/codes/csharp/chapter_stack_and_queue/linkedlist_queue.cs index 138d7fa8..088dd2ba 100644 --- a/codes/csharp/chapter_stack_and_queue/linkedlist_queue.cs +++ b/codes/csharp/chapter_stack_and_queue/linkedlist_queue.cs @@ -12,7 +12,7 @@ namespace hello_algo.chapter_stack_and_queue; /* 基于链表实现的队列 */ class LinkedListQueue { - private ListNode? front, rear; // 头结点 front ,尾结点 rear + private ListNode? front, rear; // 头节点 front ,尾节点 rear private int queSize = 0; public LinkedListQueue() @@ -36,14 +36,14 @@ class LinkedListQueue /* 入队 */ public void push(int num) { - // 尾结点后添加 num + // 尾节点后添加 num ListNode node = new ListNode(num); - // 如果队列为空,则令头、尾结点都指向该结点 + // 如果队列为空,则令头、尾节点都指向该节点 if (front == null) { front = node; rear = node; - // 如果队列不为空,则将该结点添加到尾结点后 + // 如果队列不为空,则将该节点添加到尾节点后 } else if (rear != null) { @@ -57,7 +57,7 @@ class LinkedListQueue public int pop() { int num = peek(); - // 删除头结点 + // 删除头节点 front = front?.next; queSize--; return num; diff --git a/codes/csharp/chapter_stack_and_queue/linkedlist_stack.cs b/codes/csharp/chapter_stack_and_queue/linkedlist_stack.cs index 905491a9..dc697ed1 100644 --- a/codes/csharp/chapter_stack_and_queue/linkedlist_stack.cs +++ b/codes/csharp/chapter_stack_and_queue/linkedlist_stack.cs @@ -12,7 +12,7 @@ namespace hello_algo.chapter_stack_and_queue; /* 基于链表实现的栈 */ class LinkedListStack { - private ListNode? stackPeek; // 将头结点作为栈顶 + private ListNode? stackPeek; // 将头节点作为栈顶 private int stkSize = 0; // 栈的长度 public LinkedListStack() diff --git a/codes/csharp/chapter_tree/avl_tree.cs b/codes/csharp/chapter_tree/avl_tree.cs index 776268b6..70d3282a 100644 --- a/codes/csharp/chapter_tree/avl_tree.cs +++ b/codes/csharp/chapter_tree/avl_tree.cs @@ -12,28 +12,28 @@ namespace hello_algo.chapter_tree; /* AVL 树 */ class AVLTree { - public TreeNode? root; // 根结点 + public TreeNode? root; // 根节点 - /* 获取结点高度 */ + /* 获取节点高度 */ public int height(TreeNode? node) { - // 空结点高度为 -1 ,叶结点高度为 0 + // 空节点高度为 -1 ,叶节点高度为 0 return node == null ? -1 : node.height; } - /* 更新结点高度 */ + /* 更新节点高度 */ private void updateHeight(TreeNode node) { - // 结点高度等于最高子树高度 + 1 + // 节点高度等于最高子树高度 + 1 node.height = Math.Max(height(node.left), height(node.right)) + 1; } /* 获取平衡因子 */ public int balanceFactor(TreeNode? node) { - // 空结点平衡因子为 0 + // 空节点平衡因子为 0 if (node == null) return 0; - // 结点平衡因子 = 左子树高度 - 右子树高度 + // 节点平衡因子 = 左子树高度 - 右子树高度 return height(node.left) - height(node.right); } @@ -45,10 +45,10 @@ class AVLTree // 以 child 为原点,将 node 向右旋转 child.right = node; node.left = grandChild; - // 更新结点高度 + // 更新节点高度 updateHeight(node); updateHeight(child); - // 返回旋转后子树的根结点 + // 返回旋转后子树的根节点 return child; } @@ -60,17 +60,17 @@ class AVLTree // 以 child 为原点,将 node 向左旋转 child.left = node; node.right = grandChild; - // 更新结点高度 + // 更新节点高度 updateHeight(node); updateHeight(child); - // 返回旋转后子树的根结点 + // 返回旋转后子树的根节点 return child; } /* 执行旋转操作,使该子树重新恢复平衡 */ TreeNode? rotate(TreeNode? node) { - // 获取结点 node 的平衡因子 + // 获取节点 node 的平衡因子 int balanceFactorInt = balanceFactor(node); // 左偏树 if (balanceFactorInt > 1) @@ -106,43 +106,43 @@ class AVLTree return node; } - /* 插入结点 */ + /* 插入节点 */ public TreeNode? insert(int val) { root = insertHelper(root, val); return root; } - /* 递归插入结点(辅助方法) */ + /* 递归插入节点(辅助方法) */ private TreeNode? insertHelper(TreeNode? node, int val) { if (node == null) return new TreeNode(val); - /* 1. 查找插入位置,并插入结点 */ + /* 1. 查找插入位置,并插入节点 */ if (val < node.val) node.left = insertHelper(node.left, val); else if (val > node.val) node.right = insertHelper(node.right, val); else - return node; // 重复结点不插入,直接返回 - updateHeight(node); // 更新结点高度 + return node; // 重复节点不插入,直接返回 + updateHeight(node); // 更新节点高度 /* 2. 执行旋转操作,使该子树重新恢复平衡 */ node = rotate(node); - // 返回子树的根结点 + // 返回子树的根节点 return node; } - /* 删除结点 */ + /* 删除节点 */ public TreeNode? remove(int val) { root = removeHelper(root, val); return root; } - /* 递归删除结点(辅助方法) */ + /* 递归删除节点(辅助方法) */ private TreeNode? removeHelper(TreeNode? node, int val) { if (node == null) return null; - /* 1. 查找结点,并删除之 */ + /* 1. 查找节点,并删除之 */ if (val < node.val) node.left = removeHelper(node.left, val); else if (val > node.val) @@ -152,33 +152,33 @@ class AVLTree if (node.left == null || node.right == null) { TreeNode? child = node.left != null ? node.left : node.right; - // 子结点数量 = 0 ,直接删除 node 并返回 + // 子节点数量 = 0 ,直接删除 node 并返回 if (child == null) return null; - // 子结点数量 = 1 ,直接删除 node + // 子节点数量 = 1 ,直接删除 node else node = child; } else { - // 子结点数量 = 2 ,则将中序遍历的下个结点删除,并用该结点替换当前结点 + // 子节点数量 = 2 ,则将中序遍历的下个节点删除,并用该节点替换当前节点 TreeNode? temp = getInOrderNext(node.right); node.right = removeHelper(node.right, temp.val); node.val = temp.val; } } - updateHeight(node); // 更新结点高度 + updateHeight(node); // 更新节点高度 /* 2. 执行旋转操作,使该子树重新恢复平衡 */ node = rotate(node); - // 返回子树的根结点 + // 返回子树的根节点 return node; } - /* 获取中序遍历中的下一个结点(仅适用于 root 有左子结点的情况) */ + /* 获取中序遍历中的下一个节点(仅适用于 root 有左子节点的情况) */ private TreeNode? getInOrderNext(TreeNode? node) { if (node == null) return node; - // 循环访问左子结点,直到叶结点时为最小结点,跳出 + // 循环访问左子节点,直到叶节点时为最小节点,跳出 while (node.left != null) { node = node.left; @@ -186,24 +186,24 @@ class AVLTree return node; } - /* 查找结点 */ + /* 查找节点 */ public TreeNode? search(int val) { TreeNode? cur = root; - // 循环查找,越过叶结点后跳出 + // 循环查找,越过叶节点后跳出 while (cur != null) { - // 目标结点在 cur 的右子树中 + // 目标节点在 cur 的右子树中 if (cur.val < val) cur = cur.right; - // 目标结点在 cur 的左子树中 + // 目标节点在 cur 的左子树中 else if (cur.val > val) cur = cur.left; - // 找到目标结点,跳出循环 + // 找到目标节点,跳出循环 else break; } - // 返回目标结点 + // 返回目标节点 return cur; } } @@ -213,14 +213,14 @@ public class avl_tree static void testInsert(AVLTree tree, int val) { tree.insert(val); - Console.WriteLine("\n插入结点 " + val + " 后,AVL 树为"); + Console.WriteLine("\n插入节点 " + val + " 后,AVL 树为"); PrintUtil.PrintTree(tree.root); } static void testRemove(AVLTree tree, int val) { tree.remove(val); - Console.WriteLine("\n删除结点 " + val + " 后,AVL 树为"); + Console.WriteLine("\n删除节点 " + val + " 后,AVL 树为"); PrintUtil.PrintTree(tree.root); } @@ -230,8 +230,8 @@ public class avl_tree /* 初始化空 AVL 树 */ AVLTree avlTree = new AVLTree(); - /* 插入结点 */ - // 请关注插入结点后,AVL 树是如何保持平衡的 + /* 插入节点 */ + // 请关注插入节点后,AVL 树是如何保持平衡的 testInsert(avlTree, 1); testInsert(avlTree, 2); testInsert(avlTree, 3); @@ -243,17 +243,17 @@ public class avl_tree testInsert(avlTree, 10); testInsert(avlTree, 6); - /* 插入重复结点 */ + /* 插入重复节点 */ testInsert(avlTree, 7); - /* 删除结点 */ - // 请关注删除结点后,AVL 树是如何保持平衡的 - testRemove(avlTree, 8); // 删除度为 0 的结点 - testRemove(avlTree, 5); // 删除度为 1 的结点 - testRemove(avlTree, 4); // 删除度为 2 的结点 + /* 删除节点 */ + // 请关注删除节点后,AVL 树是如何保持平衡的 + testRemove(avlTree, 8); // 删除度为 0 的节点 + testRemove(avlTree, 5); // 删除度为 1 的节点 + testRemove(avlTree, 4); // 删除度为 2 的节点 - /* 查询结点 */ + /* 查询节点 */ TreeNode? node = avlTree.search(7); - Console.WriteLine("\n查找到的结点对象为 " + node + ",结点值 = " + node?.val); + Console.WriteLine("\n查找到的节点对象为 " + node + ",节点值 = " + node?.val); } } diff --git a/codes/csharp/chapter_tree/binary_search_tree.cs b/codes/csharp/chapter_tree/binary_search_tree.cs index e37a0ea0..b4eae044 100644 --- a/codes/csharp/chapter_tree/binary_search_tree.cs +++ b/codes/csharp/chapter_tree/binary_search_tree.cs @@ -19,7 +19,7 @@ class BinarySearchTree root = buildTree(nums, 0, nums.Length - 1); // 构建二叉搜索树 } - /* 获取二叉树根结点 */ + /* 获取二叉树根节点 */ public TreeNode? getRoot() { return root; @@ -29,7 +29,7 @@ class BinarySearchTree public TreeNode? buildTree(int[] nums, int i, int j) { if (i > j) return null; - // 将数组中间结点作为根结点 + // 将数组中间节点作为根节点 int mid = (i + j) / 2; TreeNode root = new TreeNode(nums[mid]); // 递归建立左子树和右子树 @@ -38,34 +38,34 @@ class BinarySearchTree return root; } - /* 查找结点 */ + /* 查找节点 */ public TreeNode? search(int num) { TreeNode? cur = root; - // 循环查找,越过叶结点后跳出 + // 循环查找,越过叶节点后跳出 while (cur != null) { - // 目标结点在 cur 的右子树中 + // 目标节点在 cur 的右子树中 if (cur.val < num) cur = cur.right; - // 目标结点在 cur 的左子树中 + // 目标节点在 cur 的左子树中 else if (cur.val > num) cur = cur.left; - // 找到目标结点,跳出循环 + // 找到目标节点,跳出循环 else break; } - // 返回目标结点 + // 返回目标节点 return cur; } - /* 插入结点 */ + /* 插入节点 */ public 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 的右子树中 @@ -74,7 +74,7 @@ class BinarySearchTree else cur = cur.left; } - // 插入结点 val + // 插入节点 val TreeNode node = new TreeNode(num); if (pre != null) { @@ -85,31 +85,31 @@ class BinarySearchTree } - /* 删除结点 */ + /* 删除节点 */ public 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 的右子树中 + // 待删除节点在 cur 的右子树中 if (cur.val < num) cur = cur.right; - // 待删除结点在 cur 的左子树中 + // 待删除节点在 cur 的左子树中 else cur = cur.left; } - // 若无待删除结点,则直接返回 + // 若无待删除节点,则直接返回 if (cur == null || pre == null) return null; - // 子结点数量 = 0 or 1 + // 子节点数量 = 0 or 1 if (cur.left == null || cur.right == null) { - // 当子结点数量 = 0 / 1 时, child = null / 该子结点 + // 当子节点数量 = 0 / 1 时, child = null / 该子节点 TreeNode? child = cur.left != null ? cur.left : cur.right; - // 删除结点 cur + // 删除节点 cur if (pre.left == cur) { pre.left = child; @@ -119,15 +119,15 @@ class BinarySearchTree pre.right = child; } } - // 子结点数量 = 2 + // 子节点数量 = 2 else { - // 获取中序遍历中 cur 的下一个结点 + // 获取中序遍历中 cur 的下一个节点 TreeNode? nex = getInOrderNext(cur.right); if (nex != null) { int tmp = nex.val; - // 递归删除结点 nex + // 递归删除节点 nex remove(nex.val); // 将 nex 的值复制给 cur cur.val = tmp; @@ -136,11 +136,11 @@ class BinarySearchTree return cur; } - /* 获取中序遍历中的下一个结点(仅适用于 root 有左子结点的情况) */ + /* 获取中序遍历中的下一个节点(仅适用于 root 有左子节点的情况) */ private TreeNode? getInOrderNext(TreeNode? root) { if (root == null) return root; - // 循环访问左子结点,直到叶结点时为最小结点,跳出 + // 循环访问左子节点,直到叶节点时为最小节点,跳出 while (root.left != null) { root = root.left; @@ -160,24 +160,24 @@ public class binary_search_tree Console.WriteLine("\n初始化的二叉树为\n"); PrintUtil.PrintTree(bst.getRoot()); - /* 查找结点 */ + /* 查找节点 */ TreeNode? node = bst.search(7); - Console.WriteLine("\n查找到的结点对象为 " + node + ",结点值 = " + node.val); + Console.WriteLine("\n查找到的节点对象为 " + node + ",节点值 = " + node.val); - /* 插入结点 */ + /* 插入节点 */ node = bst.insert(16); - Console.WriteLine("\n插入结点 16 后,二叉树为\n"); + Console.WriteLine("\n插入节点 16 后,二叉树为\n"); PrintUtil.PrintTree(bst.getRoot()); - /* 删除结点 */ + /* 删除节点 */ bst.remove(1); - Console.WriteLine("\n删除结点 1 后,二叉树为\n"); + Console.WriteLine("\n删除节点 1 后,二叉树为\n"); PrintUtil.PrintTree(bst.getRoot()); bst.remove(2); - Console.WriteLine("\n删除结点 2 后,二叉树为\n"); + Console.WriteLine("\n删除节点 2 后,二叉树为\n"); PrintUtil.PrintTree(bst.getRoot()); bst.remove(4); - Console.WriteLine("\n删除结点 4 后,二叉树为\n"); + Console.WriteLine("\n删除节点 4 后,二叉树为\n"); PrintUtil.PrintTree(bst.getRoot()); } } diff --git a/codes/csharp/chapter_tree/binary_tree.cs b/codes/csharp/chapter_tree/binary_tree.cs index 1f77929f..c1a0292e 100644 --- a/codes/csharp/chapter_tree/binary_tree.cs +++ b/codes/csharp/chapter_tree/binary_tree.cs @@ -15,7 +15,7 @@ public class binary_tree public void Test() { /* 初始化二叉树 */ - // 初始化结点 + // 初始化节点 TreeNode n1 = new TreeNode(1); TreeNode n2 = new TreeNode(2); TreeNode n3 = new TreeNode(3); @@ -29,16 +29,16 @@ public class binary_tree Console.WriteLine("\n初始化二叉树\n"); PrintUtil.PrintTree(n1); - /* 插入与删除结点 */ + /* 插入与删除节点 */ TreeNode P = new TreeNode(0); - // 在 n1 -> n2 中间插入结点 P + // 在 n1 -> n2 中间插入节点 P n1.left = P; P.left = n2; - Console.WriteLine("\n插入结点 P 后\n"); + Console.WriteLine("\n插入节点 P 后\n"); PrintUtil.PrintTree(n1); - // 删除结点 P + // 删除节点 P n1.left = n2; - Console.WriteLine("\n删除结点 P 后\n"); + Console.WriteLine("\n删除节点 P 后\n"); PrintUtil.PrintTree(n1); } } diff --git a/codes/csharp/chapter_tree/binary_tree_bfs.cs b/codes/csharp/chapter_tree/binary_tree_bfs.cs index 2edd07ee..a98e6e77 100644 --- a/codes/csharp/chapter_tree/binary_tree_bfs.cs +++ b/codes/csharp/chapter_tree/binary_tree_bfs.cs @@ -15,7 +15,7 @@ public class binary_tree_bfs /* 层序遍历 */ public List levelOrder(TreeNode root) { - // 初始化队列,加入根结点 + // 初始化队列,加入根节点 Queue queue = new(); queue.Enqueue(root); // 初始化一个列表,用于保存遍历序列 @@ -23,11 +23,11 @@ public class binary_tree_bfs while (queue.Count != 0) { TreeNode node = queue.Dequeue(); // 队列出队 - list.Add(node.val); // 保存结点值 + list.Add(node.val); // 保存节点值 if (node.left != null) - queue.Enqueue(node.left); // 左子结点入队 + queue.Enqueue(node.left); // 左子节点入队 if (node.right != null) - queue.Enqueue(node.right); // 右子结点入队 + queue.Enqueue(node.right); // 右子节点入队 } return list; } @@ -42,6 +42,6 @@ public class binary_tree_bfs PrintUtil.PrintTree(root); List list = levelOrder(root); - Console.WriteLine("\n层序遍历的结点打印序列 = " + string.Join(",", list.ToArray())); + Console.WriteLine("\n层序遍历的节点打印序列 = " + string.Join(",", list.ToArray())); } } diff --git a/codes/csharp/chapter_tree/binary_tree_dfs.cs b/codes/csharp/chapter_tree/binary_tree_dfs.cs index e142fd58..27a847b7 100644 --- a/codes/csharp/chapter_tree/binary_tree_dfs.cs +++ b/codes/csharp/chapter_tree/binary_tree_dfs.cs @@ -17,7 +17,7 @@ public class binary_tree_dfs void preOrder(TreeNode? root) { if (root == null) return; - // 访问优先级:根结点 -> 左子树 -> 右子树 + // 访问优先级:根节点 -> 左子树 -> 右子树 list.Add(root.val); preOrder(root.left); preOrder(root.right); @@ -27,7 +27,7 @@ public class binary_tree_dfs void inOrder(TreeNode? root) { if (root == null) return; - // 访问优先级:左子树 -> 根结点 -> 右子树 + // 访问优先级:左子树 -> 根节点 -> 右子树 inOrder(root.left); list.Add(root.val); inOrder(root.right); @@ -37,7 +37,7 @@ public class binary_tree_dfs void postOrder(TreeNode? root) { if (root == null) return; - // 访问优先级:左子树 -> 右子树 -> 根结点 + // 访问优先级:左子树 -> 右子树 -> 根节点 postOrder(root.left); postOrder(root.right); list.Add(root.val); @@ -54,14 +54,14 @@ public class binary_tree_dfs list.Clear(); preOrder(root); - Console.WriteLine("\n前序遍历的结点打印序列 = " + string.Join(",", list.ToArray())); + Console.WriteLine("\n前序遍历的节点打印序列 = " + string.Join(",", list.ToArray())); list.Clear(); inOrder(root); - Console.WriteLine("\n中序遍历的结点打印序列 = " + string.Join(",", list.ToArray())); + Console.WriteLine("\n中序遍历的节点打印序列 = " + string.Join(",", list.ToArray())); list.Clear(); postOrder(root); - Console.WriteLine("\n后序遍历的结点打印序列 = " + string.Join(",", list.ToArray())); + Console.WriteLine("\n后序遍历的节点打印序列 = " + string.Join(",", list.ToArray())); } } diff --git a/codes/csharp/include/TreeNode.cs b/codes/csharp/include/TreeNode.cs index 905abc32..330c7711 100644 --- a/codes/csharp/include/TreeNode.cs +++ b/codes/csharp/include/TreeNode.cs @@ -8,10 +8,10 @@ namespace hello_algo.include; public class TreeNode { - public int val; // 结点值 - public int height; // 结点高度 - public TreeNode? left; // 左子结点引用 - public TreeNode? right; // 右子结点引用 + public int val; // 节点值 + public int height; // 节点高度 + public TreeNode? left; // 左子节点引用 + public TreeNode? right; // 右子节点引用 public TreeNode(int x) { diff --git a/codes/dart/chapter_array_and_linkedlist/linked_list.dart b/codes/dart/chapter_array_and_linkedlist/linked_list.dart index 2edd86da..94553762 100644 --- a/codes/dart/chapter_array_and_linkedlist/linked_list.dart +++ b/codes/dart/chapter_array_and_linkedlist/linked_list.dart @@ -9,14 +9,14 @@ import '../utils/print_util.dart'; class LinkedList { - /* 在链表的结点 n0 之后插入结点 P */ + /* 在链表的节点 n0 之后插入节点 P */ void insert(ListNode n0, ListNode P) { ListNode? n1 = n0.next; P.next = n1; n0.next = P; } - /* 删除链表的结点 n0 之后的首个结点 */ + /* 删除链表的节点 n0 之后的首个节点 */ void remove(ListNode n0) { if (n0.next == null) return; ListNode P = n0.next!; @@ -24,7 +24,7 @@ class LinkedList { n0.next = n1; } - /* 访问链表中索引为 index 的结点 */ + /* 访问链表中索引为 index 的节点 */ ListNode? access(ListNode? head, int index) { for (var i = 0; i < index; i++) { if (head == null) return null; @@ -33,7 +33,7 @@ class LinkedList { return head; } - /* 在链表中查找值为 target 的首个结点 */ + /* 在链表中查找值为 target 的首个节点 */ int find(ListNode? head, int target) { int index = 0; while (head != null) { @@ -50,7 +50,7 @@ class LinkedList { /* Driver Code */ int main() { // 初始化链表 - //初始化各个结点 + //初始化各个节点 ListNode n0 = ListNode(1); ListNode n1 = ListNode(3); ListNode n2 = ListNode(2); @@ -65,21 +65,21 @@ int main() { print('初始化的链表为'); printLinkedList(n0); - /* 插入结点 */ + /* 插入节点 */ LinkedList().insert(n0, ListNode(0)); printLinkedList(n0); - /* 删除结点 */ + /* 删除节点 */ LinkedList().remove(n0); printLinkedList(n0); - /* 访问结点 */ + /* 访问节点 */ ListNode? node = LinkedList().access(n0, 3); - print('链表中索引 3 处的结点的值 = ${node!.val}'); + print('链表中索引 3 处的节点的值 = ${node!.val}'); - /* 查找结点 */ + /* 查找节点 */ int index = LinkedList().find(n0, 2); - print('链表中值为 2 的结点的索引 = $index'); + print('链表中值为 2 的节点的索引 = $index'); return 0; } diff --git a/codes/dart/chapter_stack_and_queue/linkedlist_deque.dart b/codes/dart/chapter_stack_and_queue/linkedlist_deque.dart index 146535c8..7c81f0a0 100644 --- a/codes/dart/chapter_stack_and_queue/linkedlist_deque.dart +++ b/codes/dart/chapter_stack_and_queue/linkedlist_deque.dart @@ -4,19 +4,19 @@ * Author: liuyuxin (gvenusleo@gmail.com) */ -/* 双向链表结点 */ +/* 双向链表节点 */ class ListNode { - int val; // 结点值 - ListNode? next; // 后继结点引用(指针) - ListNode? prev; // 前驱结点引用(指针) + int val; // 节点值 + ListNode? next; // 后继节点引用(指针) + ListNode? prev; // 前驱节点引用(指针) ListNode(this.val, {this.next, this.prev}); } /* 基于双向链表实现的双向对列 */ class LinkedListDeque { - late ListNode? _front; // 头结点 _front - late ListNode? _rear; // 尾结点 _rear + late ListNode? _front; // 头节点 _front + late ListNode? _rear; // 尾节点 _rear int _queSize = 0; // 双向队列的长度 LinkedListDeque() { @@ -45,13 +45,13 @@ class LinkedListDeque { // 将 node 添加至链表头部 _front!.prev = node; node.next = _front; - _front = node; // 更新头结点 + _front = node; // 更新头节点 } else { // 队尾入队操作 // 将 node 添加至链表尾部 _rear!.next = node; node.prev = _rear; - _rear = node; // 更新尾结点 + _rear = node; // 更新尾节点 } _queSize++; // 更新队列长度 } @@ -75,24 +75,24 @@ class LinkedListDeque { final int val; if (isFront) { // 队首出队操作 - val = _front!.val; // 暂存头结点值 - // 删除头结点 + val = _front!.val; // 暂存头节点值 + // 删除头节点 ListNode? fNext = _front!.next; if (fNext != null) { fNext.prev = null; _front!.next = null; } - _front = fNext; // 更新头结点 + _front = fNext; // 更新头节点 } else { // 队尾出队操作 - val = _rear!.val; // 暂存尾结点值 - // 删除尾结点 + val = _rear!.val; // 暂存尾节点值 + // 删除尾节点 ListNode? rPrev = _rear!.prev; if (rPrev != null) { rPrev.next = null; _rear!.prev = null; } - _rear = rPrev; // 更新尾结点 + _rear = rPrev; // 更新尾节点 } _queSize--; // 更新队列长度 return val; diff --git a/codes/dart/chapter_stack_and_queue/linkedlist_queue.dart b/codes/dart/chapter_stack_and_queue/linkedlist_queue.dart index a143fc89..4ee392f6 100644 --- a/codes/dart/chapter_stack_and_queue/linkedlist_queue.dart +++ b/codes/dart/chapter_stack_and_queue/linkedlist_queue.dart @@ -8,8 +8,8 @@ import '../utils/list_node.dart'; /* 基于链表实现的队列 */ class LinkedListQueue { - ListNode? _front; // 头结点 _front - ListNode? _rear; // 尾结点 _rear + ListNode? _front; // 头节点 _front + ListNode? _rear; // 尾节点 _rear int _queSize = 0; // 队列长度 LinkedListQueue() { @@ -29,14 +29,14 @@ class LinkedListQueue { /* 入队 */ void push(int num) { - // 尾结点后添加 num + // 尾节点后添加 num final node = ListNode(num); - // 如果队列为空,则令头、尾结点都指向该结点 + // 如果队列为空,则令头、尾节点都指向该节点 if (_front == null) { _front = node; _rear = node; } else { - // 如果队列不为空,则将该结点添加到尾结点后 + // 如果队列不为空,则将该节点添加到尾节点后 _rear!.next = node; _rear = node; } @@ -46,7 +46,7 @@ class LinkedListQueue { /* 出队 */ int pop() { final int num = peek(); - // 删除头结点 + // 删除头节点 _front = _front!.next; _queSize--; return num; diff --git a/codes/dart/chapter_stack_and_queue/linkedlist_stack.dart b/codes/dart/chapter_stack_and_queue/linkedlist_stack.dart index 1a88b2b0..a1dbd46b 100644 --- a/codes/dart/chapter_stack_and_queue/linkedlist_stack.dart +++ b/codes/dart/chapter_stack_and_queue/linkedlist_stack.dart @@ -8,7 +8,7 @@ import '../utils/list_node.dart'; /* 基于链表类实现的栈 */ class LinkedListStack { - ListNode? _stackPeek; // 将头结点作为栈顶 + ListNode? _stackPeek; // 将头节点作为栈顶 int _stkSize = 0; // 栈的长度 LinkedListStack() { diff --git a/codes/dart/chapter_tree/avl_tree.dart b/codes/dart/chapter_tree/avl_tree.dart index 5e42b8ec..39e7bcb2 100644 --- a/codes/dart/chapter_tree/avl_tree.dart +++ b/codes/dart/chapter_tree/avl_tree.dart @@ -16,22 +16,22 @@ class AVLTree { root = null; } - /* 获取结点高度 */ + /* 获取节点高度 */ int height(TreeNode? node) { return node == null ? -1 : node.height; } - /* 更新结点高度 */ + /* 更新节点高度 */ void updateHeight(TreeNode? node) { - // 结点高度等于最高子树高度 + 1 + // 节点高度等于最高子树高度 + 1 node!.height = max(height(node.left), height(node.right)) + 1; } /* 获取平衡因子 */ int balanceFactor(TreeNode? node) { - // 空结点平衡因子为 0 + // 空节点平衡因子为 0 if (node == null) return 0; - // 结点平衡因子 = 左子树高度 - 右子树高度 + // 节点平衡因子 = 左子树高度 - 右子树高度 return height(node.left) - height(node.right); } @@ -42,10 +42,10 @@ class AVLTree { // 以 child 为原点,将 node 向右旋转 child.right = node; node.left = grandChild; - // 更新结点高度 + // 更新节点高度 updateHeight(node); updateHeight(child); - // 返回旋转后子树的根结点 + // 返回旋转后子树的根节点 return child; } @@ -56,16 +56,16 @@ class AVLTree { // 以 child 为原点,将 node 向左旋转 child.left = node; node.right = grandChild; - // 更新结点高度 + // 更新节点高度 updateHeight(node); updateHeight(child); - // 返回旋转后子树的根结点 + // 返回旋转后子树的根节点 return child; } /* 执行旋转操作,使该子树重新恢复平衡 */ TreeNode? rotate(TreeNode? node) { - // 获取结点 node 的平衡因子 + // 获取节点 node 的平衡因子 int factor = balanceFactor(node); // 左偏树 if (factor > 1) { @@ -93,39 +93,39 @@ class AVLTree { return node; } - /* 插入结点 */ + /* 插入节点 */ TreeNode? insert(int val) { root = insertHelper(root, val); return root; } - /* 递归插入结点(辅助方法) */ + /* 递归插入节点(辅助方法) */ TreeNode? insertHelper(TreeNode? node, int val) { if (node == null) return TreeNode(val); - /* 1. 查找插入位置,并插入结点 */ + /* 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); // 更新结点高度 + return node; // 重复节点不插入,直接返回 + updateHeight(node); // 更新节点高度 /* 2. 执行旋转操作,使该子树重新恢复平衡 */ node = rotate(node); - // 返回子树的根结点 + // 返回子树的根节点 return node; } - /* 删除结点 */ + /* 删除节点 */ TreeNode? remove(int val) { root = removeHelper(root, val); return root; } - /* 递归删除结点(辅助方法) */ + /* 递归删除节点(辅助方法) */ TreeNode? removeHelper(TreeNode? node, int val) { if (node == null) return null; - /* 1. 查找结点,并删除之 */ + /* 1. 查找节点,并删除之 */ if (val < node.val) node.left = removeHelper(node.left, val); else if (val > node.val) @@ -133,48 +133,48 @@ class AVLTree { else { if (node.left == null || node.right == null) { TreeNode? child = node.left ?? node.right; - // 子结点数量 = 0 ,直接删除 node 并返回 + // 子节点数量 = 0 ,直接删除 node 并返回 if (child == null) return null; - // 子结点数量 = 1 ,直接删除 node + // 子节点数量 = 1 ,直接删除 node else node = child; } else { - // 子结点数量 = 2 ,则将中序遍历的下个结点删除,并用该结点替换当前结点 + // 子节点数量 = 2 ,则将中序遍历的下个节点删除,并用该节点替换当前节点 TreeNode? temp = getInOrderNext(node.right); node.right = removeHelper(node.right, temp!.val); node.val = temp.val; } } - updateHeight(node); // 更新结点高度 + updateHeight(node); // 更新节点高度 /* 2. 执行旋转操作,使该子树重新恢复平衡 */ node = rotate(node); - // 返回子树的根结点 + // 返回子树的根节点 return node; } - /* 获取中序遍历中的下一个结点(仅适用于 root 有左子结点的情况) */ + /* 获取中序遍历中的下一个节点(仅适用于 root 有左子节点的情况) */ TreeNode? getInOrderNext(TreeNode? node) { if (node == null) return node; - // 循环访问左子结点,直到叶结点时为最小结点,跳出 + // 循环访问左子节点,直到叶节点时为最小节点,跳出 while (node!.left != null) { node = node.left; } return node; } - /* 查找结点 */ + /* 查找节点 */ TreeNode? search(int val) { TreeNode? cur = root; - // 循环查找,越过叶结点后跳出 + // 循环查找,越过叶节点后跳出 while (cur != null) { - // 目标结点在 cur 的右子树中 + // 目标节点在 cur 的右子树中 if (val < cur.val) cur = cur.left; - // 目标结点在 cur 的左子树中 + // 目标节点在 cur 的左子树中 else if (val > cur.val) cur = cur.right; - // 目标结点与当前结点相等 + // 目标节点与当前节点相等 else break; } @@ -184,13 +184,13 @@ class AVLTree { void testInsert(AVLTree tree, int val) { tree.insert(val); - print("\n插入结点 $val 后,AVL 树为"); + print("\n插入节点 $val 后,AVL 树为"); printTree(tree.root); } void testRemove(AVLTree tree, int val) { tree.remove(val); - print("\n删除结点 $val 后,AVL 树为"); + print("\n删除节点 $val 后,AVL 树为"); printTree(tree.root); } @@ -198,8 +198,8 @@ void testRemove(AVLTree tree, int val) { void main() { /* 初始化空 AVL 树 */ AVLTree avlTree = AVLTree(); - /* 插入结点 */ - // 请关注插入结点后,AVL 树是如何保持平衡的 + /* 插入节点 */ + // 请关注插入节点后,AVL 树是如何保持平衡的 testInsert(avlTree, 1); testInsert(avlTree, 2); testInsert(avlTree, 3); @@ -211,16 +211,16 @@ void main() { testInsert(avlTree, 10); testInsert(avlTree, 6); - /* 插入重复结点 */ + /* 插入重复节点 */ testInsert(avlTree, 7); - /* 删除结点 */ - // 请关注删除结点后,AVL 树是如何保持平衡的 - testRemove(avlTree, 8); // 删除度为 0 的结点 - testRemove(avlTree, 5); // 删除度为 1 的结点 - testRemove(avlTree, 4); // 删除度为 2 的结点 + /* 删除节点 */ + // 请关注删除节点后,AVL 树是如何保持平衡的 + testRemove(avlTree, 8); // 删除度为 0 的节点 + testRemove(avlTree, 5); // 删除度为 1 的节点 + testRemove(avlTree, 4); // 删除度为 2 的节点 - /* 查询结点 */ + /* 查询节点 */ TreeNode? node = avlTree.search(7); - print("\n查找到的结点对象为 $node,结点值 = ${node!.val}"); + print("\n查找到的节点对象为 $node,节点值 = ${node!.val}"); } diff --git a/codes/dart/chapter_tree/binary_search_tree.dart b/codes/dart/chapter_tree/binary_search_tree.dart index 8efc4f09..a775085c 100644 --- a/codes/dart/chapter_tree/binary_search_tree.dart +++ b/codes/dart/chapter_tree/binary_search_tree.dart @@ -15,7 +15,7 @@ void binarySearchTree(List nums) { root = buildTree(nums, 0, nums.length - 1); // 构建二叉搜索树 } -/* 获取二叉树的根结点 */ +/* 获取二叉树的根节点 */ TreeNode? getRoot() { return root; } @@ -25,7 +25,7 @@ TreeNode? buildTree(List nums, int i, int j) { if (i > j) { return null; } - // 将数组中间结点作为根结点 + // 将数组中间节点作为根节点 int mid = (i + j) ~/ 2; TreeNode? root = TreeNode(nums[mid]); root.left = buildTree(nums, i, mid - 1); @@ -33,34 +33,34 @@ TreeNode? buildTree(List nums, int i, int j) { return root; } -/* 查找结点 */ +/* 查找节点 */ TreeNode? search(int num) { TreeNode? cur = root; - // 循环查找,越过叶结点后跳出 + // 循环查找,越过叶节点后跳出 while (cur != null) { - // 目标结点在 cur 的右子树中 + // 目标节点在 cur 的右子树中 if (cur.val < num) cur = cur.right; - // 目标结点在 cur 的左子树中 + // 目标节点在 cur 的左子树中 else if (cur.val > num) cur = cur.left; - // 找到目标结点,跳出循环 + // 找到目标节点,跳出循环 else break; } - // 返回目标结点 + // 返回目标节点 return cur; } -/* 插入结点 */ +/* 插入节点 */ TreeNode? insert(int num) { // 若树为空,直接提前返回 if (root == null) return null; TreeNode? cur = root; TreeNode? pre = null; - // 循环查找,越过叶结点后跳出 + // 循环查找,越过叶节点后跳出 while (cur != null) { - // 找到重复结点,直接返回 + // 找到重复节点,直接返回 if (cur.val == num) return null; pre = cur; // 插入位置在 cur 的右子树中 @@ -70,7 +70,7 @@ TreeNode? insert(int num) { else cur = cur.left; } - // 插入结点 val + // 插入节点 val TreeNode? node = TreeNode(num); if (pre!.val < num) pre.right = node; @@ -79,42 +79,42 @@ TreeNode? insert(int num) { return node; } -/* 删除结点 */ +/* 删除节点 */ TreeNode? remove(int num) { // 若树为空,直接提前返回 if (root == null) return null; TreeNode? cur = root; TreeNode? pre = null; - // 循环查找,越过叶结点后跳出 + // 循环查找,越过叶节点后跳出 while (cur != null) { - // 找到待删除结点,跳出循环 + // 找到待删除节点,跳出循环 if (cur.val == num) break; pre = cur; - // 待删除结点在 cur 的右子树中 + // 待删除节点在 cur 的右子树中 if (cur.val < num) cur = cur.right; - // 待删除结点在 cur 的左子树中 + // 待删除节点在 cur 的左子树中 else cur = cur.left; } - // 若无待删除结点,直接返回 + // 若无待删除节点,直接返回 if (cur == null) return null; - // 子结点数量 = 0 or 1 + // 子节点数量 = 0 or 1 if (cur.left == null || cur.right == null) { - // 当子结点数量 = 0 / 1 时, child = null / 该子结点 + // 当子节点数量 = 0 / 1 时, child = null / 该子节点 TreeNode? child = cur.left ?? cur.right; - // 删除结点 cur + // 删除节点 cur if (pre!.left == cur) pre.left = child; else pre.right = child; } else { - // 子结点数量 = 2 - // 获取中序遍历中 cur 的下一个结点 + // 子节点数量 = 2 + // 获取中序遍历中 cur 的下一个节点 TreeNode? nex = getInOrderNext(cur.right); int tem = nex!.val; - // 递归删除结点 nex + // 递归删除节点 nex remove(nex.val); // 将 nex 的值复制给 cur cur.val = tem; @@ -122,10 +122,10 @@ TreeNode? remove(int num) { return cur; } -/* 获取中序遍历中的下一个结点(仅适用于 root 有左子结点的情况) */ +/* 获取中序遍历中的下一个节点(仅适用于 root 有左子节点的情况) */ TreeNode? getInOrderNext(TreeNode? root) { if (root == null) return null; - // 循环访问左子结点,直到叶结点时为最小结点,跳出 + // 循环访问左子节点,直到叶节点时为最小节点,跳出 while (root!.left != null) { root = root.left; } @@ -140,23 +140,23 @@ void main() { print("\n初始化的二叉树为\n"); printTree(getRoot()); - /* 查找结点 */ + /* 查找节点 */ TreeNode? node = search(7); - print("\n查找到的结点对象为 $node,结点值 = ${node?.val}"); + print("\n查找到的节点对象为 $node,节点值 = ${node?.val}"); - /* 插入结点 */ + /* 插入节点 */ node = insert(16); - print("\n插入结点 16 后,二叉树为\n"); + print("\n插入节点 16 后,二叉树为\n"); printTree(getRoot()); - /* 删除结点 */ + /* 删除节点 */ remove(1); - print("\n删除结点 1 后,二叉树为\n"); + print("\n删除节点 1 后,二叉树为\n"); printTree(getRoot()); remove(2); - print("\n删除结点 2 后,二叉树为\n"); + print("\n删除节点 2 后,二叉树为\n"); printTree(getRoot()); remove(4); - print("\n删除结点 4 后,二叉树为\n"); + print("\n删除节点 4 后,二叉树为\n"); printTree(getRoot()); } diff --git a/codes/dart/chapter_tree/binary_tree.dart b/codes/dart/chapter_tree/binary_tree.dart index 2cfc45a8..9b357703 100644 --- a/codes/dart/chapter_tree/binary_tree.dart +++ b/codes/dart/chapter_tree/binary_tree.dart @@ -9,7 +9,7 @@ import '../utils/tree_node.dart'; void main() { /* 初始化二叉树 */ - // 舒适化结点 + // 舒适化节点 TreeNode n1 = TreeNode(1); TreeNode n2 = TreeNode(2); TreeNode n3 = TreeNode(3); @@ -23,15 +23,15 @@ void main() { print("\n初始化二叉树\n"); printTree(n1); - /* 插入与删除结点 */ + /* 插入与删除节点 */ TreeNode p = TreeNode(0); - // 在 n1 -> n2 中间插入结点 p + // 在 n1 -> n2 中间插入节点 p n1.left = p; p.left = n2; - print("\n插入结点 P 后\n"); + print("\n插入节点 P 后\n"); printTree(n1); - // 删除结点 P + // 删除节点 P n1.left = n2; - print("\n删除结点 P 后\n"); + print("\n删除节点 P 后\n"); printTree(n1); } diff --git a/codes/dart/chapter_tree/binary_tree_bfs.dart b/codes/dart/chapter_tree/binary_tree_bfs.dart index 2d097dc3..21bb0fa2 100644 --- a/codes/dart/chapter_tree/binary_tree_bfs.dart +++ b/codes/dart/chapter_tree/binary_tree_bfs.dart @@ -10,16 +10,16 @@ import '../utils/tree_node.dart'; /* 层序遍历 */ List levelOrder(TreeNode? root) { - // 初始化队列,加入根结点 + // 初始化队列,加入根节点 Queue queue = Queue(); queue.add(root); // 初始化一个列表,用于保存遍历序列 List res = []; while (queue.isNotEmpty) { TreeNode? node = queue.removeFirst(); // 队列出队 - res.add(node!.val); // 保存结点值 - if (node.left != null) queue.add(node.left); // 左子结点入队 - if (node.right != null) queue.add(node.right); // 右子结点入队 + res.add(node!.val); // 保存节点值 + if (node.left != null) queue.add(node.left); // 左子节点入队 + if (node.right != null) queue.add(node.right); // 右子节点入队 } return res; } @@ -34,5 +34,5 @@ void main() { // 层序遍历 List res = levelOrder(root); - print("\n层序遍历的结点打印序列 = $res"); + print("\n层序遍历的节点打印序列 = $res"); } diff --git a/codes/dart/chapter_tree/binary_tree_dfs.dart b/codes/dart/chapter_tree/binary_tree_dfs.dart index 77c90fb8..a59eb76b 100644 --- a/codes/dart/chapter_tree/binary_tree_dfs.dart +++ b/codes/dart/chapter_tree/binary_tree_dfs.dart @@ -13,7 +13,7 @@ List list = []; /* 前序遍历 */ void preOrder(TreeNode? node) { if (node == null) return; - // 访问优先级:根结点 -> 左子树 -> 右子树 + // 访问优先级:根节点 -> 左子树 -> 右子树 list.add(node.val); preOrder(node.left); preOrder(node.right); @@ -22,7 +22,7 @@ void preOrder(TreeNode? node) { /* 中序遍历 */ void inOrder(TreeNode? node) { if (node == null) return; - // 访问优先级:左子树 -> 根结点 -> 右子树 + // 访问优先级:左子树 -> 根节点 -> 右子树 inOrder(node.left); list.add(node.val); inOrder(node.right); @@ -31,7 +31,7 @@ void inOrder(TreeNode? node) { /* 后序遍历 */ void postOrder(TreeNode? node) { if (node == null) return; - // 访问优先级:左子树 -> 右子树 -> 根结点 + // 访问优先级:左子树 -> 右子树 -> 根节点 postOrder(node.left); postOrder(node.right); list.add(node.val); @@ -48,15 +48,15 @@ void main() { /* 前序遍历 */ list.clear(); preOrder(root); - print("\n前序遍历的结点打印序列 = $list"); + print("\n前序遍历的节点打印序列 = $list"); /* 中序遍历 */ list.clear(); inOrder(root); - print("\n中序遍历的结点打印序列 = $list"); + print("\n中序遍历的节点打印序列 = $list"); /* 后序遍历 */ list.clear(); postOrder(root); - print("\n后序遍历的结点打印序列 = $list"); + print("\n后序遍历的节点打印序列 = $list"); } diff --git a/codes/dart/utils/tree_node.dart b/codes/dart/utils/tree_node.dart index 2cba680a..70c09321 100644 --- a/codes/dart/utils/tree_node.dart +++ b/codes/dart/utils/tree_node.dart @@ -7,10 +7,10 @@ import 'dart:collection'; class TreeNode { - int val; // 结点值 - int height; // 结点高度 - TreeNode? left; // 左子结点引用 - TreeNode? right; // 右子结点引用 + int val; // 节点值 + int height; // 节点高度 + TreeNode? left; // 左子节点引用 + TreeNode? right; // 右子节点引用 TreeNode(this.val, [this.height = 0, this.left, this.right]); } diff --git a/codes/go/chapter_array_and_linkedlist/linked_list.go b/codes/go/chapter_array_and_linkedlist/linked_list.go index 26a1d6c0..22391306 100644 --- a/codes/go/chapter_array_and_linkedlist/linked_list.go +++ b/codes/go/chapter_array_and_linkedlist/linked_list.go @@ -8,14 +8,14 @@ import ( . "github.com/krahets/hello-algo/pkg" ) -/* 在链表的结点 n0 之后插入结点 P */ +/* 在链表的节点 n0 之后插入节点 P */ func insertNode(n0 *ListNode, P *ListNode) { n1 := n0.Next P.Next = n1 n0.Next = P } -/* 删除链表的结点 n0 之后的首个结点 */ +/* 删除链表的节点 n0 之后的首个节点 */ func removeNode(n0 *ListNode) { if n0.Next == nil { return @@ -26,7 +26,7 @@ func removeNode(n0 *ListNode) { n0.Next = n1 } -/* 访问链表中索引为 index 的结点 */ +/* 访问链表中索引为 index 的节点 */ func access(head *ListNode, index int) *ListNode { for i := 0; i < index; i++ { if head == nil { @@ -37,7 +37,7 @@ func access(head *ListNode, index int) *ListNode { return head } -/* 在链表中查找值为 target 的首个结点 */ +/* 在链表中查找值为 target 的首个节点 */ func findNode(head *ListNode, target int) int { index := 0 for head != nil { diff --git a/codes/go/chapter_array_and_linkedlist/linked_list_test.go b/codes/go/chapter_array_and_linkedlist/linked_list_test.go index 76671d6a..8a3f5cb8 100644 --- a/codes/go/chapter_array_and_linkedlist/linked_list_test.go +++ b/codes/go/chapter_array_and_linkedlist/linked_list_test.go @@ -13,7 +13,7 @@ import ( func TestLinkedList(t *testing.T) { /* 初始化链表 1 -> 3 -> 2 -> 5 -> 4 */ - // 初始化各个结点 + // 初始化各个节点 n0 := NewListNode(1) n1 := NewListNode(3) n2 := NewListNode(2) @@ -28,21 +28,21 @@ func TestLinkedList(t *testing.T) { fmt.Println("初始化的链表为") PrintLinkedList(n0) - /* 插入结点 */ + /* 插入节点 */ insertNode(n0, NewListNode(0)) - fmt.Println("插入结点后的链表为") + fmt.Println("插入节点后的链表为") PrintLinkedList(n0) - /* 删除结点 */ + /* 删除节点 */ removeNode(n0) - fmt.Println("删除结点后的链表为") + fmt.Println("删除节点后的链表为") PrintLinkedList(n0) - /* 访问结点 */ + /* 访问节点 */ node := access(n0, 3) - fmt.Println("链表中索引 3 处的结点的值 =", node) + fmt.Println("链表中索引 3 处的节点的值 =", node) - /* 查找结点 */ + /* 查找节点 */ index := findNode(n0, 2) - fmt.Println("链表中值为 2 的结点的索引 =", index) + fmt.Println("链表中值为 2 的节点的索引 =", index) } diff --git a/codes/go/chapter_heap/my_heap.go b/codes/go/chapter_heap/my_heap.go index 65e43e07..af220759 100644 --- a/codes/go/chapter_heap/my_heap.go +++ b/codes/go/chapter_heap/my_heap.go @@ -27,23 +27,23 @@ func newMaxHeap(nums []any) *maxHeap { // 将列表元素原封不动添加进堆 h := &maxHeap{data: nums} for i := len(h.data) - 1; i >= 0; i-- { - // 堆化除叶结点以外的其他所有结点 + // 堆化除叶节点以外的其他所有节点 h.siftDown(i) } return h } -/* 获取左子结点索引 */ +/* 获取左子节点索引 */ func (h *maxHeap) left(i int) int { return 2*i + 1 } -/* 获取右子结点索引 */ +/* 获取右子节点索引 */ func (h *maxHeap) right(i int) int { return 2*i + 2 } -/* 获取父结点索引 */ +/* 获取父节点索引 */ func (h *maxHeap) parent(i int) int { // 向下整除 return (i - 1) / 2 @@ -71,22 +71,22 @@ func (h *maxHeap) peek() any { /* 元素入堆 */ func (h *maxHeap) push(val any) { - // 添加结点 + // 添加节点 h.data = append(h.data, val) // 从底至顶堆化 h.siftUp(len(h.data) - 1) } -/* 从结点 i 开始,从底至顶堆化 */ +/* 从节点 i 开始,从底至顶堆化 */ func (h *maxHeap) siftUp(i int) { for true { - // 获取结点 i 的父结点 + // 获取节点 i 的父节点 p := h.parent(i) - // 当“越过根结点”或“结点无需修复”时,结束堆化 + // 当“越过根节点”或“节点无需修复”时,结束堆化 if p < 0 || h.data[i].(int) <= h.data[p].(int) { break } - // 交换两结点 + // 交换两节点 h.swap(i, p) // 循环向上堆化 i = p @@ -100,9 +100,9 @@ func (h *maxHeap) pop() any { fmt.Println("error") return nil } - // 交换根结点与最右叶结点(即交换首元素与尾元素) + // 交换根节点与最右叶节点(即交换首元素与尾元素) h.swap(0, h.size()-1) - // 删除结点 + // 删除节点 val := h.data[len(h.data)-1] h.data = h.data[:len(h.data)-1] // 从顶至底堆化 @@ -112,10 +112,10 @@ func (h *maxHeap) pop() any { return val } -/* 从结点 i 开始,从顶至底堆化 */ +/* 从节点 i 开始,从顶至底堆化 */ func (h *maxHeap) siftDown(i int) { for true { - // 判断结点 i, l, r 中值最大的结点,记为 max + // 判断节点 i, l, r 中值最大的节点,记为 max l, r, max := h.left(i), h.right(i), i if l < h.size() && h.data[l].(int) > h.data[max].(int) { max = l @@ -123,11 +123,11 @@ func (h *maxHeap) siftDown(i int) { if r < h.size() && h.data[r].(int) > h.data[max].(int) { max = r } - // 若结点 i 最大或索引 l, r 越界,则无需继续堆化,跳出 + // 若节点 i 最大或索引 l, r 越界,则无需继续堆化,跳出 if max == i { break } - // 交换两结点 + // 交换两节点 h.swap(i, max) // 循环向下堆化 i = max diff --git a/codes/go/chapter_searching/hashing_search.go b/codes/go/chapter_searching/hashing_search.go index 56e1eeb9..7d10b867 100644 --- a/codes/go/chapter_searching/hashing_search.go +++ b/codes/go/chapter_searching/hashing_search.go @@ -19,7 +19,7 @@ func hashingSearchArray(m map[int]int, target int) int { /* 哈希查找(链表) */ func hashingSearchLinkedList(m map[int]*ListNode, target int) *ListNode { - // 哈希表的 key: 目标结点值,value: 结点对象 + // 哈希表的 key: 目标节点值,value: 节点对象 // 若哈希表中无此 key ,返回 nil if node, ok := m[target]; ok { return node diff --git a/codes/go/chapter_searching/hashing_search_test.go b/codes/go/chapter_searching/hashing_search_test.go index b4b89ad4..fd0f29bb 100644 --- a/codes/go/chapter_searching/hashing_search_test.go +++ b/codes/go/chapter_searching/hashing_search_test.go @@ -32,5 +32,5 @@ func TestHashingSearch(t *testing.T) { head = head.Next } node := hashingSearchLinkedList(m1, target) - fmt.Println("目标结点值 3 的对应结点对象为 ", node) + fmt.Println("目标节点值 3 的对应节点对象为 ", node) } diff --git a/codes/go/chapter_searching/linear_search.go b/codes/go/chapter_searching/linear_search.go index 95f29cf8..f55978e6 100644 --- a/codes/go/chapter_searching/linear_search.go +++ b/codes/go/chapter_searching/linear_search.go @@ -25,7 +25,7 @@ func linearSearchArray(nums []int, target int) int { func linearSearchLinkedList(node *ListNode, target int) *ListNode { // 遍历链表 for node != nil { - // 找到目标结点,返回之 + // 找到目标节点,返回之 if node.Val == target { return node } diff --git a/codes/go/chapter_searching/linear_search_test.go b/codes/go/chapter_searching/linear_search_test.go index 4c36c417..21523bdf 100644 --- a/codes/go/chapter_searching/linear_search_test.go +++ b/codes/go/chapter_searching/linear_search_test.go @@ -22,5 +22,5 @@ func TestLinearSearch(t *testing.T) { // 在链表中执行线性查找 head := ArrayToLinkedList(nums) node := linearSearchLinkedList(head, target) - fmt.Println("目标结点值 3 的对应结点对象为", node) + fmt.Println("目标节点值 3 的对应节点对象为", node) } diff --git a/codes/go/chapter_tree/avl_tree.go b/codes/go/chapter_tree/avl_tree.go index 117a7fb5..d57cdff1 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 } @@ -16,20 +16,20 @@ func newAVLTree() *aVLTree { return &aVLTree{root: nil} } -/* 获取结点高度 */ +/* 获取节点高度 */ func (t *aVLTree) height(node *TreeNode) int { - // 空结点高度为 -1 ,叶结点高度为 0 + // 空节点高度为 -1 ,叶节点高度为 0 if node != nil { return node.Height } return -1 } -/* 更新结点高度 */ +/* 更新节点高度 */ func (t *aVLTree) updateHeight(node *TreeNode) { lh := t.height(node.Left) rh := t.height(node.Right) - // 结点高度等于最高子树高度 + 1 + // 节点高度等于最高子树高度 + 1 if lh > rh { node.Height = lh + 1 } else { @@ -39,11 +39,11 @@ func (t *aVLTree) updateHeight(node *TreeNode) { /* 获取平衡因子 */ func (t *aVLTree) balanceFactor(node *TreeNode) int { - // 空结点平衡因子为 0 + // 空节点平衡因子为 0 if node == nil { return 0 } - // 结点平衡因子 = 左子树高度 - 右子树高度 + // 节点平衡因子 = 左子树高度 - 右子树高度 return t.height(node.Left) - t.height(node.Right) } @@ -54,10 +54,10 @@ func (t *aVLTree) rightRotate(node *TreeNode) *TreeNode { // 以 child 为原点,将 node 向右旋转 child.Right = node node.Left = grandChild - // 更新结点高度 + // 更新节点高度 t.updateHeight(node) t.updateHeight(child) - // 返回旋转后子树的根结点 + // 返回旋转后子树的根节点 return child } @@ -68,16 +68,16 @@ func (t *aVLTree) leftRotate(node *TreeNode) *TreeNode { // 以 child 为原点,将 node 向左旋转 child.Left = node node.Right = grandChild - // 更新结点高度 + // 更新节点高度 t.updateHeight(node) t.updateHeight(child) - // 返回旋转后子树的根结点 + // 返回旋转后子树的根节点 return child } /* 执行旋转操作,使该子树重新恢复平衡 */ func (t *aVLTree) rotate(node *TreeNode) *TreeNode { - // 获取结点 node 的平衡因子 + // 获取节点 node 的平衡因子 // Go 推荐短变量,这里 bf 指代 t.balanceFactor bf := t.balanceFactor(node) // 左偏树 @@ -106,46 +106,46 @@ func (t *aVLTree) rotate(node *TreeNode) *TreeNode { return node } -/* 插入结点 */ +/* 插入节点 */ func (t *aVLTree) insert(val int) *TreeNode { t.root = t.insertHelper(t.root, val) return t.root } -/* 递归插入结点(辅助方法) */ +/* 递归插入节点(辅助方法) */ func (t *aVLTree) insertHelper(node *TreeNode, val int) *TreeNode { if node == nil { return NewTreeNode(val) } - /* 1. 查找插入位置,并插入结点 */ + /* 1. 查找插入位置,并插入节点 */ if val < node.Val { node.Left = t.insertHelper(node.Left, val) } else if val > node.Val { node.Right = t.insertHelper(node.Right, val) } else { - // 重复结点不插入,直接返回 + // 重复节点不插入,直接返回 return node } - // 更新结点高度 + // 更新节点高度 t.updateHeight(node) /* 2. 执行旋转操作,使该子树重新恢复平衡 */ node = t.rotate(node) - // 返回子树的根结点 + // 返回子树的根节点 return node } -/* 删除结点 */ +/* 删除节点 */ func (t *aVLTree) remove(val int) *TreeNode { root := t.removeHelper(t.root, val) return root } -/* 递归删除结点(辅助方法) */ +/* 递归删除节点(辅助方法) */ func (t *aVLTree) removeHelper(node *TreeNode, val int) *TreeNode { if node == nil { return nil } - /* 1. 查找结点,并删除之 */ + /* 1. 查找节点,并删除之 */ if val < node.Val { node.Left = t.removeHelper(node.Left, val) } else if val > node.Val { @@ -156,56 +156,56 @@ func (t *aVLTree) removeHelper(node *TreeNode, val int) *TreeNode { if node.Right != nil { child = node.Right } - // 子结点数量 = 0 ,直接删除 node 并返回 + // 子节点数量 = 0 ,直接删除 node 并返回 if child == nil { return nil } else { - // 子结点数量 = 1 ,直接删除 node + // 子节点数量 = 1 ,直接删除 node node = child } } else { - // 子结点数量 = 2 ,则将中序遍历的下个结点删除,并用该结点替换当前结点 + // 子节点数量 = 2 ,则将中序遍历的下个节点删除,并用该节点替换当前节点 temp := t.getInOrderNext(node.Right) node.Right = t.removeHelper(node.Right, temp.Val) node.Val = temp.Val } } - // 更新结点高度 + // 更新节点高度 t.updateHeight(node) /* 2. 执行旋转操作,使该子树重新恢复平衡 */ node = t.rotate(node) - // 返回子树的根结点 + // 返回子树的根节点 return node } -/* 获取中序遍历中的下一个结点(仅适用于 root 有左子结点的情况) */ +/* 获取中序遍历中的下一个节点(仅适用于 root 有左子节点的情况) */ func (t *aVLTree) getInOrderNext(node *TreeNode) *TreeNode { if node == nil { return node } - // 循环访问左子结点,直到叶结点时为最小结点,跳出 + // 循环访问左子节点,直到叶节点时为最小节点,跳出 for node.Left != nil { node = node.Left } return node } -/* 查找结点 */ +/* 查找节点 */ func (t *aVLTree) search(val int) *TreeNode { cur := t.root - // 循环查找,越过叶结点后跳出 + // 循环查找,越过叶节点后跳出 for cur != nil { if cur.Val < val { - // 目标结点在 cur 的右子树中 + // 目标节点在 cur 的右子树中 cur = cur.Right } else if cur.Val > val { - // 目标结点在 cur 的左子树中 + // 目标节点在 cur 的左子树中 cur = cur.Left } else { - // 找到目标结点,跳出循环 + // 找到目标节点,跳出循环 break } } - // 返回目标结点 + // 返回目标节点 return cur } diff --git a/codes/go/chapter_tree/avl_tree_test.go b/codes/go/chapter_tree/avl_tree_test.go index 8c419bbc..8dd03776 100644 --- a/codes/go/chapter_tree/avl_tree_test.go +++ b/codes/go/chapter_tree/avl_tree_test.go @@ -14,8 +14,8 @@ import ( func TestAVLTree(t *testing.T) { /* 初始化空 AVL 树 */ tree := newAVLTree() - /* 插入结点 */ - // 请关注插入结点后,AVL 树是如何保持平衡的 + /* 插入节点 */ + // 请关注插入节点后,AVL 树是如何保持平衡的 testInsert(tree, 1) testInsert(tree, 2) testInsert(tree, 3) @@ -27,28 +27,28 @@ func TestAVLTree(t *testing.T) { testInsert(tree, 10) testInsert(tree, 6) - /* 插入重复结点 */ + /* 插入重复节点 */ testInsert(tree, 7) - /* 删除结点 */ - // 请关注删除结点后,AVL 树是如何保持平衡的 - testRemove(tree, 8) // 删除度为 0 的结点 - testRemove(tree, 5) // 删除度为 1 的结点 - testRemove(tree, 4) // 删除度为 2 的结点 + /* 删除节点 */ + // 请关注删除节点后,AVL 树是如何保持平衡的 + testRemove(tree, 8) // 删除度为 0 的节点 + testRemove(tree, 5) // 删除度为 1 的节点 + testRemove(tree, 4) // 删除度为 2 的节点 - /* 查询结点 */ + /* 查询节点 */ node := tree.search(7) - fmt.Printf("\n查找到的结点对象为 %#v ,结点值 = %d \n", node, node.Val) + fmt.Printf("\n查找到的节点对象为 %#v ,节点值 = %d \n", node, node.Val) } func testInsert(tree *aVLTree, val int) { tree.insert(val) - fmt.Printf("\n插入结点 %d 后,AVL 树为 \n", val) + fmt.Printf("\n插入节点 %d 后,AVL 树为 \n", val) PrintTree(tree.root) } func testRemove(tree *aVLTree, val int) { tree.remove(val) - fmt.Printf("\n删除结点 %d 后,AVL 树为 \n", val) + fmt.Printf("\n删除节点 %d 后,AVL 树为 \n", val) PrintTree(tree.root) } diff --git a/codes/go/chapter_tree/binary_search_tree.go b/codes/go/chapter_tree/binary_search_tree.go index b671db1e..a4cb8596 100644 --- a/codes/go/chapter_tree/binary_search_tree.go +++ b/codes/go/chapter_tree/binary_search_tree.go @@ -28,7 +28,7 @@ func (bst *binarySearchTree) buildTree(nums []int, left, right int) *TreeNode { if left > right { return nil } - // 将数组中间结点作为根结点 + // 将数组中间节点作为根节点 middle := left + (right-left)>>1 root := NewTreeNode(nums[middle]) // 递归构建左子树和右子树 @@ -37,53 +37,53 @@ func (bst *binarySearchTree) buildTree(nums []int, left, right int) *TreeNode { return root } -/* 获取根结点 */ +/* 获取根节点 */ func (bst *binarySearchTree) getRoot() *TreeNode { return bst.root } -/* 获取中序遍历的下一个结点(仅适用于 root 有左子结点的情况) */ +/* 获取中序遍历的下一个节点(仅适用于 root 有左子节点的情况) */ func (bst *binarySearchTree) getInOrderNext(node *TreeNode) *TreeNode { if node == nil { return node } - // 循环访问左子结点,直到叶结点时为最小结点,跳出 + // 循环访问左子节点,直到叶节点时为最小节点,跳出 for node.Left != nil { node = node.Left } return node } -/* 查找结点 */ +/* 查找节点 */ func (bst *binarySearchTree) search(num int) *TreeNode { node := bst.root - // 循环查找,越过叶结点后跳出 + // 循环查找,越过叶节点后跳出 for node != nil { if node.Val < num { - // 目标结点在 cur 的右子树中 + // 目标节点在 cur 的右子树中 node = node.Right } else if node.Val > num { - // 目标结点在 cur 的左子树中 + // 目标节点在 cur 的左子树中 node = node.Left } else { - // 找到目标结点,跳出循环 + // 找到目标节点,跳出循环 break } } - // 返回目标结点 + // 返回目标节点 return node } -/* 插入结点 */ +/* 插入节点 */ func (bst *binarySearchTree) insert(num int) *TreeNode { cur := bst.root // 若树为空,直接提前返回 if cur == nil { return nil } - // 待插入结点之前的结点位置 + // 待插入节点之前的节点位置 var pre *TreeNode = nil - // 循环查找,越过叶结点后跳出 + // 循环查找,越过叶节点后跳出 for cur != nil { if cur.Val == num { return nil @@ -95,7 +95,7 @@ func (bst *binarySearchTree) insert(num int) *TreeNode { cur = cur.Left } } - // 插入结点 + // 插入节点 node := NewTreeNode(num) if pre.Val < num { pre.Right = node @@ -105,54 +105,54 @@ func (bst *binarySearchTree) insert(num int) *TreeNode { return cur } -/* 删除结点 */ +/* 删除节点 */ func (bst *binarySearchTree) remove(num int) *TreeNode { cur := bst.root // 若树为空,直接提前返回 if cur == nil { return nil } - // 待删除结点之前的结点位置 + // 待删除节点之前的节点位置 var pre *TreeNode = nil - // 循环查找,越过叶结点后跳出 + // 循环查找,越过叶节点后跳出 for cur != nil { if cur.Val == num { break } pre = cur if cur.Val < num { - // 待删除结点在右子树中 + // 待删除节点在右子树中 cur = cur.Right } else { - // 待删除结点在左子树中 + // 待删除节点在左子树中 cur = cur.Left } } - // 若无待删除结点,则直接返回 + // 若无待删除节点,则直接返回 if cur == nil { return nil } - // 子结点数为 0 或 1 + // 子节点数为 0 或 1 if cur.Left == nil || cur.Right == nil { var child *TreeNode = nil - // 取出待删除结点的子结点 + // 取出待删除节点的子节点 if cur.Left != nil { child = cur.Left } else { child = cur.Right } - // 将子结点替换为待删除结点 + // 将子节点替换为待删除节点 if pre.Left == cur { pre.Left = child } else { pre.Right = child } - // 子结点数为 2 + // 子节点数为 2 } else { - // 获取中序遍历中待删除结点 cur 的下一个结点 + // 获取中序遍历中待删除节点 cur 的下一个节点 next := bst.getInOrderNext(cur) temp := next.Val - // 递归删除结点 next + // 递归删除节点 next bst.remove(next.Val) // 将 next 的值复制给 cur cur.Val = temp diff --git a/codes/go/chapter_tree/binary_search_tree_test.go b/codes/go/chapter_tree/binary_search_tree_test.go index 2a864d13..4f87ee7a 100644 --- a/codes/go/chapter_tree/binary_search_tree_test.go +++ b/codes/go/chapter_tree/binary_search_tree_test.go @@ -15,27 +15,27 @@ func TestBinarySearchTree(t *testing.T) { fmt.Println("\n初始化的二叉树为:") bst.print() - // 获取根结点 + // 获取根节点 node := bst.getRoot() - fmt.Println("\n二叉树的根结点为:", node.Val) + fmt.Println("\n二叉树的根节点为:", node.Val) - // 查找结点 + // 查找节点 node = bst.search(7) - fmt.Println("查找到的结点对象为", node, ",结点值 =", node.Val) + fmt.Println("查找到的节点对象为", node, ",节点值 =", node.Val) - // 插入结点 + // 插入节点 node = bst.insert(16) - fmt.Println("\n插入结点后 16 的二叉树为:") + fmt.Println("\n插入节点后 16 的二叉树为:") bst.print() - // 删除结点 + // 删除节点 bst.remove(1) - fmt.Println("\n删除结点 1 后的二叉树为:") + fmt.Println("\n删除节点 1 后的二叉树为:") bst.print() bst.remove(2) - fmt.Println("\n删除结点 2 后的二叉树为:") + fmt.Println("\n删除节点 2 后的二叉树为:") bst.print() bst.remove(4) - fmt.Println("\n删除结点 4 后的二叉树为:") + fmt.Println("\n删除节点 4 后的二叉树为:") bst.print() } diff --git a/codes/go/chapter_tree/binary_tree_bfs.go b/codes/go/chapter_tree/binary_tree_bfs.go index 76dc4aea..938fb063 100644 --- a/codes/go/chapter_tree/binary_tree_bfs.go +++ b/codes/go/chapter_tree/binary_tree_bfs.go @@ -12,7 +12,7 @@ import ( /* 层序遍历 */ func levelOrder(root *TreeNode) []int { - // 初始化队列,加入根结点 + // 初始化队列,加入根节点 queue := list.New() queue.PushBack(root) // 初始化一个切片,用于保存遍历序列 @@ -20,14 +20,14 @@ func levelOrder(root *TreeNode) []int { for queue.Len() > 0 { // 队列出队 node := queue.Remove(queue.Front()).(*TreeNode) - // 保存结点值 + // 保存节点值 nums = append(nums, node.Val) if node.Left != nil { - // 左子结点入队 + // 左子节点入队 queue.PushBack(node.Left) } if node.Right != nil { - // 右子结点入队 + // 右子节点入队 queue.PushBack(node.Right) } } diff --git a/codes/go/chapter_tree/binary_tree_bfs_test.go b/codes/go/chapter_tree/binary_tree_bfs_test.go index 7b1bbf1f..b29c44f3 100644 --- a/codes/go/chapter_tree/binary_tree_bfs_test.go +++ b/codes/go/chapter_tree/binary_tree_bfs_test.go @@ -20,5 +20,5 @@ func TestLevelOrder(t *testing.T) { // 层序遍历 nums := levelOrder(root) - fmt.Println("\n层序遍历的结点打印序列 =", nums) + fmt.Println("\n层序遍历的节点打印序列 =", nums) } diff --git a/codes/go/chapter_tree/binary_tree_dfs.go b/codes/go/chapter_tree/binary_tree_dfs.go index 1a857eba..75486cf7 100644 --- a/codes/go/chapter_tree/binary_tree_dfs.go +++ b/codes/go/chapter_tree/binary_tree_dfs.go @@ -15,7 +15,7 @@ func preOrder(node *TreeNode) { if node == nil { return } - // 访问优先级:根结点 -> 左子树 -> 右子树 + // 访问优先级:根节点 -> 左子树 -> 右子树 nums = append(nums, node.Val) preOrder(node.Left) preOrder(node.Right) @@ -26,7 +26,7 @@ func inOrder(node *TreeNode) { if node == nil { return } - // 访问优先级:左子树 -> 根结点 -> 右子树 + // 访问优先级:左子树 -> 根节点 -> 右子树 inOrder(node.Left) nums = append(nums, node.Val) inOrder(node.Right) @@ -37,7 +37,7 @@ func postOrder(node *TreeNode) { if node == nil { return } - // 访问优先级:左子树 -> 右子树 -> 根结点 + // 访问优先级:左子树 -> 右子树 -> 根节点 postOrder(node.Left) postOrder(node.Right) nums = append(nums, node.Val) diff --git a/codes/go/chapter_tree/binary_tree_dfs_test.go b/codes/go/chapter_tree/binary_tree_dfs_test.go index 9e0dfe22..dfe822f2 100644 --- a/codes/go/chapter_tree/binary_tree_dfs_test.go +++ b/codes/go/chapter_tree/binary_tree_dfs_test.go @@ -21,15 +21,15 @@ func TestPreInPostOrderTraversal(t *testing.T) { // 前序遍历 nums = nil preOrder(root) - fmt.Println("\n前序遍历的结点打印序列 =", nums) + fmt.Println("\n前序遍历的节点打印序列 =", nums) // 中序遍历 nums = nil inOrder(root) - fmt.Println("\n中序遍历的结点打印序列 =", nums) + fmt.Println("\n中序遍历的节点打印序列 =", nums) // 后序遍历 nums = nil postOrder(root) - fmt.Println("\n后序遍历的结点打印序列 =", nums) + fmt.Println("\n后序遍历的节点打印序列 =", nums) } diff --git a/codes/go/chapter_tree/binary_tree_test.go b/codes/go/chapter_tree/binary_tree_test.go index f91e816f..f226e4f7 100644 --- a/codes/go/chapter_tree/binary_tree_test.go +++ b/codes/go/chapter_tree/binary_tree_test.go @@ -13,7 +13,7 @@ import ( func TestBinaryTree(t *testing.T) { /* 初始化二叉树 */ - // 初始化结点 + // 初始化节点 n1 := NewTreeNode(1) n2 := NewTreeNode(2) n3 := NewTreeNode(3) @@ -27,15 +27,15 @@ func TestBinaryTree(t *testing.T) { fmt.Println("初始化二叉树") PrintTree(n1) - /* 插入与删除结点 */ - // 插入结点 + /* 插入与删除节点 */ + // 插入节点 p := NewTreeNode(0) n1.Left = p p.Left = n2 - fmt.Println("插入结点 P 后") + fmt.Println("插入节点 P 后") PrintTree(n1) - // 删除结点 + // 删除节点 n1.Left = n2 - fmt.Println("删除结点 P 后") + fmt.Println("删除节点 P 后") PrintTree(n1) } diff --git a/codes/go/pkg/tree_node.go b/codes/go/pkg/tree_node.go index 560fc4f0..32299168 100644 --- a/codes/go/pkg/tree_node.go +++ b/codes/go/pkg/tree_node.go @@ -9,10 +9,10 @@ import ( ) type TreeNode struct { - Val int // 结点值 - Height int // 结点高度 - Left *TreeNode // 左子结点引用 - Right *TreeNode // 右子结点引用 + Val int // 节点值 + Height int // 节点高度 + Left *TreeNode // 左子节点引用 + Right *TreeNode // 右子节点引用 } func NewTreeNode(v int) *TreeNode { diff --git a/codes/java/chapter_array_and_linkedlist/linked_list.java b/codes/java/chapter_array_and_linkedlist/linked_list.java index 64a41ed1..75844590 100644 --- a/codes/java/chapter_array_and_linkedlist/linked_list.java +++ b/codes/java/chapter_array_and_linkedlist/linked_list.java @@ -9,14 +9,14 @@ package chapter_array_and_linkedlist; import include.*; public class linked_list { - /* 在链表的结点 n0 之后插入结点 P */ + /* 在链表的节点 n0 之后插入节点 P */ static void insert(ListNode n0, ListNode P) { ListNode n1 = n0.next; P.next = n1; n0.next = P; } - /* 删除链表的结点 n0 之后的首个结点 */ + /* 删除链表的节点 n0 之后的首个节点 */ static void remove(ListNode n0) { if (n0.next == null) return; @@ -26,7 +26,7 @@ public class linked_list { n0.next = n1; } - /* 访问链表中索引为 index 的结点 */ + /* 访问链表中索引为 index 的节点 */ static ListNode access(ListNode head, int index) { for (int i = 0; i < index; i++) { if (head == null) @@ -36,7 +36,7 @@ public class linked_list { return head; } - /* 在链表中查找值为 target 的首个结点 */ + /* 在链表中查找值为 target 的首个节点 */ static int find(ListNode head, int target) { int index = 0; while (head != null) { @@ -51,7 +51,7 @@ public class linked_list { /* Driver Code */ public static void main(String[] args) { /* 初始化链表 */ - // 初始化各个结点 + // 初始化各个节点 ListNode n0 = new ListNode(1); ListNode n1 = new ListNode(3); ListNode n2 = new ListNode(2); @@ -65,22 +65,22 @@ public class linked_list { System.out.println("初始化的链表为"); PrintUtil.printLinkedList(n0); - /* 插入结点 */ + /* 插入节点 */ insert(n0, new ListNode(0)); - System.out.println("插入结点后的链表为"); + System.out.println("插入节点后的链表为"); PrintUtil.printLinkedList(n0); - /* 删除结点 */ + /* 删除节点 */ remove(n0); - System.out.println("删除结点后的链表为"); + System.out.println("删除节点后的链表为"); PrintUtil.printLinkedList(n0); - /* 访问结点 */ + /* 访问节点 */ ListNode node = access(n0, 3); - System.out.println("链表中索引 3 处的结点的值 = " + node.val); + System.out.println("链表中索引 3 处的节点的值 = " + node.val); - /* 查找结点 */ + /* 查找节点 */ int index = find(n0, 2); - System.out.println("链表中值为 2 的结点的索引 = " + index); + System.out.println("链表中值为 2 的节点的索引 = " + index); } } diff --git a/codes/java/chapter_heap/my_heap.java b/codes/java/chapter_heap/my_heap.java index c3341d0b..746d28d7 100644 --- a/codes/java/chapter_heap/my_heap.java +++ b/codes/java/chapter_heap/my_heap.java @@ -18,23 +18,23 @@ class MaxHeap { public MaxHeap(List nums) { // 将列表元素原封不动添加进堆 maxHeap = new ArrayList<>(nums); - // 堆化除叶结点以外的其他所有结点 + // 堆化除叶节点以外的其他所有节点 for (int i = parent(size() - 1); i >= 0; i--) { siftDown(i); } } - /* 获取左子结点索引 */ + /* 获取左子节点索引 */ private int left(int i) { return 2 * i + 1; } - /* 获取右子结点索引 */ + /* 获取右子节点索引 */ private int right(int i) { return 2 * i + 2; } - /* 获取父结点索引 */ + /* 获取父节点索引 */ private int parent(int i) { return (i - 1) / 2; // 向下整除 } @@ -65,21 +65,21 @@ class MaxHeap { /* 元素入堆 */ public void push(int val) { - // 添加结点 + // 添加节点 maxHeap.add(val); // 从底至顶堆化 siftUp(size() - 1); } - /* 从结点 i 开始,从底至顶堆化 */ + /* 从节点 i 开始,从底至顶堆化 */ private void siftUp(int i) { while (true) { - // 获取结点 i 的父结点 + // 获取节点 i 的父节点 int p = parent(i); - // 当“越过根结点”或“结点无需修复”时,结束堆化 + // 当“越过根节点”或“节点无需修复”时,结束堆化 if (p < 0 || maxHeap.get(i) <= maxHeap.get(p)) break; - // 交换两结点 + // 交换两节点 swap(i, p); // 循环向上堆化 i = p; @@ -91,9 +91,9 @@ class MaxHeap { // 判空处理 if (isEmpty()) throw new EmptyStackException(); - // 交换根结点与最右叶结点(即交换首元素与尾元素) + // 交换根节点与最右叶节点(即交换首元素与尾元素) swap(0, size() - 1); - // 删除结点 + // 删除节点 int val = maxHeap.remove(size() - 1); // 从顶至底堆化 siftDown(0); @@ -101,18 +101,18 @@ class MaxHeap { return val; } - /* 从结点 i 开始,从顶至底堆化 */ + /* 从节点 i 开始,从顶至底堆化 */ private void siftDown(int i) { while (true) { - // 判断结点 i, l, r 中值最大的结点,记为 ma + // 判断节点 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 最大或索引 l, r 越界,则无需继续堆化,跳出 + // 若节点 i 最大或索引 l, r 越界,则无需继续堆化,跳出 if (ma == i) break; - // 交换两结点 + // 交换两节点 swap(i, ma); // 循环向下堆化 i = ma; diff --git a/codes/java/chapter_searching/hashing_search.java b/codes/java/chapter_searching/hashing_search.java index 364d2969..78f40fac 100644 --- a/codes/java/chapter_searching/hashing_search.java +++ b/codes/java/chapter_searching/hashing_search.java @@ -19,7 +19,7 @@ public class hashing_search { /* 哈希查找(链表) */ static ListNode hashingSearchLinkedList(Map map, int target) { - // 哈希表的 key: 目标结点值,value: 结点对象 + // 哈希表的 key: 目标节点值,value: 节点对象 // 若哈希表中无此 key ,返回 null return map.getOrDefault(target, null); } @@ -42,10 +42,10 @@ public class hashing_search { // 初始化哈希表 Map map1 = new HashMap<>(); while (head != null) { - map1.put(head.val, head); // key: 结点值,value: 结点 + map1.put(head.val, head); // key: 节点值,value: 节点 head = head.next; } ListNode node = hashingSearchLinkedList(map1, target); - System.out.println("目标结点值 3 的对应结点对象为 " + node); + System.out.println("目标节点值 3 的对应节点对象为 " + node); } } diff --git a/codes/java/chapter_searching/linear_search.java b/codes/java/chapter_searching/linear_search.java index 4976575d..1a4ffa62 100644 --- a/codes/java/chapter_searching/linear_search.java +++ b/codes/java/chapter_searching/linear_search.java @@ -25,12 +25,12 @@ public class linear_search { static ListNode linearSearchLinkedList(ListNode head, int target) { // 遍历链表 while (head != null) { - // 找到目标结点,返回之 + // 找到目标节点,返回之 if (head.val == target) return head; head = head.next; } - // 未找到目标结点,返回 null + // 未找到目标节点,返回 null return null; } @@ -45,6 +45,6 @@ public class linear_search { /* 在链表中执行线性查找 */ ListNode head = ListNode.arrToLinkedList(nums); ListNode node = linearSearchLinkedList(head, target); - System.out.println("目标结点值 3 的对应结点对象为 " + node); + System.out.println("目标节点值 3 的对应节点对象为 " + node); } } diff --git a/codes/java/chapter_stack_and_queue/linkedlist_deque.java b/codes/java/chapter_stack_and_queue/linkedlist_deque.java index 45dff8e9..a9504474 100644 --- a/codes/java/chapter_stack_and_queue/linkedlist_deque.java +++ b/codes/java/chapter_stack_and_queue/linkedlist_deque.java @@ -8,11 +8,11 @@ package chapter_stack_and_queue; import java.util.*; -/* 双向链表结点 */ +/* 双向链表节点 */ class ListNode { - int val; // 结点值 - ListNode next; // 后继结点引用(指针) - ListNode prev; // 前驱结点引用(指针) + int val; // 节点值 + ListNode next; // 后继节点引用(指针) + ListNode prev; // 前驱节点引用(指针) ListNode(int val) { this.val = val; prev = next = null; @@ -21,7 +21,7 @@ class ListNode { /* 基于双向链表实现的双向队列 */ class LinkedListDeque { - private ListNode front, rear; // 头结点 front ,尾结点 rear + private ListNode front, rear; // 头节点 front ,尾节点 rear private int queSize = 0; // 双向队列的长度 public LinkedListDeque() { @@ -49,13 +49,13 @@ class LinkedListDeque { // 将 node 添加至链表头部 front.prev = node; node.next = front; - front = node; // 更新头结点 + front = node; // 更新头节点 // 队尾入队操作 } else { // 将 node 添加至链表尾部 rear.next = node; node.prev = rear; - rear = node; // 更新尾结点 + rear = node; // 更新尾节点 } queSize++; // 更新队列长度 } @@ -78,24 +78,24 @@ class LinkedListDeque { int val; // 队首出队操作 if (isFront) { - val = front.val; // 暂存头结点值 - // 删除头结点 + val = front.val; // 暂存头节点值 + // 删除头节点 ListNode fNext = front.next; if (fNext != null) { fNext.prev = null; front.next = null; } - front = fNext; // 更新头结点 + front = fNext; // 更新头节点 // 队尾出队操作 } else { - val = rear.val; // 暂存尾结点值 - // 删除尾结点 + val = rear.val; // 暂存尾节点值 + // 删除尾节点 ListNode rPrev = rear.prev; if (rPrev != null) { rPrev.next = null; rear.prev = null; } - rear = rPrev; // 更新尾结点 + rear = rPrev; // 更新尾节点 } queSize--; // 更新队列长度 return val; diff --git a/codes/java/chapter_stack_and_queue/linkedlist_queue.java b/codes/java/chapter_stack_and_queue/linkedlist_queue.java index 5dacaa3d..93176dbb 100644 --- a/codes/java/chapter_stack_and_queue/linkedlist_queue.java +++ b/codes/java/chapter_stack_and_queue/linkedlist_queue.java @@ -10,7 +10,7 @@ import java.util.*; /* 基于链表实现的队列 */ class LinkedListQueue { - private ListNode front, rear; // 头结点 front ,尾结点 rear + private ListNode front, rear; // 头节点 front ,尾节点 rear private int queSize = 0; public LinkedListQueue() { @@ -30,13 +30,13 @@ class LinkedListQueue { /* 入队 */ public void push(int num) { - // 尾结点后添加 num + // 尾节点后添加 num ListNode node = new ListNode(num); - // 如果队列为空,则令头、尾结点都指向该结点 + // 如果队列为空,则令头、尾节点都指向该节点 if (front == null) { front = node; rear = node; - // 如果队列不为空,则将该结点添加到尾结点后 + // 如果队列不为空,则将该节点添加到尾节点后 } else { rear.next = node; rear = node; @@ -47,7 +47,7 @@ class LinkedListQueue { /* 出队 */ public int pop() { int num = peek(); - // 删除头结点 + // 删除头节点 front = front.next; queSize--; return num; diff --git a/codes/java/chapter_stack_and_queue/linkedlist_stack.java b/codes/java/chapter_stack_and_queue/linkedlist_stack.java index b1a78aa4..3f898817 100644 --- a/codes/java/chapter_stack_and_queue/linkedlist_stack.java +++ b/codes/java/chapter_stack_and_queue/linkedlist_stack.java @@ -11,7 +11,7 @@ import include.*; /* 基于链表实现的栈 */ class LinkedListStack { - private ListNode stackPeek; // 将头结点作为栈顶 + private ListNode stackPeek; // 将头节点作为栈顶 private int stkSize = 0; // 栈的长度 public LinkedListStack() { diff --git a/codes/java/chapter_tree/avl_tree.java b/codes/java/chapter_tree/avl_tree.java index c982b7a3..8deb787c 100644 --- a/codes/java/chapter_tree/avl_tree.java +++ b/codes/java/chapter_tree/avl_tree.java @@ -10,25 +10,25 @@ import include.*; /* AVL 树 */ class AVLTree { - TreeNode root; // 根结点 + TreeNode root; // 根节点 - /* 获取结点高度 */ + /* 获取节点高度 */ public int height(TreeNode node) { - // 空结点高度为 -1 ,叶结点高度为 0 + // 空节点高度为 -1 ,叶节点高度为 0 return node == null ? -1 : node.height; } - /* 更新结点高度 */ + /* 更新节点高度 */ private void updateHeight(TreeNode node) { - // 结点高度等于最高子树高度 + 1 + // 节点高度等于最高子树高度 + 1 node.height = Math.max(height(node.left), height(node.right)) + 1; } /* 获取平衡因子 */ public int balanceFactor(TreeNode node) { - // 空结点平衡因子为 0 + // 空节点平衡因子为 0 if (node == null) return 0; - // 结点平衡因子 = 左子树高度 - 右子树高度 + // 节点平衡因子 = 左子树高度 - 右子树高度 return height(node.left) - height(node.right); } @@ -39,10 +39,10 @@ class AVLTree { // 以 child 为原点,将 node 向右旋转 child.right = node; node.left = grandChild; - // 更新结点高度 + // 更新节点高度 updateHeight(node); updateHeight(child); - // 返回旋转后子树的根结点 + // 返回旋转后子树的根节点 return child; } @@ -53,16 +53,16 @@ class AVLTree { // 以 child 为原点,将 node 向左旋转 child.left = node; node.right = grandChild; - // 更新结点高度 + // 更新节点高度 updateHeight(node); updateHeight(child); - // 返回旋转后子树的根结点 + // 返回旋转后子树的根节点 return child; } /* 执行旋转操作,使该子树重新恢复平衡 */ private TreeNode rotate(TreeNode node) { - // 获取结点 node 的平衡因子 + // 获取节点 node 的平衡因子 int balanceFactor = balanceFactor(node); // 左偏树 if (balanceFactor > 1) { @@ -90,39 +90,39 @@ class AVLTree { return node; } - /* 插入结点 */ + /* 插入节点 */ public TreeNode insert(int val) { root = insertHelper(root, val); return root; } - /* 递归插入结点(辅助方法) */ + /* 递归插入节点(辅助方法) */ private TreeNode insertHelper(TreeNode node, int val) { if (node == null) return new TreeNode(val); - /* 1. 查找插入位置,并插入结点 */ + /* 1. 查找插入位置,并插入节点 */ if (val < node.val) node.left = insertHelper(node.left, val); else if (val > node.val) node.right = insertHelper(node.right, val); else - return node; // 重复结点不插入,直接返回 - updateHeight(node); // 更新结点高度 + return node; // 重复节点不插入,直接返回 + updateHeight(node); // 更新节点高度 /* 2. 执行旋转操作,使该子树重新恢复平衡 */ node = rotate(node); - // 返回子树的根结点 + // 返回子树的根节点 return node; } - /* 删除结点 */ + /* 删除节点 */ public TreeNode remove(int val) { root = removeHelper(root, val); return root; } - /* 递归删除结点(辅助方法) */ + /* 递归删除节点(辅助方法) */ private TreeNode removeHelper(TreeNode node, int val) { if (node == null) return null; - /* 1. 查找结点,并删除之 */ + /* 1. 查找节点,并删除之 */ if (val < node.val) node.left = removeHelper(node.left, val); else if (val > node.val) @@ -130,52 +130,52 @@ class AVLTree { else { if (node.left == null || node.right == null) { TreeNode child = node.left != null ? node.left : node.right; - // 子结点数量 = 0 ,直接删除 node 并返回 + // 子节点数量 = 0 ,直接删除 node 并返回 if (child == null) return null; - // 子结点数量 = 1 ,直接删除 node + // 子节点数量 = 1 ,直接删除 node else node = child; } else { - // 子结点数量 = 2 ,则将中序遍历的下个结点删除,并用该结点替换当前结点 + // 子节点数量 = 2 ,则将中序遍历的下个节点删除,并用该节点替换当前节点 TreeNode temp = getInOrderNext(node.right); node.right = removeHelper(node.right, temp.val); node.val = temp.val; } } - updateHeight(node); // 更新结点高度 + updateHeight(node); // 更新节点高度 /* 2. 执行旋转操作,使该子树重新恢复平衡 */ node = rotate(node); - // 返回子树的根结点 + // 返回子树的根节点 return node; } - /* 获取中序遍历中的下一个结点(仅适用于 root 有左子结点的情况) */ + /* 获取中序遍历中的下一个节点(仅适用于 root 有左子节点的情况) */ private TreeNode getInOrderNext(TreeNode node) { if (node == null) return node; - // 循环访问左子结点,直到叶结点时为最小结点,跳出 + // 循环访问左子节点,直到叶节点时为最小节点,跳出 while (node.left != null) { node = node.left; } return node; } - /* 查找结点 */ + /* 查找节点 */ public TreeNode search(int val) { TreeNode cur = root; - // 循环查找,越过叶结点后跳出 + // 循环查找,越过叶节点后跳出 while (cur != null) { - // 目标结点在 cur 的右子树中 + // 目标节点在 cur 的右子树中 if (cur.val < val) cur = cur.right; - // 目标结点在 cur 的左子树中 + // 目标节点在 cur 的左子树中 else if (cur.val > val) cur = cur.left; - // 找到目标结点,跳出循环 + // 找到目标节点,跳出循环 else break; } - // 返回目标结点 + // 返回目标节点 return cur; } } @@ -183,13 +183,13 @@ class AVLTree { public class avl_tree { static void testInsert(AVLTree tree, int val) { tree.insert(val); - System.out.println("\n插入结点 " + val + " 后,AVL 树为"); + System.out.println("\n插入节点 " + val + " 后,AVL 树为"); PrintUtil.printTree(tree.root); } static void testRemove(AVLTree tree, int val) { tree.remove(val); - System.out.println("\n删除结点 " + val + " 后,AVL 树为"); + System.out.println("\n删除节点 " + val + " 后,AVL 树为"); PrintUtil.printTree(tree.root); } @@ -197,8 +197,8 @@ public class avl_tree { /* 初始化空 AVL 树 */ AVLTree avlTree = new AVLTree(); - /* 插入结点 */ - // 请关注插入结点后,AVL 树是如何保持平衡的 + /* 插入节点 */ + // 请关注插入节点后,AVL 树是如何保持平衡的 testInsert(avlTree, 1); testInsert(avlTree, 2); testInsert(avlTree, 3); @@ -210,17 +210,17 @@ public class avl_tree { testInsert(avlTree, 10); testInsert(avlTree, 6); - /* 插入重复结点 */ + /* 插入重复节点 */ testInsert(avlTree, 7); - /* 删除结点 */ - // 请关注删除结点后,AVL 树是如何保持平衡的 - testRemove(avlTree, 8); // 删除度为 0 的结点 - testRemove(avlTree, 5); // 删除度为 1 的结点 - testRemove(avlTree, 4); // 删除度为 2 的结点 + /* 删除节点 */ + // 请关注删除节点后,AVL 树是如何保持平衡的 + testRemove(avlTree, 8); // 删除度为 0 的节点 + testRemove(avlTree, 5); // 删除度为 1 的节点 + testRemove(avlTree, 4); // 删除度为 2 的节点 - /* 查询结点 */ + /* 查询节点 */ TreeNode node = avlTree.search(7); - System.out.println("\n查找到的结点对象为 " + node + ",结点值 = " + node.val); + System.out.println("\n查找到的节点对象为 " + node + ",节点值 = " + node.val); } } diff --git a/codes/java/chapter_tree/binary_search_tree.java b/codes/java/chapter_tree/binary_search_tree.java index 7f13b903..0d6436f1 100644 --- a/codes/java/chapter_tree/binary_search_tree.java +++ b/codes/java/chapter_tree/binary_search_tree.java @@ -18,7 +18,7 @@ class BinarySearchTree { root = buildTree(nums, 0, nums.length - 1); // 构建二叉搜索树 } - /* 获取二叉树根结点 */ + /* 获取二叉树根节点 */ public TreeNode getRoot() { return root; } @@ -26,7 +26,7 @@ class BinarySearchTree { /* 构建二叉搜索树 */ public TreeNode buildTree(int[] nums, int i, int j) { if (i > j) return null; - // 将数组中间结点作为根结点 + // 将数组中间节点作为根节点 int mid = (i + j) / 2; TreeNode root = new TreeNode(nums[mid]); // 递归建立左子树和右子树 @@ -35,30 +35,30 @@ class BinarySearchTree { return root; } - /* 查找结点 */ + /* 查找节点 */ public TreeNode search(int num) { TreeNode cur = root; - // 循环查找,越过叶结点后跳出 + // 循环查找,越过叶节点后跳出 while (cur != null) { - // 目标结点在 cur 的右子树中 + // 目标节点在 cur 的右子树中 if (cur.val < num) cur = cur.right; - // 目标结点在 cur 的左子树中 + // 目标节点在 cur 的左子树中 else if (cur.val > num) cur = cur.left; - // 找到目标结点,跳出循环 + // 找到目标节点,跳出循环 else break; } - // 返回目标结点 + // 返回目标节点 return cur; } - /* 插入结点 */ + /* 插入节点 */ public 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 的右子树中 @@ -66,44 +66,44 @@ class BinarySearchTree { // 插入位置在 cur 的左子树中 else cur = cur.left; } - // 插入结点 val + // 插入节点 val TreeNode node = new TreeNode(num); if (pre.val < num) pre.right = node; else pre.left = node; return node; } - /* 删除结点 */ + /* 删除节点 */ public 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 的右子树中 + // 待删除节点在 cur 的右子树中 if (cur.val < num) cur = cur.right; - // 待删除结点在 cur 的左子树中 + // 待删除节点在 cur 的左子树中 else cur = cur.left; } - // 若无待删除结点,则直接返回 + // 若无待删除节点,则直接返回 if (cur == null) return null; - // 子结点数量 = 0 or 1 + // 子节点数量 = 0 or 1 if (cur.left == null || cur.right == null) { - // 当子结点数量 = 0 / 1 时, child = null / 该子结点 + // 当子节点数量 = 0 / 1 时, child = null / 该子节点 TreeNode child = cur.left != null ? cur.left : cur.right; - // 删除结点 cur + // 删除节点 cur if (pre.left == cur) pre.left = child; else pre.right = child; } - // 子结点数量 = 2 + // 子节点数量 = 2 else { - // 获取中序遍历中 cur 的下一个结点 + // 获取中序遍历中 cur 的下一个节点 TreeNode nex = getInOrderNext(cur.right); int tmp = nex.val; - // 递归删除结点 nex + // 递归删除节点 nex remove(nex.val); // 将 nex 的值复制给 cur cur.val = tmp; @@ -111,10 +111,10 @@ class BinarySearchTree { return cur; } - /* 获取中序遍历中的下一个结点(仅适用于 root 有左子结点的情况) */ + /* 获取中序遍历中的下一个节点(仅适用于 root 有左子节点的情况) */ public TreeNode getInOrderNext(TreeNode root) { if (root == null) return root; - // 循环访问左子结点,直到叶结点时为最小结点,跳出 + // 循环访问左子节点,直到叶节点时为最小节点,跳出 while (root.left != null) { root = root.left; } @@ -130,24 +130,24 @@ public class binary_search_tree { System.out.println("\n初始化的二叉树为\n"); PrintUtil.printTree(bst.getRoot()); - /* 查找结点 */ + /* 查找节点 */ TreeNode node = bst.search(7); - System.out.println("\n查找到的结点对象为 " + node + ",结点值 = " + node.val); + System.out.println("\n查找到的节点对象为 " + node + ",节点值 = " + node.val); - /* 插入结点 */ + /* 插入节点 */ node = bst.insert(16); - System.out.println("\n插入结点 16 后,二叉树为\n"); + System.out.println("\n插入节点 16 后,二叉树为\n"); PrintUtil.printTree(bst.getRoot()); - /* 删除结点 */ + /* 删除节点 */ bst.remove(1); - System.out.println("\n删除结点 1 后,二叉树为\n"); + System.out.println("\n删除节点 1 后,二叉树为\n"); PrintUtil.printTree(bst.getRoot()); bst.remove(2); - System.out.println("\n删除结点 2 后,二叉树为\n"); + System.out.println("\n删除节点 2 后,二叉树为\n"); PrintUtil.printTree(bst.getRoot()); bst.remove(4); - System.out.println("\n删除结点 4 后,二叉树为\n"); + System.out.println("\n删除节点 4 后,二叉树为\n"); PrintUtil.printTree(bst.getRoot()); } } diff --git a/codes/java/chapter_tree/binary_tree.java b/codes/java/chapter_tree/binary_tree.java index 65a511e8..d71e1f8d 100644 --- a/codes/java/chapter_tree/binary_tree.java +++ b/codes/java/chapter_tree/binary_tree.java @@ -11,7 +11,7 @@ import include.*; public class binary_tree { public static void main(String[] args) { /* 初始化二叉树 */ - // 初始化结点 + // 初始化节点 TreeNode n1 = new TreeNode(1); TreeNode n2 = new TreeNode(2); TreeNode n3 = new TreeNode(3); @@ -25,16 +25,16 @@ public class binary_tree { System.out.println("\n初始化二叉树\n"); PrintUtil.printTree(n1); - /* 插入与删除结点 */ + /* 插入与删除节点 */ TreeNode P = new TreeNode(0); - // 在 n1 -> n2 中间插入结点 P + // 在 n1 -> n2 中间插入节点 P n1.left = P; P.left = n2; - System.out.println("\n插入结点 P 后\n"); + System.out.println("\n插入节点 P 后\n"); PrintUtil.printTree(n1); - // 删除结点 P + // 删除节点 P n1.left = n2; - System.out.println("\n删除结点 P 后\n"); + System.out.println("\n删除节点 P 后\n"); PrintUtil.printTree(n1); } } diff --git a/codes/java/chapter_tree/binary_tree_bfs.java b/codes/java/chapter_tree/binary_tree_bfs.java index 246921dc..e631420f 100644 --- a/codes/java/chapter_tree/binary_tree_bfs.java +++ b/codes/java/chapter_tree/binary_tree_bfs.java @@ -12,17 +12,17 @@ import java.util.*; public class binary_tree_bfs { /* 层序遍历 */ static List levelOrder(TreeNode root) { - // 初始化队列,加入根结点 + // 初始化队列,加入根节点 Queue queue = new LinkedList<>() {{ add(root); }}; // 初始化一个列表,用于保存遍历序列 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); // 左子结点入队 + queue.offer(node.left); // 左子节点入队 if (node.right != null) - queue.offer(node.right); // 右子结点入队 + queue.offer(node.right); // 右子节点入队 } return list; } @@ -36,6 +36,6 @@ public class binary_tree_bfs { /* 层序遍历 */ List list = levelOrder(root); - System.out.println("\n层序遍历的结点打印序列 = " + list); + System.out.println("\n层序遍历的节点打印序列 = " + list); } } diff --git a/codes/java/chapter_tree/binary_tree_dfs.java b/codes/java/chapter_tree/binary_tree_dfs.java index 9f2d0507..4c27bbcd 100644 --- a/codes/java/chapter_tree/binary_tree_dfs.java +++ b/codes/java/chapter_tree/binary_tree_dfs.java @@ -16,7 +16,7 @@ public class binary_tree_dfs { /* 前序遍历 */ static void preOrder(TreeNode root) { if (root == null) return; - // 访问优先级:根结点 -> 左子树 -> 右子树 + // 访问优先级:根节点 -> 左子树 -> 右子树 list.add(root.val); preOrder(root.left); preOrder(root.right); @@ -25,7 +25,7 @@ public class binary_tree_dfs { /* 中序遍历 */ static void inOrder(TreeNode root) { if (root == null) return; - // 访问优先级:左子树 -> 根结点 -> 右子树 + // 访问优先级:左子树 -> 根节点 -> 右子树 inOrder(root.left); list.add(root.val); inOrder(root.right); @@ -34,7 +34,7 @@ public class binary_tree_dfs { /* 后序遍历 */ static void postOrder(TreeNode root) { if (root == null) return; - // 访问优先级:左子树 -> 右子树 -> 根结点 + // 访问优先级:左子树 -> 右子树 -> 根节点 postOrder(root.left); postOrder(root.right); list.add(root.val); @@ -50,16 +50,16 @@ public class binary_tree_dfs { /* 前序遍历 */ list.clear(); preOrder(root); - System.out.println("\n前序遍历的结点打印序列 = " + list); + System.out.println("\n前序遍历的节点打印序列 = " + list); /* 中序遍历 */ list.clear(); inOrder(root); - System.out.println("\n中序遍历的结点打印序列 = " + list); + System.out.println("\n中序遍历的节点打印序列 = " + list); /* 后序遍历 */ list.clear(); postOrder(root); - System.out.println("\n后序遍历的结点打印序列 = " + list); + System.out.println("\n后序遍历的节点打印序列 = " + list); } } diff --git a/codes/java/include/TreeNode.java b/codes/java/include/TreeNode.java index 22a34974..29cdc947 100644 --- a/codes/java/include/TreeNode.java +++ b/codes/java/include/TreeNode.java @@ -12,10 +12,10 @@ import java.util.*; * Definition for a binary tree node. */ public class TreeNode { - public int val; // 结点值 - public int height; // 结点高度 - public TreeNode left; // 左子结点引用 - public TreeNode right; // 右子结点引用 + public int val; // 节点值 + public int height; // 节点高度 + public TreeNode left; // 左子节点引用 + public TreeNode right; // 右子节点引用 public TreeNode(int x) { val = x; diff --git a/codes/javascript/chapter_array_and_linkedlist/linked_list.js b/codes/javascript/chapter_array_and_linkedlist/linked_list.js index 2832ea06..e061cb9f 100644 --- a/codes/javascript/chapter_array_and_linkedlist/linked_list.js +++ b/codes/javascript/chapter_array_and_linkedlist/linked_list.js @@ -7,14 +7,14 @@ const { printLinkedList } = require("../modules/PrintUtil"); const { ListNode } = require("../modules/ListNode"); -/* 在链表的结点 n0 之后插入结点 P */ +/* 在链表的节点 n0 之后插入节点 P */ function insert(n0, P) { const n1 = n0.next; P.next = n1; n0.next = P; } -/* 删除链表的结点 n0 之后的首个结点 */ +/* 删除链表的节点 n0 之后的首个节点 */ function remove(n0) { if (!n0.next) return; @@ -24,7 +24,7 @@ function remove(n0) { n0.next = n1; } -/* 访问链表中索引为 index 的结点 */ +/* 访问链表中索引为 index 的节点 */ function access(head, index) { for (let i = 0; i < index; i++) { if (!head) { @@ -35,7 +35,7 @@ function access(head, index) { return head; } -/* 在链表中查找值为 target 的首个结点 */ +/* 在链表中查找值为 target 的首个节点 */ function find(head, target) { let index = 0; while (head !== null) { @@ -50,7 +50,7 @@ function find(head, target) { /* Driver Code */ /* 初始化链表 */ -// 初始化各个结点 +// 初始化各个节点 const n0 = new ListNode(1); const n1 = new ListNode(3); const n2 = new ListNode(2); @@ -64,20 +64,20 @@ n3.next = n4; console.log("初始化的链表为"); printLinkedList(n0); -/* 插入结点 */ +/* 插入节点 */ insert(n0, new ListNode(0)); -console.log("插入结点后的链表为"); +console.log("插入节点后的链表为"); printLinkedList(n0); -/* 删除结点 */ +/* 删除节点 */ remove(n0); -console.log("删除结点后的链表为"); +console.log("删除节点后的链表为"); printLinkedList(n0); -/* 访问结点 */ +/* 访问节点 */ const node = access(n0, 3); -console.log("链表中索引 3 处的结点的值 = " + node.val); +console.log("链表中索引 3 处的节点的值 = " + node.val); -/* 查找结点 */ +/* 查找节点 */ const index = find(n0, 2); -console.log("链表中值为 2 的结点的索引 = " + index); +console.log("链表中值为 2 的节点的索引 = " + index); diff --git a/codes/javascript/chapter_heap/my_heap.js b/codes/javascript/chapter_heap/my_heap.js index 10cb2f8c..44735c28 100644 --- a/codes/javascript/chapter_heap/my_heap.js +++ b/codes/javascript/chapter_heap/my_heap.js @@ -14,23 +14,23 @@ class MaxHeap { constructor(nums) { // 将列表元素原封不动添加进堆 this.#maxHeap = nums === undefined ? [] : [...nums]; - // 堆化除叶结点以外的其他所有结点 + // 堆化除叶节点以外的其他所有节点 for (let i = this.#parent(this.size() - 1); i >= 0; i--) { this.#siftDown(i); } } - /* 获取左子结点索引 */ + /* 获取左子节点索引 */ #left(i) { return 2 * i + 1; } - /* 获取右子结点索引 */ + /* 获取右子节点索引 */ #right(i) { return 2 * i + 2; } - /* 获取父结点索引 */ + /* 获取父节点索引 */ #parent(i) { return Math.floor((i - 1) / 2); // 向下整除 } @@ -61,20 +61,20 @@ class MaxHeap { /* 元素入堆 */ push(val) { - // 添加结点 + // 添加节点 this.#maxHeap.push(val); // 从底至顶堆化 this.#siftUp(this.size() - 1); } - /* 从结点 i 开始,从底至顶堆化 */ + /* 从节点 i 开始,从底至顶堆化 */ #siftUp(i) { while (true) { - // 获取结点 i 的父结点 + // 获取节点 i 的父节点 const p = this.#parent(i); - // 当“越过根结点”或“结点无需修复”时,结束堆化 + // 当“越过根节点”或“节点无需修复”时,结束堆化 if (p < 0 || this.#maxHeap[i] <= this.#maxHeap[p]) break; - // 交换两结点 + // 交换两节点 this.#swap(i, p); // 循环向上堆化 i = p; @@ -85,9 +85,9 @@ class MaxHeap { pop() { // 判空处理 if (this.isEmpty()) throw new Error("堆为空"); - // 交换根结点与最右叶结点(即交换首元素与尾元素) + // 交换根节点与最右叶节点(即交换首元素与尾元素) this.#swap(0, this.size() - 1); - // 删除结点 + // 删除节点 const val = this.#maxHeap.pop(); // 从顶至底堆化 this.#siftDown(0); @@ -95,18 +95,18 @@ class MaxHeap { return val; } - /* 从结点 i 开始,从顶至底堆化 */ + /* 从节点 i 开始,从顶至底堆化 */ #siftDown(i) { while (true) { - // 判断结点 i, l, r 中值最大的结点,记为 ma + // 判断节点 i, l, r 中值最大的节点,记为 ma const l = this.#left(i), r = this.#right(i); let ma = i; if (l < this.size() && this.#maxHeap[l] > this.#maxHeap[ma]) ma = l; if (r < this.size() && this.#maxHeap[r] > this.#maxHeap[ma]) ma = r; - // 若结点 i 最大或索引 l, r 越界,则无需继续堆化,跳出 + // 若节点 i 最大或索引 l, r 越界,则无需继续堆化,跳出 if (ma == i) break; - // 交换两结点 + // 交换两节点 this.#swap(i, ma); // 循环向下堆化 i = ma; diff --git a/codes/javascript/chapter_searching/hashing_search.js b/codes/javascript/chapter_searching/hashing_search.js index d71a9aba..56fac093 100644 --- a/codes/javascript/chapter_searching/hashing_search.js +++ b/codes/javascript/chapter_searching/hashing_search.js @@ -15,7 +15,7 @@ function hashingSearchArray(map, target) { /* 哈希查找(链表) */ function hashingSearchLinkedList(map, target) { - // 哈希表的 key: 目标结点值,value: 结点对象 + // 哈希表的 key: 目标节点值,value: 节点对象 // 若哈希表中无此 key ,返回 null return map.has(target) ? map.get(target) : null; } @@ -38,8 +38,8 @@ let head = arrToLinkedList(nums) // 初始化哈希表 const map1 = new Map(); while (head != null) { - map1.set(head.val, head); // key: 结点值,value: 结点 + map1.set(head.val, head); // key: 节点值,value: 节点 head = head.next; } const node = hashingSearchLinkedList(map1, target); -console.log("目标结点值 3 的对应结点对象为", node); +console.log("目标节点值 3 的对应节点对象为", node); diff --git a/codes/javascript/chapter_searching/linear_search.js b/codes/javascript/chapter_searching/linear_search.js index 5a655703..1e619542 100644 --- a/codes/javascript/chapter_searching/linear_search.js +++ b/codes/javascript/chapter_searching/linear_search.js @@ -23,13 +23,13 @@ function linearSearchArray(nums, target) { function linearSearchLinkedList(head, target) { // 遍历链表 while(head) { - // 找到目标结点,返回之 + // 找到目标节点,返回之 if(head.val === target) { return head; } head = head.next; } - // 未找到目标结点,返回 null + // 未找到目标节点,返回 null return null; } @@ -44,4 +44,4 @@ console.log("目标元素 3 的索引 = " + index); /* 在链表中执行线性查找 */ const head = arrToLinkedList(nums); const node = linearSearchLinkedList(head, target); -console.log("目标结点值 3 的对应结点对象为 ", node); +console.log("目标节点值 3 的对应节点对象为 ", node); diff --git a/codes/javascript/chapter_stack_and_queue/linkedlist_deque.js b/codes/javascript/chapter_stack_and_queue/linkedlist_deque.js index bd9eb4ea..3dfc9583 100644 --- a/codes/javascript/chapter_stack_and_queue/linkedlist_deque.js +++ b/codes/javascript/chapter_stack_and_queue/linkedlist_deque.js @@ -4,11 +4,11 @@ * Author: Zhuo Qinyue (1403450829@qq.com) */ -/* 双向链表结点 */ +/* 双向链表节点 */ class ListNode { - prev; // 前驱结点引用 (指针) - next; // 后继结点引用 (指针) - val; // 结点值 + prev; // 前驱节点引用 (指针) + next; // 后继节点引用 (指针) + val; // 节点值 constructor(val) { this.val = val; @@ -19,8 +19,8 @@ class ListNode { /* 基于双向链表实现的双向队列 */ class LinkedListDeque { - #front; // 头结点 front - #rear; // 尾结点 rear + #front; // 头节点 front + #rear; // 尾节点 rear #queSize; // 双向队列的长度 constructor() { @@ -40,7 +40,7 @@ class LinkedListDeque { // 将 node 添加至链表尾部 this.#rear.next = node; node.prev = this.#rear; - this.#rear = node; // 更新尾结点 + this.#rear = node; // 更新尾节点 } this.#queSize++; } @@ -56,7 +56,7 @@ class LinkedListDeque { // 将 node 添加至链表头部 this.#front.prev = node; node.next = this.#front; - this.#front = node; // 更新头结点 + this.#front = node; // 更新头节点 } this.#queSize++; } @@ -66,14 +66,14 @@ class LinkedListDeque { if (this.#queSize === 0) { return null; } - const value = this.#rear.val; // 存储尾结点值 - // 删除尾结点 + const value = this.#rear.val; // 存储尾节点值 + // 删除尾节点 let temp = this.#rear.prev; if (temp !== null) { temp.next = null; this.#rear.prev = null; } - this.#rear = temp; // 更新尾结点 + this.#rear = temp; // 更新尾节点 this.#queSize--; return value; } @@ -83,14 +83,14 @@ class LinkedListDeque { if (this.#queSize === 0) { return null; } - const value = this.#front.val; // 存储尾结点值 - // 删除头结点 + const value = this.#front.val; // 存储尾节点值 + // 删除头节点 let temp = this.#front.next; if (temp !== null) { temp.prev = null; this.#front.next = null; } - this.#front = temp; // 更新头结点 + this.#front = temp; // 更新头节点 this.#queSize--; return value; } diff --git a/codes/javascript/chapter_stack_and_queue/linkedlist_queue.js b/codes/javascript/chapter_stack_and_queue/linkedlist_queue.js index 71634c9b..315e0de8 100644 --- a/codes/javascript/chapter_stack_and_queue/linkedlist_queue.js +++ b/codes/javascript/chapter_stack_and_queue/linkedlist_queue.js @@ -8,8 +8,8 @@ const { ListNode } = require("../modules/ListNode"); /* 基于链表实现的队列 */ class LinkedListQueue { - #front; // 头结点 #front - #rear; // 尾结点 #rear + #front; // 头节点 #front + #rear; // 尾节点 #rear #queSize = 0; constructor() { @@ -29,13 +29,13 @@ class LinkedListQueue { /* 入队 */ push(num) { - // 尾结点后添加 num + // 尾节点后添加 num const node = new ListNode(num); - // 如果队列为空,则令头、尾结点都指向该结点 + // 如果队列为空,则令头、尾节点都指向该节点 if (!this.#front) { this.#front = node; this.#rear = node; - // 如果队列不为空,则将该结点添加到尾结点后 + // 如果队列不为空,则将该节点添加到尾节点后 } else { this.#rear.next = node; this.#rear = node; @@ -46,7 +46,7 @@ class LinkedListQueue { /* 出队 */ pop() { const num = this.peek(); - // 删除头结点 + // 删除头节点 this.#front = this.#front.next; this.#queSize--; return num; diff --git a/codes/javascript/chapter_stack_and_queue/linkedlist_stack.js b/codes/javascript/chapter_stack_and_queue/linkedlist_stack.js index 6c006f3a..a17d24bd 100644 --- a/codes/javascript/chapter_stack_and_queue/linkedlist_stack.js +++ b/codes/javascript/chapter_stack_and_queue/linkedlist_stack.js @@ -8,7 +8,7 @@ const { ListNode } = require("../modules/ListNode"); /* 基于链表实现的栈 */ class LinkedListStack { - #stackPeek; // 将头结点作为栈顶 + #stackPeek; // 将头节点作为栈顶 #stkSize = 0; // 栈的长度 constructor() { diff --git a/codes/javascript/chapter_tree/avl_tree.js b/codes/javascript/chapter_tree/avl_tree.js index 65c4a57d..13a9d6ee 100644 --- a/codes/javascript/chapter_tree/avl_tree.js +++ b/codes/javascript/chapter_tree/avl_tree.js @@ -11,26 +11,26 @@ const { printTree } = require("../modules/PrintUtil"); class AVLTree { /*构造方法*/ constructor() { - this.root = null; //根结点 + this.root = null; //根节点 } - /* 获取结点高度 */ + /* 获取节点高度 */ height(node) { - // 空结点高度为 -1 ,叶结点高度为 0 + // 空节点高度为 -1 ,叶节点高度为 0 return node === null ? -1 : node.height; } - /* 更新结点高度 */ + /* 更新节点高度 */ #updateHeight(node) { - // 结点高度等于最高子树高度 + 1 + // 节点高度等于最高子树高度 + 1 node.height = Math.max(this.height(node.left), this.height(node.right)) + 1; } /* 获取平衡因子 */ balanceFactor(node) { - // 空结点平衡因子为 0 + // 空节点平衡因子为 0 if (node === null) return 0; - // 结点平衡因子 = 左子树高度 - 右子树高度 + // 节点平衡因子 = 左子树高度 - 右子树高度 return this.height(node.left) - this.height(node.right); } @@ -41,10 +41,10 @@ class AVLTree { // 以 child 为原点,将 node 向右旋转 child.right = node; node.left = grandChild; - // 更新结点高度 + // 更新节点高度 this.#updateHeight(node); this.#updateHeight(child); - // 返回旋转后子树的根结点 + // 返回旋转后子树的根节点 return child; } @@ -55,16 +55,16 @@ class AVLTree { // 以 child 为原点,将 node 向左旋转 child.left = node; node.right = grandChild; - // 更新结点高度 + // 更新节点高度 this.#updateHeight(node); this.#updateHeight(child); - // 返回旋转后子树的根结点 + // 返回旋转后子树的根节点 return child; } /* 执行旋转操作,使该子树重新恢复平衡 */ #rotate(node) { - // 获取结点 node 的平衡因子 + // 获取节点 node 的平衡因子 const balanceFactor = this.balanceFactor(node); // 左偏树 if (balanceFactor > 1) { @@ -92,103 +92,103 @@ class AVLTree { return node; } - /* 插入结点 */ + /* 插入节点 */ insert(val) { this.root = this.#insertHelper(this.root, val); return this.root; } - /* 递归插入结点(辅助方法) */ + /* 递归插入节点(辅助方法) */ #insertHelper(node, val) { if (node === null) return new TreeNode(val); - /* 1. 查找插入位置,并插入结点 */ + /* 1. 查找插入位置,并插入节点 */ if (val < node.val) node.left = this.#insertHelper(node.left, val); else if (val > node.val) node.right = this.#insertHelper(node.right, val); - else return node; // 重复结点不插入,直接返回 - this.#updateHeight(node); // 更新结点高度 + else return node; // 重复节点不插入,直接返回 + this.#updateHeight(node); // 更新节点高度 /* 2. 执行旋转操作,使该子树重新恢复平衡 */ node = this.#rotate(node); - // 返回子树的根结点 + // 返回子树的根节点 return node; } - /* 删除结点 */ + /* 删除节点 */ remove(val) { this.root = this.#removeHelper(this.root, val); return this.root; } - /* 递归删除结点(辅助方法) */ + /* 递归删除节点(辅助方法) */ #removeHelper(node, val) { if (node === null) return null; - /* 1. 查找结点,并删除之 */ + /* 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 并返回 + // 子节点数量 = 0 ,直接删除 node 并返回 if (child === null) return null; - // 子结点数量 = 1 ,直接删除 node + // 子节点数量 = 1 ,直接删除 node else node = child; } else { - // 子结点数量 = 2 ,则将中序遍历的下个结点删除,并用该结点替换当前结点 + // 子节点数量 = 2 ,则将中序遍历的下个节点删除,并用该节点替换当前节点 const temp = this.#getInOrderNext(node.right); node.right = this.#removeHelper(node.right, temp.val); node.val = temp.val; } } - this.#updateHeight(node); // 更新结点高度 + this.#updateHeight(node); // 更新节点高度 /* 2. 执行旋转操作,使该子树重新恢复平衡 */ node = this.#rotate(node); - // 返回子树的根结点 + // 返回子树的根节点 return node; } - /* 获取中序遍历中的下一个结点(仅适用于 root 有左子结点的情况) */ + /* 获取中序遍历中的下一个节点(仅适用于 root 有左子节点的情况) */ #getInOrderNext(node) { if (node === null) return node; - // 循环访问左子结点,直到叶结点时为最小结点,跳出 + // 循环访问左子节点,直到叶节点时为最小节点,跳出 while (node.left !== null) { node = node.left; } return node; } - /* 查找结点 */ + /* 查找节点 */ search(val) { let cur = this.root; - // 循环查找,越过叶结点后跳出 + // 循环查找,越过叶节点后跳出 while (cur !== null) { - // 目标结点在 cur 的右子树中 + // 目标节点在 cur 的右子树中 if (cur.val < val) cur = cur.right; - // 目标结点在 cur 的左子树中 + // 目标节点在 cur 的左子树中 else if (cur.val > val) cur = cur.left; - // 找到目标结点,跳出循环 + // 找到目标节点,跳出循环 else break; } - // 返回目标结点 + // 返回目标节点 return cur; } } function testInsert(tree, val) { tree.insert(val); - console.log("\n插入结点 " + val + " 后,AVL 树为"); + console.log("\n插入节点 " + val + " 后,AVL 树为"); printTree(tree.root); } function testRemove(tree, val) { tree.remove(val); - console.log("\n删除结点 " + val + " 后,AVL 树为"); + console.log("\n删除节点 " + val + " 后,AVL 树为"); printTree(tree.root); } /* Driver Code */ /* 初始化空 AVL 树 */ const avlTree = new AVLTree(); -/* 插入结点 */ -// 请关注插入结点后,AVL 树是如何保持平衡的 +/* 插入节点 */ +// 请关注插入节点后,AVL 树是如何保持平衡的 testInsert(avlTree, 1); testInsert(avlTree, 2); testInsert(avlTree, 3); @@ -200,15 +200,15 @@ testInsert(avlTree, 9); testInsert(avlTree, 10); testInsert(avlTree, 6); -/* 插入重复结点 */ +/* 插入重复节点 */ testInsert(avlTree, 7); -/* 删除结点 */ -// 请关注删除结点后,AVL 树是如何保持平衡的 -testRemove(avlTree, 8); // 删除度为 0 的结点 -testRemove(avlTree, 5); // 删除度为 1 的结点 -testRemove(avlTree, 4); // 删除度为 2 的结点 +/* 删除节点 */ +// 请关注删除节点后,AVL 树是如何保持平衡的 +testRemove(avlTree, 8); // 删除度为 0 的节点 +testRemove(avlTree, 5); // 删除度为 1 的节点 +testRemove(avlTree, 4); // 删除度为 2 的节点 -/* 查询结点 */ +/* 查询节点 */ const node = avlTree.search(7); -console.log("\n查找到的结点对象为", node, ",结点值 = " + node.val); +console.log("\n查找到的节点对象为", node, ",节点值 = " + node.val); diff --git a/codes/javascript/chapter_tree/binary_search_tree.js b/codes/javascript/chapter_tree/binary_search_tree.js index 769124a3..2ed342d7 100644 --- a/codes/javascript/chapter_tree/binary_search_tree.js +++ b/codes/javascript/chapter_tree/binary_search_tree.js @@ -15,7 +15,7 @@ function BinarySearchTree(nums) { root = buildTree(nums, 0, nums.length - 1); // 构建二叉搜索树 } -/* 获取二叉树根结点 */ +/* 获取二叉树根节点 */ function getRoot() { return root; } @@ -23,7 +23,7 @@ function getRoot() { /* 构建二叉搜索树 */ function buildTree(nums, i, j) { if (i > j) return null; - // 将数组中间结点作为根结点 + // 将数组中间节点作为根节点 let mid = Math.floor((i + j) / 2); let root = new TreeNode(nums[mid]); // 递归建立左子树和右子树 @@ -32,30 +32,30 @@ function buildTree(nums, i, j) { return root; } -/* 查找结点 */ +/* 查找节点 */ function search(num) { let cur = root; - // 循环查找,越过叶结点后跳出 + // 循环查找,越过叶节点后跳出 while (cur !== null) { - // 目标结点在 cur 的右子树中 + // 目标节点在 cur 的右子树中 if (cur.val < num) cur = cur.right; - // 目标结点在 cur 的左子树中 + // 目标节点在 cur 的左子树中 else if (cur.val > num) cur = cur.left; - // 找到目标结点,跳出循环 + // 找到目标节点,跳出循环 else break; } - // 返回目标结点 + // 返回目标节点 return cur; } -/* 插入结点 */ +/* 插入节点 */ function insert(num) { // 若树为空,直接提前返回 if (root === null) return null; let cur = root, pre = null; - // 循环查找,越过叶结点后跳出 + // 循环查找,越过叶节点后跳出 while (cur !== null) { - // 找到重复结点,直接返回 + // 找到重复节点,直接返回 if (cur.val === num) return null; pre = cur; // 插入位置在 cur 的右子树中 @@ -63,44 +63,44 @@ function insert(num) { // 插入位置在 cur 的左子树中 else cur = cur.left; } - // 插入结点 val + // 插入节点 val let node = new TreeNode(num); if (pre.val < num) pre.right = node; else pre.left = node; return node; } -/* 删除结点 */ +/* 删除节点 */ function remove(num) { // 若树为空,直接提前返回 if (root === null) return null; let cur = root, pre = null; - // 循环查找,越过叶结点后跳出 + // 循环查找,越过叶节点后跳出 while (cur !== null) { - // 找到待删除结点,跳出循环 + // 找到待删除节点,跳出循环 if (cur.val === num) break; pre = cur; - // 待删除结点在 cur 的右子树中 + // 待删除节点在 cur 的右子树中 if (cur.val < num) cur = cur.right; - // 待删除结点在 cur 的左子树中 + // 待删除节点在 cur 的左子树中 else cur = cur.left; } - // 若无待删除结点,则直接返回 + // 若无待删除节点,则直接返回 if (cur === null) return null; - // 子结点数量 = 0 or 1 + // 子节点数量 = 0 or 1 if (cur.left === null || cur.right === null) { - // 当子结点数量 = 0 / 1 时, child = null / 该子结点 + // 当子节点数量 = 0 / 1 时, child = null / 该子节点 let child = cur.left !== null ? cur.left : cur.right; - // 删除结点 cur + // 删除节点 cur if (pre.left === cur) pre.left = child; else pre.right = child; } - // 子结点数量 = 2 + // 子节点数量 = 2 else { - // 获取中序遍历中 cur 的下一个结点 + // 获取中序遍历中 cur 的下一个节点 let nex = getInOrderNext(cur.right); let tmp = nex.val; - // 递归删除结点 nex + // 递归删除节点 nex remove(nex.val); // 将 nex 的值复制给 cur cur.val = tmp; @@ -108,10 +108,10 @@ function remove(num) { return cur; } -/* 获取中序遍历中的下一个结点(仅适用于 root 有左子结点的情况) */ +/* 获取中序遍历中的下一个节点(仅适用于 root 有左子节点的情况) */ function getInOrderNext(root) { if (root === null) return root; - // 循环访问左子结点,直到叶结点时为最小结点,跳出 + // 循环访问左子节点,直到叶节点时为最小节点,跳出 while (root.left !== null) { root = root.left; } @@ -125,22 +125,22 @@ BinarySearchTree(nums); console.log("\n初始化的二叉树为\n"); printTree(getRoot()); -/* 查找结点 */ +/* 查找节点 */ let node = search(7); -console.log("\n查找到的结点对象为 " + node + ",结点值 = " + node.val); +console.log("\n查找到的节点对象为 " + node + ",节点值 = " + node.val); -/* 插入结点 */ +/* 插入节点 */ node = insert(16); -console.log("\n插入结点 16 后,二叉树为\n"); +console.log("\n插入节点 16 后,二叉树为\n"); printTree(getRoot()); -/* 删除结点 */ +/* 删除节点 */ remove(1); -console.log("\n删除结点 1 后,二叉树为\n"); +console.log("\n删除节点 1 后,二叉树为\n"); printTree(getRoot()); remove(2); -console.log("\n删除结点 2 后,二叉树为\n"); +console.log("\n删除节点 2 后,二叉树为\n"); printTree(getRoot()); remove(4); -console.log("\n删除结点 4 后,二叉树为\n"); +console.log("\n删除节点 4 后,二叉树为\n"); printTree(getRoot()); diff --git a/codes/javascript/chapter_tree/binary_tree.js b/codes/javascript/chapter_tree/binary_tree.js index 7b28f972..59f4ce37 100644 --- a/codes/javascript/chapter_tree/binary_tree.js +++ b/codes/javascript/chapter_tree/binary_tree.js @@ -8,7 +8,7 @@ const { TreeNode } = require("../modules/TreeNode"); const { printTree } = require("../modules/PrintUtil"); /* 初始化二叉树 */ -// 初始化结点 +// 初始化节点 let n1 = new TreeNode(1), n2 = new TreeNode(2), n3 = new TreeNode(3), @@ -22,14 +22,14 @@ n2.right = n5; console.log("\n初始化二叉树\n"); printTree(n1); -/* 插入与删除结点 */ +/* 插入与删除节点 */ const P = new TreeNode(0); -// 在 n1 -> n2 中间插入结点 P +// 在 n1 -> n2 中间插入节点 P n1.left = P; P.left = n2; -console.log("\n插入结点 P 后\n"); +console.log("\n插入节点 P 后\n"); printTree(n1); -// 删除结点 P +// 删除节点 P n1.left = n2; -console.log("\n删除结点 P 后\n"); +console.log("\n删除节点 P 后\n"); printTree(n1); diff --git a/codes/javascript/chapter_tree/binary_tree_bfs.js b/codes/javascript/chapter_tree/binary_tree_bfs.js index 46941ca0..0fdab504 100644 --- a/codes/javascript/chapter_tree/binary_tree_bfs.js +++ b/codes/javascript/chapter_tree/binary_tree_bfs.js @@ -9,17 +9,17 @@ const { printTree } = require("../modules/PrintUtil"); /* 层序遍历 */ function levelOrder(root) { - // 初始化队列,加入根结点 + // 初始化队列,加入根节点 const queue = [root]; // 初始化一个列表,用于保存遍历序列 const list = []; while (queue.length) { let node = queue.shift(); // 队列出队 - list.push(node.val); // 保存结点值 + 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; @@ -34,4 +34,4 @@ printTree(root); /* 层序遍历 */ const list = levelOrder(root); -console.log("\n层序遍历的结点打印序列 = " + list); +console.log("\n层序遍历的节点打印序列 = " + list); diff --git a/codes/javascript/chapter_tree/binary_tree_dfs.js b/codes/javascript/chapter_tree/binary_tree_dfs.js index 8ad0686c..59a99038 100644 --- a/codes/javascript/chapter_tree/binary_tree_dfs.js +++ b/codes/javascript/chapter_tree/binary_tree_dfs.js @@ -13,7 +13,7 @@ const list = []; /* 前序遍历 */ function preOrder(root) { if (root === null) return; - // 访问优先级:根结点 -> 左子树 -> 右子树 + // 访问优先级:根节点 -> 左子树 -> 右子树 list.push(root.val); preOrder(root.left); preOrder(root.right); @@ -22,7 +22,7 @@ function preOrder(root) { /* 中序遍历 */ function inOrder(root) { if (root === null) return; - // 访问优先级:左子树 -> 根结点 -> 右子树 + // 访问优先级:左子树 -> 根节点 -> 右子树 inOrder(root.left); list.push(root.val); inOrder(root.right); @@ -31,7 +31,7 @@ function inOrder(root) { /* 后序遍历 */ function postOrder(root) { if (root === null) return; - // 访问优先级:左子树 -> 右子树 -> 根结点 + // 访问优先级:左子树 -> 右子树 -> 根节点 postOrder(root.left); postOrder(root.right); list.push(root.val); @@ -47,14 +47,14 @@ printTree(root); /* 前序遍历 */ list.length = 0; preOrder(root); -console.log("\n前序遍历的结点打印序列 = " + list); +console.log("\n前序遍历的节点打印序列 = " + list); /* 中序遍历 */ list.length = 0; inOrder(root); -console.log("\n中序遍历的结点打印序列 = " + list); +console.log("\n中序遍历的节点打印序列 = " + list); /* 后序遍历 */ list.length = 0; postOrder(root); -console.log("\n后序遍历的结点打印序列 = " + list); +console.log("\n后序遍历的节点打印序列 = " + list); diff --git a/codes/javascript/modules/TreeNode.js b/codes/javascript/modules/TreeNode.js index a2ac066e..e6bd068a 100644 --- a/codes/javascript/modules/TreeNode.js +++ b/codes/javascript/modules/TreeNode.js @@ -8,10 +8,10 @@ * Definition for a binary tree node. */ class TreeNode { - val; // 结点值 - left; // 左子结点指针 - right; // 右子结点指针 - height; //结点高度 + val; // 节点值 + left; // 左子节点指针 + right; // 右子节点指针 + height; //节点高度 constructor(val, left, right, height) { this.val = val === undefined ? 0 : val; this.left = left === undefined ? null : left; diff --git a/codes/python/chapter_array_and_linkedlist/linked_list.py b/codes/python/chapter_array_and_linkedlist/linked_list.py index 781e0ba4..29179f68 100644 --- a/codes/python/chapter_array_and_linkedlist/linked_list.py +++ b/codes/python/chapter_array_and_linkedlist/linked_list.py @@ -9,13 +9,13 @@ sys.path.append(osp.dirname(osp.dirname(osp.abspath(__file__)))) from modules import * def insert(n0: ListNode, P: ListNode) -> None: - """ 在链表的结点 n0 之后插入结点 P """ + """ 在链表的节点 n0 之后插入节点 P """ n1 = n0.next P.next = n1 n0.next = P def remove(n0: ListNode) -> None: - """ 删除链表的结点 n0 之后的首个结点 """ + """ 删除链表的节点 n0 之后的首个节点 """ if not n0.next: return # n0 -> P -> n1 @@ -24,7 +24,7 @@ def remove(n0: ListNode) -> None: n0.next = n1 def access(head: ListNode, index: int) -> ListNode | None: - """ 访问链表中索引为 index 的结点 """ + """ 访问链表中索引为 index 的节点 """ for _ in range(index): if not head: return None @@ -32,7 +32,7 @@ def access(head: ListNode, index: int) -> ListNode | None: return head def find(head: ListNode, target: int) -> int: - """ 在链表中查找值为 target 的首个结点 """ + """ 在链表中查找值为 target 的首个节点 """ index = 0 while head: if head.val == target: @@ -45,7 +45,7 @@ def find(head: ListNode, target: int) -> int: """ Driver Code """ if __name__ == "__main__": """ 初始化链表 """ - # 初始化各个结点 + # 初始化各个节点 n0 = ListNode(1) n1 = ListNode(3) n2 = ListNode(2) @@ -59,20 +59,20 @@ if __name__ == "__main__": print("初始化的链表为") print_linked_list(n0) - """ 插入结点 """ + """ 插入节点 """ insert(n0, ListNode(0)) - print("插入结点后的链表为") + print("插入节点后的链表为") print_linked_list(n0) - """ 删除结点 """ + """ 删除节点 """ remove(n0) - print("删除结点后的链表为") + print("删除节点后的链表为") print_linked_list(n0) - """ 访问结点 """ + """ 访问节点 """ node: ListNode = access(n0, 3) - print("链表中索引 3 处的结点的值 = {}".format(node.val)) + print("链表中索引 3 处的节点的值 = {}".format(node.val)) - """ 查找结点 """ + """ 查找节点 """ index: int = find(n0, 2) - print("链表中值为 2 的结点的索引 = {}".format(index)) + print("链表中值为 2 的节点的索引 = {}".format(index)) diff --git a/codes/python/chapter_heap/my_heap.py b/codes/python/chapter_heap/my_heap.py index 3bc5d337..69dd2ef9 100644 --- a/codes/python/chapter_heap/my_heap.py +++ b/codes/python/chapter_heap/my_heap.py @@ -14,20 +14,20 @@ class MaxHeap: """ 构造方法 """ # 将列表元素原封不动添加进堆 self.max_heap = nums - # 堆化除叶结点以外的其他所有结点 + # 堆化除叶节点以外的其他所有节点 for i in range(self.parent(self.size() - 1), -1, -1): self.sift_down(i) def left(self, i: int) -> int: - """ 获取左子结点索引 """ + """ 获取左子节点索引 """ return 2 * i + 1 def right(self, i: int) -> int: - """ 获取右子结点索引 """ + """ 获取右子节点索引 """ return 2 * i + 2 def parent(self, i: int) -> int: - """ 获取父结点索引 """ + """ 获取父节点索引 """ return (i - 1) // 2 # 向下整除 def swap(self, i: int, j: int): @@ -49,20 +49,20 @@ class MaxHeap: def push(self, val: int): """ 元素入堆 """ - # 添加结点 + # 添加节点 self.max_heap.append(val) # 从底至顶堆化 self.sift_up(self.size() - 1) def sift_up(self, i: int): - """ 从结点 i 开始,从底至顶堆化 """ + """ 从节点 i 开始,从底至顶堆化 """ while True: - # 获取结点 i 的父结点 + # 获取节点 i 的父节点 p = self.parent(i) - # 当“越过根结点”或“结点无需修复”时,结束堆化 + # 当“越过根节点”或“节点无需修复”时,结束堆化 if p < 0 or self.max_heap[i] <= self.max_heap[p]: break - # 交换两结点 + # 交换两节点 self.swap(i, p) # 循环向上堆化 i = p @@ -71,9 +71,9 @@ class MaxHeap: """ 元素出堆 """ # 判空处理 assert not self.is_empty() - # 交换根结点与最右叶结点(即交换首元素与尾元素) + # 交换根节点与最右叶节点(即交换首元素与尾元素) self.swap(0, self.size() - 1) - # 删除结点 + # 删除节点 val = self.max_heap.pop() # 从顶至底堆化 self.sift_down(0) @@ -81,18 +81,18 @@ class MaxHeap: return val def sift_down(self, i: int): - """ 从结点 i 开始,从顶至底堆化 """ + """ 从节点 i 开始,从顶至底堆化 """ while True: - # 判断结点 i, l, r 中值最大的结点,记为 ma + # 判断节点 i, l, r 中值最大的节点,记为 ma l, r, ma = self.left(i), self.right(i), i if l < self.size() and self.max_heap[l] > self.max_heap[ma]: ma = l if r < self.size() and self.max_heap[r] > self.max_heap[ma]: ma = r - # 若结点 i 最大或索引 l, r 越界,则无需继续堆化,跳出 + # 若节点 i 最大或索引 l, r 越界,则无需继续堆化,跳出 if ma == i: break - # 交换两结点 + # 交换两节点 self.swap(i, ma) # 循环向下堆化 i = ma diff --git a/codes/python/chapter_searching/hashing_search.py b/codes/python/chapter_searching/hashing_search.py index 96d80761..92f7a284 100644 --- a/codes/python/chapter_searching/hashing_search.py +++ b/codes/python/chapter_searching/hashing_search.py @@ -16,7 +16,7 @@ def hashing_search_array(mapp: dict[int, int], target: int) -> int: def hashing_search_linkedlist(mapp: dict[int, ListNode], target: int) -> ListNode | None: """ 哈希查找(链表) """ - # 哈希表的 key: 目标元素,value: 结点对象 + # 哈希表的 key: 目标元素,value: 节点对象 # 若哈希表中无此 key ,返回 None return mapp.get(target, None) @@ -39,7 +39,7 @@ if __name__ == '__main__': # 初始化哈希表 map1 = dict[int, ListNode]() while head: - map1[head.val] = head # key: 结点值,value: 结点 + map1[head.val] = head # key: 节点值,value: 节点 head = head.next node: ListNode = hashing_search_linkedlist(map1, target) - print("目标结点值 3 的对应结点对象为", node) + print("目标节点值 3 的对应节点对象为", node) diff --git a/codes/python/chapter_searching/linear_search.py b/codes/python/chapter_searching/linear_search.py index c6fb228f..54c27471 100644 --- a/codes/python/chapter_searching/linear_search.py +++ b/codes/python/chapter_searching/linear_search.py @@ -20,10 +20,10 @@ def linear_search_linkedlist(head: ListNode, target: int) -> ListNode | None: """ 线性查找(链表) """ # 遍历链表 while head: - if head.val == target: # 找到目标结点,返回之 + if head.val == target: # 找到目标节点,返回之 return head head = head.next - return None # 未找到目标结点,返回 None + return None # 未找到目标节点,返回 None """ Driver Code """ @@ -38,4 +38,4 @@ if __name__ == '__main__': # 在链表中执行线性查找 head: ListNode = list_to_linked_list(nums) node: ListNode | None = linear_search_linkedlist(head, target) - print("目标结点值 3 的对应结点对象为", node) + print("目标节点值 3 的对应节点对象为", node) diff --git a/codes/python/chapter_stack_and_queue/linkedlist_deque.py b/codes/python/chapter_stack_and_queue/linkedlist_deque.py index 0d63ab4f..d41a230a 100644 --- a/codes/python/chapter_stack_and_queue/linkedlist_deque.py +++ b/codes/python/chapter_stack_and_queue/linkedlist_deque.py @@ -5,19 +5,19 @@ Author: Krahets (krahets@163.com) """ class ListNode: - """ 双向链表结点 """ + """ 双向链表节点 """ def __init__(self, val: int) -> None: """ 构造方法 """ self.val: int = val - self.next: ListNode | None = None # 后继结点引用(指针) - self.prev: ListNode | None = None # 前驱结点引用(指针) + self.next: ListNode | None = None # 后继节点引用(指针) + self.prev: ListNode | None = None # 前驱节点引用(指针) class LinkedListDeque: """ 基于双向链表实现的双向队列 """ def __init__(self) -> None: """ 构造方法 """ - self.front: ListNode | None = None # 头结点 front - self.rear: ListNode | None = None # 尾结点 rear + self.front: ListNode | None = None # 头节点 front + self.rear: ListNode | None = None # 尾节点 rear self.__size: int = 0 # 双向队列的长度 def size(self) -> int: @@ -39,13 +39,13 @@ class LinkedListDeque: # 将 node 添加至链表头部 self.front.prev = node node.next = self.front - self.front = node # 更新头结点 + self.front = node # 更新头节点 # 队尾入队操作 else: # 将 node 添加至链表尾部 self.rear.next = node node.prev = self.rear - self.rear = node # 更新尾结点 + self.rear = node # 更新尾节点 self.__size += 1 # 更新队列长度 def push_first(self, num: int) -> None: @@ -63,22 +63,22 @@ class LinkedListDeque: return None # 队首出队操作 if is_front: - val: int = self.front.val # 暂存头结点值 - # 删除头结点 + val: int = self.front.val # 暂存头节点值 + # 删除头节点 fnext: ListNode | None = self.front.next if fnext != None: fnext.prev = None self.front.next = None - self.front = fnext # 更新头结点 + self.front = fnext # 更新头节点 # 队尾出队操作 else: - val: int = self.rear.val # 暂存尾结点值 - # 删除尾结点 + val: int = self.rear.val # 暂存尾节点值 + # 删除尾节点 rprev: ListNode | None = self.rear.prev if rprev != None: rprev.next = None self.rear.prev = None - self.rear = rprev # 更新尾结点 + self.rear = rprev # 更新尾节点 self.__size -= 1 # 更新队列长度 return val diff --git a/codes/python/chapter_stack_and_queue/linkedlist_queue.py b/codes/python/chapter_stack_and_queue/linkedlist_queue.py index 793339d3..17476538 100644 --- a/codes/python/chapter_stack_and_queue/linkedlist_queue.py +++ b/codes/python/chapter_stack_and_queue/linkedlist_queue.py @@ -12,8 +12,8 @@ class LinkedListQueue: """ 基于链表实现的队列 """ def __init__(self): """ 构造方法 """ - self.__front: ListNode | None = None # 头结点 front - self.__rear: ListNode | None = None # 尾结点 rear + self.__front: ListNode | None = None # 头节点 front + self.__rear: ListNode | None = None # 尾节点 rear self.__size: int = 0 def size(self) -> int: @@ -26,13 +26,13 @@ class LinkedListQueue: def push(self, num: int) -> None: """ 入队 """ - # 尾结点后添加 num + # 尾节点后添加 num node = ListNode(num) - # 如果队列为空,则令头、尾结点都指向该结点 + # 如果队列为空,则令头、尾节点都指向该节点 if self.__front is None: self.__front = node self.__rear = node - # 如果队列不为空,则将该结点添加到尾结点后 + # 如果队列不为空,则将该节点添加到尾节点后 else: self.__rear.next = node self.__rear = node @@ -41,7 +41,7 @@ class LinkedListQueue: def pop(self) -> int: """ 出队 """ num = self.peek() - # 删除头结点 + # 删除头节点 self.__front = self.__front.next self.__size -= 1 return num diff --git a/codes/python/chapter_tree/avl_tree.py b/codes/python/chapter_tree/avl_tree.py index 76213e62..fe3c7456 100644 --- a/codes/python/chapter_tree/avl_tree.py +++ b/codes/python/chapter_tree/avl_tree.py @@ -19,23 +19,23 @@ class AVLTree: return self.__root def height(self, node: TreeNode | None) -> int: - """ 获取结点高度 """ - # 空结点高度为 -1 ,叶结点高度为 0 + """ 获取节点高度 """ + # 空节点高度为 -1 ,叶节点高度为 0 if node is not None: return node.height return -1 def __update_height(self, node: TreeNode | None): - """ 更新结点高度 """ - # 结点高度等于最高子树高度 + 1 + """ 更新节点高度 """ + # 节点高度等于最高子树高度 + 1 node.height = max([self.height(node.left), self.height(node.right)]) + 1 def balance_factor(self, node: TreeNode | None) -> int: """ 获取平衡因子 """ - # 空结点平衡因子为 0 + # 空节点平衡因子为 0 if node is None: return 0 - # 结点平衡因子 = 左子树高度 - 右子树高度 + # 节点平衡因子 = 左子树高度 - 右子树高度 return self.height(node.left) - self.height(node.right) def __right_rotate(self, node: TreeNode | None) -> TreeNode | None: @@ -45,10 +45,10 @@ class AVLTree: # 以 child 为原点,将 node 向右旋转 child.right = node node.left = grand_child - # 更新结点高度 + # 更新节点高度 self.__update_height(node) self.__update_height(child) - # 返回旋转后子树的根结点 + # 返回旋转后子树的根节点 return child def __left_rotate(self, node: TreeNode | None) -> TreeNode | None: @@ -58,15 +58,15 @@ class AVLTree: # 以 child 为原点,将 node 向左旋转 child.left = node node.right = grand_child - # 更新结点高度 + # 更新节点高度 self.__update_height(node) self.__update_height(child) - # 返回旋转后子树的根结点 + # 返回旋转后子树的根节点 return child def __rotate(self, node: TreeNode | None) -> TreeNode | None: """ 执行旋转操作,使该子树重新恢复平衡 """ - # 获取结点 node 的平衡因子 + # 获取节点 node 的平衡因子 balance_factor = self.balance_factor(node) # 左偏树 if balance_factor > 1: @@ -90,37 +90,37 @@ class AVLTree: return node def insert(self, val) -> TreeNode: - """ 插入结点 """ + """ 插入节点 """ self.__root = self.__insert_helper(self.__root, val) return self.__root def __insert_helper(self, node: TreeNode | None, val: int) -> TreeNode: - """ 递归插入结点(辅助方法)""" + """ 递归插入节点(辅助方法)""" if node is None: return TreeNode(val) - # 1. 查找插入位置,并插入结点 + # 1. 查找插入位置,并插入节点 if val < node.val: node.left = self.__insert_helper(node.left, val) elif val > node.val: node.right = self.__insert_helper(node.right, val) else: - # 重复结点不插入,直接返回 + # 重复节点不插入,直接返回 return node - # 更新结点高度 + # 更新节点高度 self.__update_height(node) # 2. 执行旋转操作,使该子树重新恢复平衡 return self.__rotate(node) def remove(self, val: int) -> TreeNode | None: - """ 删除结点 """ + """ 删除节点 """ self.__root = self.__remove_helper(self.__root, val) return self.__root def __remove_helper(self, node: TreeNode | None, val: int) -> TreeNode | None: - """ 递归删除结点(辅助方法) """ + """ 递归删除节点(辅助方法) """ if node is None: return None - # 1. 查找结点,并删除之 + # 1. 查找节点,并删除之 if val < node.val: node.left = self.__remove_helper(node.left, val) elif val > node.val: @@ -128,45 +128,45 @@ class AVLTree: else: if node.left is None or node.right is None: child = node.left or node.right - # 子结点数量 = 0 ,直接删除 node 并返回 + # 子节点数量 = 0 ,直接删除 node 并返回 if child is None: return None - # 子结点数量 = 1 ,直接删除 node + # 子节点数量 = 1 ,直接删除 node else: node = child - else: # 子结点数量 = 2 ,则将中序遍历的下个结点删除,并用该结点替换当前结点 + else: # 子节点数量 = 2 ,则将中序遍历的下个节点删除,并用该节点替换当前节点 temp = self.__get_inorder_next(node.right) node.right = self.__remove_helper(node.right, temp.val) node.val = temp.val - # 更新结点高度 + # 更新节点高度 self.__update_height(node) # 2. 执行旋转操作,使该子树重新恢复平衡 return self.__rotate(node) def __get_inorder_next(self, node: TreeNode | None) -> TreeNode | None: - """ 获取中序遍历中的下一个结点(仅适用于 root 有左子结点的情况) """ + """ 获取中序遍历中的下一个节点(仅适用于 root 有左子节点的情况) """ if node is None: return None - # 循环访问左子结点,直到叶结点时为最小结点,跳出 + # 循环访问左子节点,直到叶节点时为最小节点,跳出 while node.left is not None: node = node.left return node def search(self, val: int) -> TreeNode | None: - """ 查找结点 """ + """ 查找节点 """ cur = self.__root - # 循环查找,越过叶结点后跳出 + # 循环查找,越过叶节点后跳出 while cur is not None: - # 目标结点在 cur 的右子树中 + # 目标节点在 cur 的右子树中 if cur.val < val: cur = cur.right - # 目标结点在 cur 的左子树中 + # 目标节点在 cur 的左子树中 elif cur.val > val: cur = cur.left - # 找到目标结点,跳出循环 + # 找到目标节点,跳出循环 else: break - # 返回目标结点 + # 返回目标节点 return cur @@ -174,19 +174,19 @@ class AVLTree: if __name__ == "__main__": def test_insert(tree: AVLTree, val: int): tree.insert(val) - print("\n插入结点 {} 后,AVL 树为".format(val)) + print("\n插入节点 {} 后,AVL 树为".format(val)) print_tree(tree.root) def test_remove(tree: AVLTree, val: int): tree.remove(val) - print("\n删除结点 {} 后,AVL 树为".format(val)) + print("\n删除节点 {} 后,AVL 树为".format(val)) print_tree(tree.root) # 初始化空 AVL 树 avl_tree = AVLTree() - # 插入结点 - # 请关注插入结点后,AVL 树是如何保持平衡的 + # 插入节点 + # 请关注插入节点后,AVL 树是如何保持平衡的 test_insert(avl_tree, 1) test_insert(avl_tree, 2) test_insert(avl_tree, 3) @@ -198,14 +198,14 @@ if __name__ == "__main__": test_insert(avl_tree, 10) test_insert(avl_tree, 6) - # 插入重复结点 + # 插入重复节点 test_insert(avl_tree, 7) - # 删除结点 - # 请关注删除结点后,AVL 树是如何保持平衡的 - test_remove(avl_tree, 8) # 删除度为 0 的结点 - test_remove(avl_tree, 5) # 删除度为 1 的结点 - test_remove(avl_tree, 4) # 删除度为 2 的结点 + # 删除节点 + # 请关注删除节点后,AVL 树是如何保持平衡的 + test_remove(avl_tree, 8) # 删除度为 0 的节点 + test_remove(avl_tree, 5) # 删除度为 1 的节点 + test_remove(avl_tree, 4) # 删除度为 2 的节点 result_node = avl_tree.search(7) - print("\n查找到的结点对象为 {},结点值 = {}".format(result_node, result_node.val)) + print("\n查找到的节点对象为 {},节点值 = {}".format(result_node, result_node.val)) diff --git a/codes/python/chapter_tree/binary_search_tree.py b/codes/python/chapter_tree/binary_search_tree.py index b87d87ff..5c2920d2 100644 --- a/codes/python/chapter_tree/binary_search_tree.py +++ b/codes/python/chapter_tree/binary_search_tree.py @@ -21,7 +21,7 @@ class BinarySearchTree: if start_index > end_index: return None - # 将数组中间结点作为根结点 + # 将数组中间节点作为根节点 mid: int = (start_index + end_index) // 2 root = TreeNode(nums[mid]) # 递归建立左子树和右子树 @@ -34,31 +34,31 @@ class BinarySearchTree: return self.__root def search(self, num: int) -> TreeNode | None: - """ 查找结点 """ + """ 查找节点 """ cur: TreeNode | None = self.__root - # 循环查找,越过叶结点后跳出 + # 循环查找,越过叶节点后跳出 while cur is not None: - # 目标结点在 cur 的右子树中 + # 目标节点在 cur 的右子树中 if cur.val < num: cur = cur.right - # 目标结点在 cur 的左子树中 + # 目标节点在 cur 的左子树中 elif cur.val > num: cur = cur.left - # 找到目标结点,跳出循环 + # 找到目标节点,跳出循环 else: break return cur def insert(self, num: int) -> TreeNode | None: - """ 插入结点 """ + """ 插入节点 """ # 若树为空,直接提前返回 if self.__root is None: return None - # 循环查找,越过叶结点后跳出 + # 循环查找,越过叶节点后跳出 cur, pre = self.__root, None while cur is not None: - # 找到重复结点,直接返回 + # 找到重复节点,直接返回 if cur.val == num: return None pre = cur @@ -69,7 +69,7 @@ class BinarySearchTree: else: cur = cur.left - # 插入结点 val + # 插入节点 val node = TreeNode(num) if pre.val < num: pre.right = node @@ -78,51 +78,51 @@ class BinarySearchTree: return node def remove(self, num: int) -> TreeNode | None: - """ 删除结点 """ + """ 删除节点 """ # 若树为空,直接提前返回 if self.__root is None: return None - # 循环查找,越过叶结点后跳出 + # 循环查找,越过叶节点后跳出 cur, pre = self.__root, None while cur is not None: - # 找到待删除结点,跳出循环 + # 找到待删除节点,跳出循环 if cur.val == num: break pre = cur - if cur.val < num: # 待删除结点在 cur 的右子树中 + if cur.val < num: # 待删除节点在 cur 的右子树中 cur = cur.right - else: # 待删除结点在 cur 的左子树中 + else: # 待删除节点在 cur 的左子树中 cur = cur.left - # 若无待删除结点,则直接返回 + # 若无待删除节点,则直接返回 if cur is None: return None - # 子结点数量 = 0 or 1 + # 子节点数量 = 0 or 1 if cur.left is None or cur.right is None: - # 当子结点数量 = 0 / 1 时, child = null / 该子结点 + # 当子节点数量 = 0 / 1 时, child = null / 该子节点 child = cur.left or cur.right - # 删除结点 cur + # 删除节点 cur if pre.left == cur: pre.left = child else: pre.right = child - # 子结点数量 = 2 + # 子节点数量 = 2 else: - # 获取中序遍历中 cur 的下一个结点 + # 获取中序遍历中 cur 的下一个节点 nex: TreeNode = self.get_inorder_next(cur.right) tmp: int = nex.val - # 递归删除结点 nex + # 递归删除节点 nex self.remove(nex.val) # 将 nex 的值复制给 cur cur.val = tmp return cur def get_inorder_next(self, root: TreeNode | None) -> TreeNode | None: - """ 获取中序遍历中的下一个结点(仅适用于 root 有左子结点的情况) """ + """ 获取中序遍历中的下一个节点(仅适用于 root 有左子节点的情况) """ if root is None: return root - # 循环访问左子结点,直到叶结点时为最小结点,跳出 + # 循环访问左子节点,直到叶节点时为最小节点,跳出 while root.left is not None: root = root.left return root @@ -136,24 +136,24 @@ if __name__ == "__main__": print("\n初始化的二叉树为\n") print_tree(bst.root) - # 查找结点 + # 查找节点 node = bst.search(7) - print("\n查找到的结点对象为: {},结点值 = {}".format(node, node.val)) + print("\n查找到的节点对象为: {},节点值 = {}".format(node, node.val)) - # 插入结点 + # 插入节点 node = bst.insert(16) - print("\n插入结点 16 后,二叉树为\n") + print("\n插入节点 16 后,二叉树为\n") print_tree(bst.root) - # 删除结点 + # 删除节点 bst.remove(1) - print("\n删除结点 1 后,二叉树为\n") + print("\n删除节点 1 后,二叉树为\n") print_tree(bst.root) bst.remove(2) - print("\n删除结点 2 后,二叉树为\n") + print("\n删除节点 2 后,二叉树为\n") print_tree(bst.root) bst.remove(4) - print("\n删除结点 4 后,二叉树为\n") + print("\n删除节点 4 后,二叉树为\n") print_tree(bst.root) diff --git a/codes/python/chapter_tree/binary_tree.py b/codes/python/chapter_tree/binary_tree.py index 512f08e9..0a65ad7e 100644 --- a/codes/python/chapter_tree/binary_tree.py +++ b/codes/python/chapter_tree/binary_tree.py @@ -13,7 +13,7 @@ from modules import * """ Driver Code """ if __name__ == "__main__": """ 初始化二叉树 """ - # 初始化结点 + # 初始化节点 n1 = TreeNode(val=1) n2 = TreeNode(val=2) n3 = TreeNode(val=3) @@ -27,14 +27,14 @@ if __name__ == "__main__": print("\n初始化二叉树\n") print_tree(n1) - """ 插入与删除结点 """ + """ 插入与删除节点 """ P = TreeNode(0) - # 在 n1 -> n2 中间插入结点 P + # 在 n1 -> n2 中间插入节点 P n1.left = P P.left = n2 - print("\n插入结点 P 后\n") + print("\n插入节点 P 后\n") print_tree(n1) - # 删除结点 + # 删除节点 n1.left = n2 - print("\n删除结点 P 后\n") + print("\n删除节点 P 后\n") print_tree(n1) diff --git a/codes/python/chapter_tree/binary_tree_bfs.py b/codes/python/chapter_tree/binary_tree_bfs.py index 020387d2..8e59cf6c 100644 --- a/codes/python/chapter_tree/binary_tree_bfs.py +++ b/codes/python/chapter_tree/binary_tree_bfs.py @@ -11,18 +11,18 @@ from collections import deque def level_order(root: TreeNode | None) -> list[int]: """ 层序遍历 """ - # 初始化队列,加入根结点 + # 初始化队列,加入根节点 queue: deque[TreeNode] = deque() queue.append(root) # 初始化一个列表,用于保存遍历序列 res: list[int] = [] while queue: node: TreeNode = queue.popleft() # 队列出队 - res.append(node.val) # 保存结点值 + res.append(node.val) # 保存节点值 if node.left is not None: - queue.append(node.left) # 左子结点入队 + queue.append(node.left) # 左子节点入队 if node.right is not None: - queue.append(node.right) # 右子结点入队 + queue.append(node.right) # 右子节点入队 return res @@ -36,5 +36,5 @@ if __name__ == "__main__": # 层序遍历 res: list[int] = level_order(root) - print("\n层序遍历的结点打印序列 = ", res) + print("\n层序遍历的节点打印序列 = ", res) assert res == [1, 2, 3, 4, 5, 6, 7] diff --git a/codes/python/chapter_tree/binary_tree_dfs.py b/codes/python/chapter_tree/binary_tree_dfs.py index b2e0583f..a7ebcf62 100644 --- a/codes/python/chapter_tree/binary_tree_dfs.py +++ b/codes/python/chapter_tree/binary_tree_dfs.py @@ -12,7 +12,7 @@ def pre_order(root: TreeNode | None) -> None: """ 前序遍历 """ if root is None: return - # 访问优先级:根结点 -> 左子树 -> 右子树 + # 访问优先级:根节点 -> 左子树 -> 右子树 res.append(root.val) pre_order(root=root.left) pre_order(root=root.right) @@ -21,7 +21,7 @@ def in_order(root: TreeNode | None) -> None: """ 中序遍历 """ if root is None: return - # 访问优先级:左子树 -> 根结点 -> 右子树 + # 访问优先级:左子树 -> 根节点 -> 右子树 in_order(root=root.left) res.append(root.val) in_order(root=root.right) @@ -30,7 +30,7 @@ def post_order(root: TreeNode | None) -> None: """ 后序遍历 """ if root is None: return - # 访问优先级:左子树 -> 右子树 -> 根结点 + # 访问优先级:左子树 -> 右子树 -> 根节点 post_order(root=root.left) post_order(root=root.right) res.append(root.val) @@ -47,17 +47,17 @@ if __name__ == "__main__": # 前序遍历 res = [] pre_order(root) - print("\n前序遍历的结点打印序列 = ", res) + print("\n前序遍历的节点打印序列 = ", res) assert res == [1, 2, 4, 5, 3, 6, 7] # 中序遍历 res.clear() in_order(root) - print("\n中序遍历的结点打印序列 = ", res) + print("\n中序遍历的节点打印序列 = ", res) assert res == [4, 2, 5, 1, 6, 3, 7] # 后序遍历 res.clear() post_order(root) - print("\n后序遍历的结点打印序列 = ", res) + print("\n后序遍历的节点打印序列 = ", res) assert res == [4, 5, 2, 6, 7, 3, 1] diff --git a/codes/python/modules/binary_tree.py b/codes/python/modules/binary_tree.py index 42831be9..ca25d34f 100644 --- a/codes/python/modules/binary_tree.py +++ b/codes/python/modules/binary_tree.py @@ -9,10 +9,10 @@ from collections import deque class TreeNode: """ Definition for a binary tree node """ def __init__(self, val: int = 0): - self.val: int = val # 结点值 - self.height: int = 0 # 结点高度 - self.left: TreeNode | None = None # 左子结点引用 - self.right: TreeNode | None = None # 右子结点引用 + self.val: int = val # 节点值 + self.height: int = 0 # 节点高度 + self.left: TreeNode | None = None # 左子节点引用 + self.right: TreeNode | None = None # 右子节点引用 def list_to_tree(arr: list[int]) -> TreeNode | None: """ Generate a binary tree with a list """ diff --git a/codes/python/modules/linked_list.py b/codes/python/modules/linked_list.py index 6d87bd22..3fef0347 100644 --- a/codes/python/modules/linked_list.py +++ b/codes/python/modules/linked_list.py @@ -7,8 +7,8 @@ Author: Krahets (krahets@163.com) class ListNode: """ Definition for a singly-linked list node """ def __init__(self, val: int): - self.val: int = val # 结点值 - self.next: ListNode | None = None # 后继结点引用 + self.val: int = val # 节点值 + self.next: ListNode | None = None # 后继节点引用 def list_to_linked_list(arr: list[int]) -> ListNode | None: """ Generate a linked list with a list """ diff --git a/codes/rust/chapter_array_and_linkedlist/linked_list.rs b/codes/rust/chapter_array_and_linkedlist/linked_list.rs index fe9aa5c8..c6c732e6 100644 --- a/codes/rust/chapter_array_and_linkedlist/linked_list.rs +++ b/codes/rust/chapter_array_and_linkedlist/linked_list.rs @@ -10,7 +10,7 @@ use std::rc::Rc; use std::cell::RefCell; use list_node::ListNode; -/* 在链表的结点 n0 之后插入结点 P */ +/* 在链表的节点 n0 之后插入节点 P */ #[allow(non_snake_case)] pub fn insert(n0: &Rc>>, P: Rc>>) { let n1 = n0.borrow_mut().next.take(); @@ -18,7 +18,7 @@ pub fn insert(n0: &Rc>>, P: Rc>>) { n0.borrow_mut().next = Some(P); } -/* 删除链表的结点 n0 之后的首个结点 */ +/* 删除链表的节点 n0 之后的首个节点 */ #[allow(non_snake_case)] pub fn remove(n0: &Rc>>) { if n0.borrow().next.is_none() {return}; @@ -30,7 +30,7 @@ pub fn remove(n0: &Rc>>) { } } -/* 访问链表中索引为 index 的结点 */ +/* 访问链表中索引为 index 的节点 */ pub fn access(head: Rc>>, index: i32) -> Rc>> { if index <= 0 {return head}; if let Some(node) = &head.borrow_mut().next { @@ -39,7 +39,7 @@ pub fn access(head: Rc>>, index: i32) -> Rc(head: Rc>>, target: T, index: i32) -> i32 { if head.borrow().val == target {return index}; if let Some(node) = &head.borrow_mut().next { @@ -51,7 +51,7 @@ pub fn find(head: Rc>>, target: T, index: i32) /* Driver Code */ fn main() { /* 初始化链表 */ - // 初始化各个结点 + // 初始化各个节点 let n0 = ListNode::new(1); let n1 = ListNode::new(3); let n2 = ListNode::new(2); @@ -65,21 +65,21 @@ fn main() { print!("初始化的链表为 "); print_util::print_linked_list(&n0); - /* 插入结点 */ + /* 插入节点 */ insert(&n0, ListNode::new(0)); - print!("插入结点后的链表为 "); + print!("插入节点后的链表为 "); print_util::print_linked_list(&n0); - /* 删除结点 */ + /* 删除节点 */ remove(&n0); - print!("删除结点后的链表为 "); + print!("删除节点后的链表为 "); print_util::print_linked_list(&n0); - /* 访问结点 */ + /* 访问节点 */ let node = access(n0.clone(), 3); - println!("链表中索引 3 处的结点的值 = {}", node.borrow().val); + println!("链表中索引 3 处的节点的值 = {}", node.borrow().val); - /* 查找结点 */ + /* 查找节点 */ let index = find(n0.clone(), 2, 0); - println!("链表中值为 2 的结点的索引 = {}", index); + println!("链表中值为 2 的节点的索引 = {}", index); } diff --git a/codes/rust/chapter_stack_and_queue/linkedlist_deque.rs b/codes/rust/chapter_stack_and_queue/linkedlist_deque.rs index 937d1a31..b9eb92f0 100644 --- a/codes/rust/chapter_stack_and_queue/linkedlist_deque.rs +++ b/codes/rust/chapter_stack_and_queue/linkedlist_deque.rs @@ -9,11 +9,11 @@ include!("../include/include.rs"); use std::rc::Rc; use std::cell::RefCell; -/* 双向链表结点 */ +/* 双向链表节点 */ pub struct ListNode { - pub val: T, // 结点值 - pub next: Option>>>, // 后继结点引用(指针) - pub prev: Option>>>, // 前驱结点引用(指针) + pub val: T, // 节点值 + pub next: Option>>>, // 后继节点引用(指针) + pub prev: Option>>>, // 前驱节点引用(指针) } impl ListNode { @@ -29,8 +29,8 @@ impl ListNode { /* 基于双向链表实现的双向队列 */ #[allow(dead_code)] pub struct LinkedListDeque { - front: Option>>>, // 头结点 front - rear: Option>>>, // 尾结点 rear + front: Option>>>, // 头节点 front + rear: Option>>>, // 尾节点 rear que_size: usize, // 双向队列的长度 } @@ -63,7 +63,7 @@ impl LinkedListDeque { Some(old_front) => { old_front.borrow_mut().prev = Some(node.clone()); node.borrow_mut().next = Some(old_front); - self.front = Some(node); // 更新头结点 + self.front = Some(node); // 更新头节点 } None => { self.rear = Some(node.clone()); @@ -77,7 +77,7 @@ impl LinkedListDeque { Some(old_rear) => { old_rear.borrow_mut().next = Some(node.clone()); node.borrow_mut().prev = Some(old_rear); - self.rear = Some(node); // 更新尾结点 + self.rear = Some(node); // 更新尾节点 } None => { self.front = Some(node.clone()); @@ -107,7 +107,7 @@ impl LinkedListDeque { match old_front.borrow_mut().next.take() { Some(new_front) => { new_front.borrow_mut().prev.take(); - self.front = Some(new_front); // 更新头结点 + self.front = Some(new_front); // 更新头节点 } None => { self.rear.take(); @@ -122,7 +122,7 @@ impl LinkedListDeque { match old_rear.borrow_mut().prev.take() { Some(new_rear) => { new_rear.borrow_mut().next.take(); - self.rear = Some(new_rear); // 更新尾结点 + self.rear = Some(new_rear); // 更新尾节点 } None => { self.front.take(); diff --git a/codes/rust/chapter_stack_and_queue/linkedlist_queue.rs b/codes/rust/chapter_stack_and_queue/linkedlist_queue.rs index e0c6dc2e..cb4cefca 100644 --- a/codes/rust/chapter_stack_and_queue/linkedlist_queue.rs +++ b/codes/rust/chapter_stack_and_queue/linkedlist_queue.rs @@ -13,8 +13,8 @@ use list_node::ListNode; /* 基于链表实现的队列 */ #[allow(dead_code)] pub struct LinkedListQueue { - front: Option>>>, // 头结点 front - rear: Option>>>, // 尾结点 rear + front: Option>>>, // 头节点 front + rear: Option>>>, // 尾节点 rear que_size: usize, // 队列的长度 } @@ -39,15 +39,15 @@ impl LinkedListQueue { /* 入队 */ pub fn push(&mut self, num: T) { - // 尾结点后添加 num + // 尾节点后添加 num let new_rear = ListNode::new(num); match self.rear.take() { - // 如果队列不为空,则将该结点添加到尾结点后 + // 如果队列不为空,则将该节点添加到尾节点后 Some(old_rear) => { old_rear.borrow_mut().next = Some(new_rear.clone()); self.rear = Some(new_rear); } - // 如果队列为空,则令头、尾结点都指向该结点 + // 如果队列为空,则令头、尾节点都指向该节点 None => { self.front = Some(new_rear.clone()); self.rear = Some(new_rear); diff --git a/codes/rust/chapter_stack_and_queue/linkedlist_stack.rs b/codes/rust/chapter_stack_and_queue/linkedlist_stack.rs index ba52a815..26ddc90f 100644 --- a/codes/rust/chapter_stack_and_queue/linkedlist_stack.rs +++ b/codes/rust/chapter_stack_and_queue/linkedlist_stack.rs @@ -13,7 +13,7 @@ use list_node::ListNode; /* 基于链表实现的栈 */ #[allow(dead_code)] pub struct LinkedListStack { - stack_peek: Option>>>, // 将头结点作为栈顶 + stack_peek: Option>>>, // 将头节点作为栈顶 stk_size: usize, // 栈的长度 } diff --git a/codes/rust/chapter_tree/binary_tree.rs b/codes/rust/chapter_tree/binary_tree.rs index 232ac93f..c5726683 100644 --- a/codes/rust/chapter_tree/binary_tree.rs +++ b/codes/rust/chapter_tree/binary_tree.rs @@ -24,16 +24,16 @@ fn main() { println!("\n初始化二叉树\n"); print_util::print_tree(&n1); - // 插入结点与删除结点 + // 插入节点与删除节点 let p = TreeNode::new(0); - // 在 n1 -> n2 中间插入结点 P + // 在 n1 -> n2 中间插入节点 P p.borrow_mut().left = Some(Rc::clone(&n2)); n1.borrow_mut().left = Some(Rc::clone(&p)); - println!("\n插入结点 P 后\n"); + println!("\n插入节点 P 后\n"); print_util::print_tree(&n1); - // 删除结点 P + // 删除节点 P drop(p); n1.borrow_mut().left = Some(Rc::clone(&n2)); - println!("\n删除结点 P 后\n"); + println!("\n删除节点 P 后\n"); print_util::print_tree(&n1); } \ No newline at end of file diff --git a/codes/swift/chapter_array_and_linkedlist/linked_list.swift b/codes/swift/chapter_array_and_linkedlist/linked_list.swift index d3644203..62274de1 100644 --- a/codes/swift/chapter_array_and_linkedlist/linked_list.swift +++ b/codes/swift/chapter_array_and_linkedlist/linked_list.swift @@ -6,14 +6,14 @@ import utils -/* 在链表的结点 n0 之后插入结点 P */ +/* 在链表的节点 n0 之后插入节点 P */ func insert(n0: ListNode, P: ListNode) { let n1 = n0.next P.next = n1 n0.next = P } -/* 删除链表的结点 n0 之后的首个结点 */ +/* 删除链表的节点 n0 之后的首个节点 */ func remove(n0: ListNode) { if n0.next == nil { return @@ -25,7 +25,7 @@ func remove(n0: ListNode) { P?.next = nil } -/* 访问链表中索引为 index 的结点 */ +/* 访问链表中索引为 index 的节点 */ func access(head: ListNode, index: Int) -> ListNode? { var head: ListNode? = head for _ in 0 ..< index { @@ -37,7 +37,7 @@ func access(head: ListNode, index: Int) -> ListNode? { return head } -/* 在链表中查找值为 target 的首个结点 */ +/* 在链表中查找值为 target 的首个节点 */ func find(head: ListNode, target: Int) -> Int { var head: ListNode? = head var index = 0 @@ -56,7 +56,7 @@ enum LinkedList { /* Driver Code */ static func main() { /* 初始化链表 */ - // 初始化各个结点 + // 初始化各个节点 let n0 = ListNode(x: 1) let n1 = ListNode(x: 3) let n2 = ListNode(x: 2) @@ -70,22 +70,22 @@ enum LinkedList { print("初始化的链表为") PrintUtil.printLinkedList(head: n0) - /* 插入结点 */ + /* 插入节点 */ insert(n0: n0, P: ListNode(x: 0)) - print("插入结点后的链表为") + print("插入节点后的链表为") PrintUtil.printLinkedList(head: n0) - /* 删除结点 */ + /* 删除节点 */ remove(n0: n0) - print("删除结点后的链表为") + print("删除节点后的链表为") PrintUtil.printLinkedList(head: n0) - /* 访问结点 */ + /* 访问节点 */ let node = access(head: n0, index: 3) - print("链表中索引 3 处的结点的值 = \(node!.val)") + print("链表中索引 3 处的节点的值 = \(node!.val)") - /* 查找结点 */ + /* 查找节点 */ let index = find(head: n0, target: 2) - print("链表中值为 2 的结点的索引 = \(index)") + print("链表中值为 2 的节点的索引 = \(index)") } } diff --git a/codes/swift/chapter_heap/my_heap.swift b/codes/swift/chapter_heap/my_heap.swift index 273dacea..3588cae2 100644 --- a/codes/swift/chapter_heap/my_heap.swift +++ b/codes/swift/chapter_heap/my_heap.swift @@ -14,23 +14,23 @@ class MaxHeap { init(nums: [Int]) { // 将列表元素原封不动添加进堆 maxHeap = nums - // 堆化除叶结点以外的其他所有结点 + // 堆化除叶节点以外的其他所有节点 for i in stride(from: parent(i: size() - 1), through: 0, by: -1) { siftDown(i: i) } } - /* 获取左子结点索引 */ + /* 获取左子节点索引 */ private func left(i: Int) -> Int { 2 * i + 1 } - /* 获取右子结点索引 */ + /* 获取右子节点索引 */ private func right(i: Int) -> Int { 2 * i + 2 } - /* 获取父结点索引 */ + /* 获取父节点索引 */ private func parent(i: Int) -> Int { (i - 1) / 2 // 向下整除 } @@ -57,23 +57,23 @@ class MaxHeap { /* 元素入堆 */ func push(val: Int) { - // 添加结点 + // 添加节点 maxHeap.append(val) // 从底至顶堆化 siftUp(i: size() - 1) } - /* 从结点 i 开始,从底至顶堆化 */ + /* 从节点 i 开始,从底至顶堆化 */ private func siftUp(i: Int) { var i = i while true { - // 获取结点 i 的父结点 + // 获取节点 i 的父节点 let p = parent(i: i) - // 当“越过根结点”或“结点无需修复”时,结束堆化 + // 当“越过根节点”或“节点无需修复”时,结束堆化 if p < 0 || maxHeap[i] <= maxHeap[p] { break } - // 交换两结点 + // 交换两节点 swap(i: i, j: p) // 循环向上堆化 i = p @@ -86,9 +86,9 @@ class MaxHeap { if isEmpty() { fatalError("堆为空") } - // 交换根结点与最右叶结点(即交换首元素与尾元素) + // 交换根节点与最右叶节点(即交换首元素与尾元素) swap(i: 0, j: size() - 1) - // 删除结点 + // 删除节点 let val = maxHeap.remove(at: size() - 1) // 从顶至底堆化 siftDown(i: 0) @@ -96,11 +96,11 @@ class MaxHeap { return val } - /* 从结点 i 开始,从顶至底堆化 */ + /* 从节点 i 开始,从顶至底堆化 */ private func siftDown(i: Int) { var i = i while true { - // 判断结点 i, l, r 中值最大的结点,记为 ma + // 判断节点 i, l, r 中值最大的节点,记为 ma let l = left(i: i) let r = right(i: i) var ma = i @@ -110,11 +110,11 @@ class MaxHeap { if r < size(), maxHeap[r] > maxHeap[ma] { ma = r } - // 若结点 i 最大或索引 l, r 越界,则无需继续堆化,跳出 + // 若节点 i 最大或索引 l, r 越界,则无需继续堆化,跳出 if ma == i { break } - // 交换两结点 + // 交换两节点 swap(i: i, j: ma) // 循环向下堆化 i = ma diff --git a/codes/swift/chapter_searching/hashing_search.swift b/codes/swift/chapter_searching/hashing_search.swift index 3ef8f239..a8be99da 100644 --- a/codes/swift/chapter_searching/hashing_search.swift +++ b/codes/swift/chapter_searching/hashing_search.swift @@ -15,7 +15,7 @@ func hashingSearchArray(map: [Int: Int], target: Int) -> Int { /* 哈希查找(链表) */ func hashingSearchLinkedList(map: [Int: ListNode], target: Int) -> ListNode? { - // 哈希表的 key: 目标结点值,value: 结点对象 + // 哈希表的 key: 目标节点值,value: 节点对象 // 若哈希表中无此 key ,返回 null return map[target] } @@ -41,10 +41,10 @@ enum HashingSearch { // 初始化哈希表 var map1: [Int: ListNode] = [:] while head != nil { - map1[head!.val] = head! // key: 结点值,value: 结点 + map1[head!.val] = head! // key: 节点值,value: 节点 head = head?.next } let node = hashingSearchLinkedList(map: map1, target: target) - print("目标结点值 3 的对应结点对象为 \(node!)") + print("目标节点值 3 的对应节点对象为 \(node!)") } } diff --git a/codes/swift/chapter_searching/linear_search.swift b/codes/swift/chapter_searching/linear_search.swift index ef101cec..1544f774 100644 --- a/codes/swift/chapter_searching/linear_search.swift +++ b/codes/swift/chapter_searching/linear_search.swift @@ -24,13 +24,13 @@ func linearSearchLinkedList(head: ListNode?, target: Int) -> ListNode? { var head = head // 遍历链表 while head != nil { - // 找到目标结点,返回之 + // 找到目标节点,返回之 if head?.val == target { return head } head = head?.next } - // 未找到目标结点,返回 null + // 未找到目标节点,返回 null return nil } @@ -48,6 +48,6 @@ enum LinearSearch { /* 在链表中执行线性查找 */ let head = ListNode.arrToLinkedList(arr: nums) let node = linearSearchLinkedList(head: head, target: target) - print("目标结点值 3 的对应结点对象为 \(node!)") + print("目标节点值 3 的对应节点对象为 \(node!)") } } diff --git a/codes/swift/chapter_stack_and_queue/linkedlist_deque.swift b/codes/swift/chapter_stack_and_queue/linkedlist_deque.swift index 2a2905e3..f50fbbf5 100644 --- a/codes/swift/chapter_stack_and_queue/linkedlist_deque.swift +++ b/codes/swift/chapter_stack_and_queue/linkedlist_deque.swift @@ -4,11 +4,11 @@ * Author: nuomi1 (nuomi1@qq.com) */ -/* 双向链表结点 */ +/* 双向链表节点 */ class ListNode { - var val: Int // 结点值 - var next: ListNode? // 后继结点引用(指针) - var prev: ListNode? // 前驱结点引用(指针) + var val: Int // 节点值 + var next: ListNode? // 后继节点引用(指针) + var prev: ListNode? // 前驱节点引用(指针) init(val: Int) { self.val = val @@ -17,8 +17,8 @@ class ListNode { /* 基于双向链表实现的双向队列 */ class LinkedListDeque { - private var front: ListNode? // 头结点 front - private var rear: ListNode? // 尾结点 rear + private var front: ListNode? // 头节点 front + private var rear: ListNode? // 尾节点 rear private var queSize: Int // 双向队列的长度 init() { @@ -48,14 +48,14 @@ class LinkedListDeque { // 将 node 添加至链表头部 front?.prev = node node.next = front - front = node // 更新头结点 + front = node // 更新头节点 } // 队尾入队操作 else { // 将 node 添加至链表尾部 rear?.next = node node.prev = rear - rear = node // 更新尾结点 + rear = node // 更新尾节点 } queSize += 1 // 更新队列长度 } @@ -78,25 +78,25 @@ class LinkedListDeque { let val: Int // 队首出队操作 if isFront { - val = front!.val // 暂存头结点值 - // 删除头结点 + val = front!.val // 暂存头节点值 + // 删除头节点 let fNext = front?.next if fNext != nil { fNext?.prev = nil front?.next = nil } - front = fNext // 更新头结点 + front = fNext // 更新头节点 } // 队尾出队操作 else { - val = rear!.val // 暂存尾结点值 - // 删除尾结点 + val = rear!.val // 暂存尾节点值 + // 删除尾节点 let rPrev = rear?.prev if rPrev != nil { rPrev?.next = nil rear?.prev = nil } - rear = rPrev // 更新尾结点 + rear = rPrev // 更新尾节点 } queSize -= 1 // 更新队列长度 return val diff --git a/codes/swift/chapter_stack_and_queue/linkedlist_queue.swift b/codes/swift/chapter_stack_and_queue/linkedlist_queue.swift index 3c85acca..141de434 100644 --- a/codes/swift/chapter_stack_and_queue/linkedlist_queue.swift +++ b/codes/swift/chapter_stack_and_queue/linkedlist_queue.swift @@ -8,8 +8,8 @@ import utils /* 基于链表实现的队列 */ class LinkedListQueue { - private var front: ListNode? // 头结点 - private var rear: ListNode? // 尾结点 + private var front: ListNode? // 头节点 + private var rear: ListNode? // 尾节点 private var _size = 0 init() {} @@ -26,14 +26,14 @@ class LinkedListQueue { /* 入队 */ func push(num: Int) { - // 尾结点后添加 num + // 尾节点后添加 num let node = ListNode(x: num) - // 如果队列为空,则令头、尾结点都指向该结点 + // 如果队列为空,则令头、尾节点都指向该节点 if front == nil { front = node rear = node } - // 如果队列不为空,则将该结点添加到尾结点后 + // 如果队列不为空,则将该节点添加到尾节点后 else { rear?.next = node rear = node @@ -45,7 +45,7 @@ class LinkedListQueue { @discardableResult func pop() -> Int { let num = peek() - // 删除头结点 + // 删除头节点 front = front?.next _size -= 1 return num diff --git a/codes/swift/chapter_stack_and_queue/linkedlist_stack.swift b/codes/swift/chapter_stack_and_queue/linkedlist_stack.swift index 97f7dabc..7f857380 100644 --- a/codes/swift/chapter_stack_and_queue/linkedlist_stack.swift +++ b/codes/swift/chapter_stack_and_queue/linkedlist_stack.swift @@ -8,7 +8,7 @@ import utils /* 基于链表实现的栈 */ class LinkedListStack { - private var _peek: ListNode? // 将头结点作为栈顶 + private var _peek: ListNode? // 将头节点作为栈顶 private var _size = 0 // 栈的长度 init() {} diff --git a/codes/swift/chapter_tree/avl_tree.swift b/codes/swift/chapter_tree/avl_tree.swift index d7d084c4..0fb41976 100644 --- a/codes/swift/chapter_tree/avl_tree.swift +++ b/codes/swift/chapter_tree/avl_tree.swift @@ -8,25 +8,25 @@ import utils /* AVL 树 */ class AVLTree { - fileprivate var root: TreeNode? // 根结点 + fileprivate var root: TreeNode? // 根节点 - /* 获取结点高度 */ + /* 获取节点高度 */ func height(node: TreeNode?) -> Int { - // 空结点高度为 -1 ,叶结点高度为 0 + // 空节点高度为 -1 ,叶节点高度为 0 node == nil ? -1 : node!.height } - /* 更新结点高度 */ + /* 更新节点高度 */ private func updateHeight(node: TreeNode?) { - // 结点高度等于最高子树高度 + 1 + // 节点高度等于最高子树高度 + 1 node?.height = max(height(node: node?.left), height(node: node?.right)) + 1 } /* 获取平衡因子 */ func balanceFactor(node: TreeNode?) -> Int { - // 空结点平衡因子为 0 + // 空节点平衡因子为 0 guard let node = node else { return 0 } - // 结点平衡因子 = 左子树高度 - 右子树高度 + // 节点平衡因子 = 左子树高度 - 右子树高度 return height(node: node.left) - height(node: node.right) } @@ -37,10 +37,10 @@ class AVLTree { // 以 child 为原点,将 node 向右旋转 child?.right = node node?.left = grandChild - // 更新结点高度 + // 更新节点高度 updateHeight(node: node) updateHeight(node: child) - // 返回旋转后子树的根结点 + // 返回旋转后子树的根节点 return child } @@ -51,16 +51,16 @@ class AVLTree { // 以 child 为原点,将 node 向左旋转 child?.left = node node?.right = grandChild - // 更新结点高度 + // 更新节点高度 updateHeight(node: node) updateHeight(node: child) - // 返回旋转后子树的根结点 + // 返回旋转后子树的根节点 return child } /* 执行旋转操作,使该子树重新恢复平衡 */ private func rotate(node: TreeNode?) -> TreeNode? { - // 获取结点 node 的平衡因子 + // 获取节点 node 的平衡因子 let balanceFactor = balanceFactor(node: node) // 左偏树 if balanceFactor > 1 { @@ -88,48 +88,48 @@ class AVLTree { return node } - /* 插入结点 */ + /* 插入节点 */ @discardableResult func insert(val: Int) -> TreeNode? { root = insertHelper(node: root, val: val) return root } - /* 递归插入结点(辅助方法) */ + /* 递归插入节点(辅助方法) */ private func insertHelper(node: TreeNode?, val: Int) -> TreeNode? { var node = node if node == nil { return TreeNode(x: val) } - /* 1. 查找插入位置,并插入结点 */ + /* 1. 查找插入位置,并插入节点 */ if val < node!.val { node?.left = insertHelper(node: node?.left, val: val) } else if val > node!.val { node?.right = insertHelper(node: node?.right, val: val) } else { - return node // 重复结点不插入,直接返回 + return node // 重复节点不插入,直接返回 } - updateHeight(node: node) // 更新结点高度 + updateHeight(node: node) // 更新节点高度 /* 2. 执行旋转操作,使该子树重新恢复平衡 */ node = rotate(node: node) - // 返回子树的根结点 + // 返回子树的根节点 return node } - /* 删除结点 */ + /* 删除节点 */ @discardableResult func remove(val: Int) -> TreeNode? { root = removeHelper(node: root, val: val) return root } - /* 递归删除结点(辅助方法) */ + /* 递归删除节点(辅助方法) */ private func removeHelper(node: TreeNode?, val: Int) -> TreeNode? { var node = node if node == nil { return nil } - /* 1. 查找结点,并删除之 */ + /* 1. 查找节点,并删除之 */ if val < node!.val { node?.left = removeHelper(node: node?.left, val: val) } else if val > node!.val { @@ -137,59 +137,59 @@ class AVLTree { } else { if node?.left == nil || node?.right == nil { let child = node?.left != nil ? node?.left : node?.right - // 子结点数量 = 0 ,直接删除 node 并返回 + // 子节点数量 = 0 ,直接删除 node 并返回 if child == nil { return nil } - // 子结点数量 = 1 ,直接删除 node + // 子节点数量 = 1 ,直接删除 node else { node = child } } else { - // 子结点数量 = 2 ,则将中序遍历的下个结点删除,并用该结点替换当前结点 + // 子节点数量 = 2 ,则将中序遍历的下个节点删除,并用该节点替换当前节点 let temp = getInOrderNext(node: node?.right) node?.right = removeHelper(node: node?.right, val: temp!.val) node?.val = temp!.val } } - updateHeight(node: node) // 更新结点高度 + updateHeight(node: node) // 更新节点高度 /* 2. 执行旋转操作,使该子树重新恢复平衡 */ node = rotate(node: node) - // 返回子树的根结点 + // 返回子树的根节点 return node } - /* 获取中序遍历中的下一个结点(仅适用于 root 有左子结点的情况) */ + /* 获取中序遍历中的下一个节点(仅适用于 root 有左子节点的情况) */ private func getInOrderNext(node: TreeNode?) -> TreeNode? { var node = node if node == nil { return node } - // 循环访问左子结点,直到叶结点时为最小结点,跳出 + // 循环访问左子节点,直到叶节点时为最小节点,跳出 while node?.left != nil { node = node?.left } return node } - /* 查找结点 */ + /* 查找节点 */ func search(val: Int) -> TreeNode? { var cur = root while cur != nil { - // 目标结点在 cur 的右子树中 + // 目标节点在 cur 的右子树中 if cur!.val < val { cur = cur?.right } - // 目标结点在 cur 的左子树中 + // 目标节点在 cur 的左子树中 else if cur!.val > val { cur = cur?.left } - // 找到目标结点,跳出循环 + // 找到目标节点,跳出循环 else { break } } - // 返回目标结点 + // 返回目标节点 return cur } } @@ -198,13 +198,13 @@ class AVLTree { enum _AVLTree { static func testInsert(tree: AVLTree, val: Int) { tree.insert(val: val) - print("\n插入结点 \(val) 后,AVL 树为") + print("\n插入节点 \(val) 后,AVL 树为") PrintUtil.printTree(root: tree.root) } static func testRemove(tree: AVLTree, val: Int) { tree.remove(val: val) - print("\n删除结点 \(val) 后,AVL 树为") + print("\n删除节点 \(val) 后,AVL 树为") PrintUtil.printTree(root: tree.root) } @@ -213,8 +213,8 @@ enum _AVLTree { /* 初始化空 AVL 树 */ let avlTree = AVLTree() - /* 插入结点 */ - // 请关注插入结点后,AVL 树是如何保持平衡的 + /* 插入节点 */ + // 请关注插入节点后,AVL 树是如何保持平衡的 testInsert(tree: avlTree, val: 1) testInsert(tree: avlTree, val: 2) testInsert(tree: avlTree, val: 3) @@ -226,17 +226,17 @@ enum _AVLTree { testInsert(tree: avlTree, val: 10) testInsert(tree: avlTree, val: 6) - /* 插入重复结点 */ + /* 插入重复节点 */ testInsert(tree: avlTree, val: 7) - /* 删除结点 */ - // 请关注删除结点后,AVL 树是如何保持平衡的 - testRemove(tree: avlTree, val: 8) // 删除度为 0 的结点 - testRemove(tree: avlTree, val: 5) // 删除度为 1 的结点 - testRemove(tree: avlTree, val: 4) // 删除度为 2 的结点 + /* 删除节点 */ + // 请关注删除节点后,AVL 树是如何保持平衡的 + testRemove(tree: avlTree, val: 8) // 删除度为 0 的节点 + testRemove(tree: avlTree, val: 5) // 删除度为 1 的节点 + testRemove(tree: avlTree, val: 4) // 删除度为 2 的节点 - /* 查询结点 */ + /* 查询节点 */ let node = avlTree.search(val: 7) - print("\n查找到的结点对象为 \(node!),结点值 = \(node!.val)") + print("\n查找到的节点对象为 \(node!),节点值 = \(node!.val)") } } diff --git a/codes/swift/chapter_tree/binary_search_tree.swift b/codes/swift/chapter_tree/binary_search_tree.swift index 9d5025c0..5cb4b134 100644 --- a/codes/swift/chapter_tree/binary_search_tree.swift +++ b/codes/swift/chapter_tree/binary_search_tree.swift @@ -15,7 +15,7 @@ class BinarySearchTree { root = buildTree(nums: nums, i: 0, j: nums.count - 1) // 构建二叉搜索树 } - /* 获取二叉树根结点 */ + /* 获取二叉树根节点 */ func getRoot() -> TreeNode? { root } @@ -25,7 +25,7 @@ class BinarySearchTree { if i > j { return nil } - // 将数组中间结点作为根结点 + // 将数组中间节点作为根节点 let mid = (i + j) / 2 let root = TreeNode(x: nums[mid]) // 递归建立左子树和右子树 @@ -34,29 +34,29 @@ class BinarySearchTree { return root } - /* 查找结点 */ + /* 查找节点 */ func search(num: Int) -> TreeNode? { var cur = root - // 循环查找,越过叶结点后跳出 + // 循环查找,越过叶节点后跳出 while cur != nil { - // 目标结点在 cur 的右子树中 + // 目标节点在 cur 的右子树中 if cur!.val < num { cur = cur?.right } - // 目标结点在 cur 的左子树中 + // 目标节点在 cur 的左子树中 else if cur!.val > num { cur = cur?.left } - // 找到目标结点,跳出循环 + // 找到目标节点,跳出循环 else { break } } - // 返回目标结点 + // 返回目标节点 return cur } - /* 插入结点 */ + /* 插入节点 */ func insert(num: Int) -> TreeNode? { // 若树为空,直接提前返回 if root == nil { @@ -64,9 +64,9 @@ class BinarySearchTree { } var cur = root var pre: TreeNode? - // 循环查找,越过叶结点后跳出 + // 循环查找,越过叶节点后跳出 while cur != nil { - // 找到重复结点,直接返回 + // 找到重复节点,直接返回 if cur!.val == num { return nil } @@ -80,7 +80,7 @@ class BinarySearchTree { cur = cur?.left } } - // 插入结点 val + // 插入节点 val let node = TreeNode(x: num) if pre!.val < num { pre?.right = node @@ -90,7 +90,7 @@ class BinarySearchTree { return node } - /* 删除结点 */ + /* 删除节点 */ @discardableResult func remove(num: Int) -> TreeNode? { // 若树为空,直接提前返回 @@ -99,43 +99,43 @@ class BinarySearchTree { } var cur = root var pre: TreeNode? - // 循环查找,越过叶结点后跳出 + // 循环查找,越过叶节点后跳出 while cur != nil { - // 找到待删除结点,跳出循环 + // 找到待删除节点,跳出循环 if cur!.val == num { break } pre = cur - // 待删除结点在 cur 的右子树中 + // 待删除节点在 cur 的右子树中 if cur!.val < num { cur = cur?.right } - // 待删除结点在 cur 的左子树中 + // 待删除节点在 cur 的左子树中 else { cur = cur?.left } } - // 若无待删除结点,则直接返回 + // 若无待删除节点,则直接返回 if cur == nil { return nil } - // 子结点数量 = 0 or 1 + // 子节点数量 = 0 or 1 if cur?.left == nil || cur?.right == nil { - // 当子结点数量 = 0 / 1 时, child = null / 该子结点 + // 当子节点数量 = 0 / 1 时, child = null / 该子节点 let child = cur?.left != nil ? cur?.left : cur?.right - // 删除结点 cur + // 删除节点 cur if pre?.left === cur { pre?.left = child } else { pre?.right = child } } - // 子结点数量 = 2 + // 子节点数量 = 2 else { - // 获取中序遍历中 cur 的下一个结点 + // 获取中序遍历中 cur 的下一个节点 let nex = getInOrderNext(root: cur?.right) let tmp = nex!.val - // 递归删除结点 nex + // 递归删除节点 nex remove(num: nex!.val) // 将 nex 的值复制给 cur cur?.val = tmp @@ -143,13 +143,13 @@ class BinarySearchTree { return cur } - /* 获取中序遍历中的下一个结点(仅适用于 root 有左子结点的情况) */ + /* 获取中序遍历中的下一个节点(仅适用于 root 有左子节点的情况) */ func getInOrderNext(root: TreeNode?) -> TreeNode? { var root = root if root == nil { return root } - // 循环访问左子结点,直到叶结点时为最小结点,跳出 + // 循环访问左子节点,直到叶节点时为最小节点,跳出 while root?.left != nil { root = root?.left } @@ -167,24 +167,24 @@ enum _BinarySearchTree { print("\n初始化的二叉树为\n") PrintUtil.printTree(root: bst.getRoot()) - /* 查找结点 */ + /* 查找节点 */ var node = bst.search(num: 7) - print("\n查找到的结点对象为 \(node!),结点值 = \(node!.val)") + print("\n查找到的节点对象为 \(node!),节点值 = \(node!.val)") - /* 插入结点 */ + /* 插入节点 */ node = bst.insert(num: 16) - print("\n插入结点 16 后,二叉树为\n") + print("\n插入节点 16 后,二叉树为\n") PrintUtil.printTree(root: bst.getRoot()) - /* 删除结点 */ + /* 删除节点 */ bst.remove(num: 1) - print("\n删除结点 1 后,二叉树为\n") + print("\n删除节点 1 后,二叉树为\n") PrintUtil.printTree(root: bst.getRoot()) bst.remove(num: 2) - print("\n删除结点 2 后,二叉树为\n") + print("\n删除节点 2 后,二叉树为\n") PrintUtil.printTree(root: bst.getRoot()) bst.remove(num: 4) - print("\n删除结点 4 后,二叉树为\n") + print("\n删除节点 4 后,二叉树为\n") PrintUtil.printTree(root: bst.getRoot()) } } diff --git a/codes/swift/chapter_tree/binary_tree.swift b/codes/swift/chapter_tree/binary_tree.swift index ad9e3c74..2efc099f 100644 --- a/codes/swift/chapter_tree/binary_tree.swift +++ b/codes/swift/chapter_tree/binary_tree.swift @@ -11,7 +11,7 @@ enum BinaryTree { /* Driver Code */ static func main() { /* 初始化二叉树 */ - // 初始化结点 + // 初始化节点 let n1 = TreeNode(x: 1) let n2 = TreeNode(x: 2) let n3 = TreeNode(x: 3) @@ -25,16 +25,16 @@ enum BinaryTree { print("\n初始化二叉树\n") PrintUtil.printTree(root: n1) - /* 插入与删除结点 */ + /* 插入与删除节点 */ let P = TreeNode(x: 0) - // 在 n1 -> n2 中间插入结点 P + // 在 n1 -> n2 中间插入节点 P n1.left = P P.left = n2 - print("\n插入结点 P 后\n") + print("\n插入节点 P 后\n") PrintUtil.printTree(root: n1) - // 删除结点 P + // 删除节点 P n1.left = n2 - print("\n删除结点 P 后\n") + print("\n删除节点 P 后\n") PrintUtil.printTree(root: n1) } } diff --git a/codes/swift/chapter_tree/binary_tree_bfs.swift b/codes/swift/chapter_tree/binary_tree_bfs.swift index 326214a9..0ddcb85f 100644 --- a/codes/swift/chapter_tree/binary_tree_bfs.swift +++ b/codes/swift/chapter_tree/binary_tree_bfs.swift @@ -8,18 +8,18 @@ import utils /* 层序遍历 */ func levelOrder(root: TreeNode) -> [Int] { - // 初始化队列,加入根结点 + // 初始化队列,加入根节点 var queue: [TreeNode] = [root] // 初始化一个列表,用于保存遍历序列 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) // 左子结点入队 + queue.append(left) // 左子节点入队 } if let right = node.right { - queue.append(right) // 右子结点入队 + queue.append(right) // 右子节点入队 } } return list @@ -37,6 +37,6 @@ enum BinaryTreeBFS { /* 层序遍历 */ let list = levelOrder(root: node) - print("\n层序遍历的结点打印序列 = \(list)") + print("\n层序遍历的节点打印序列 = \(list)") } } diff --git a/codes/swift/chapter_tree/binary_tree_dfs.swift b/codes/swift/chapter_tree/binary_tree_dfs.swift index d68d764c..61695ef7 100644 --- a/codes/swift/chapter_tree/binary_tree_dfs.swift +++ b/codes/swift/chapter_tree/binary_tree_dfs.swift @@ -14,7 +14,7 @@ func preOrder(root: TreeNode?) { guard let root = root else { return } - // 访问优先级:根结点 -> 左子树 -> 右子树 + // 访问优先级:根节点 -> 左子树 -> 右子树 list.append(root.val) preOrder(root: root.left) preOrder(root: root.right) @@ -25,7 +25,7 @@ func inOrder(root: TreeNode?) { guard let root = root else { return } - // 访问优先级:左子树 -> 根结点 -> 右子树 + // 访问优先级:左子树 -> 根节点 -> 右子树 inOrder(root: root.left) list.append(root.val) inOrder(root: root.right) @@ -36,7 +36,7 @@ func postOrder(root: TreeNode?) { guard let root = root else { return } - // 访问优先级:左子树 -> 右子树 -> 根结点 + // 访问优先级:左子树 -> 右子树 -> 根节点 postOrder(root: root.left) postOrder(root: root.right) list.append(root.val) @@ -55,16 +55,16 @@ enum BinaryTreeDFS { /* 前序遍历 */ list.removeAll() preOrder(root: root) - print("\n前序遍历的结点打印序列 = \(list)") + print("\n前序遍历的节点打印序列 = \(list)") /* 中序遍历 */ list.removeAll() inOrder(root: root) - print("\n中序遍历的结点打印序列 = \(list)") + print("\n中序遍历的节点打印序列 = \(list)") /* 后序遍历 */ list.removeAll() postOrder(root: root) - print("\n后序遍历的结点打印序列 = \(list)") + print("\n后序遍历的节点打印序列 = \(list)") } } diff --git a/codes/swift/utils/ListNode.swift b/codes/swift/utils/ListNode.swift index a45d212e..f6cc869b 100644 --- a/codes/swift/utils/ListNode.swift +++ b/codes/swift/utils/ListNode.swift @@ -5,8 +5,8 @@ */ public class ListNode { - public var val: Int // 结点值 - public var next: ListNode? // 后继结点引用 + public var val: Int // 节点值 + public var next: ListNode? // 后继节点引用 public init(x: Int) { val = x diff --git a/codes/swift/utils/TreeNode.swift b/codes/swift/utils/TreeNode.swift index bb5abf55..cdb7fef6 100644 --- a/codes/swift/utils/TreeNode.swift +++ b/codes/swift/utils/TreeNode.swift @@ -5,10 +5,10 @@ */ public class TreeNode { - public var val: Int // 结点值 - public var height: Int // 结点高度 - public var left: TreeNode? // 左子结点引用 - public var right: TreeNode? // 右子结点引用 + public var val: Int // 节点值 + public var height: Int // 节点高度 + public var left: TreeNode? // 左子节点引用 + public var right: TreeNode? // 右子节点引用 public init(x: Int) { val = x diff --git a/codes/typescript/chapter_array_and_linkedlist/linked_list.ts b/codes/typescript/chapter_array_and_linkedlist/linked_list.ts index 453f487e..f1eff855 100644 --- a/codes/typescript/chapter_array_and_linkedlist/linked_list.ts +++ b/codes/typescript/chapter_array_and_linkedlist/linked_list.ts @@ -7,14 +7,14 @@ import { ListNode } from '../modules/ListNode'; import { printLinkedList } from '../modules/PrintUtil'; -/* 在链表的结点 n0 之后插入结点 P */ +/* 在链表的节点 n0 之后插入节点 P */ function insert(n0: ListNode, P: ListNode): void { const n1 = n0.next; P.next = n1; n0.next = P; } -/* 删除链表的结点 n0 之后的首个结点 */ +/* 删除链表的节点 n0 之后的首个节点 */ function remove(n0: ListNode): void { if (!n0.next) { return; @@ -25,7 +25,7 @@ function remove(n0: ListNode): void { n0.next = n1; } -/* 访问链表中索引为 index 的结点 */ +/* 访问链表中索引为 index 的节点 */ function access(head: ListNode | null, index: number): ListNode | null { for (let i = 0; i < index; i++) { if (!head) { @@ -36,7 +36,7 @@ function access(head: ListNode | null, index: number): ListNode | null { return head; } -/* 在链表中查找值为 target 的首个结点 */ +/* 在链表中查找值为 target 的首个节点 */ function find(head: ListNode | null, target: number): number { let index = 0; while (head !== null) { @@ -51,7 +51,7 @@ function find(head: ListNode | null, target: number): number { /* Driver Code */ /* 初始化链表 */ -// 初始化各个结点 +// 初始化各个节点 const n0 = new ListNode(1); const n1 = new ListNode(3); const n2 = new ListNode(2); @@ -65,22 +65,22 @@ n3.next = n4; console.log('初始化的链表为'); printLinkedList(n0); -/* 插入结点 */ +/* 插入节点 */ insert(n0, new ListNode(0)); -console.log('插入结点后的链表为'); +console.log('插入节点后的链表为'); printLinkedList(n0); -/* 删除结点 */ +/* 删除节点 */ remove(n0); -console.log('删除结点后的链表为'); +console.log('删除节点后的链表为'); printLinkedList(n0); -/* 访问结点 */ +/* 访问节点 */ const node = access(n0, 3); -console.log(`链表中索引 3 处的结点的值 = ${node?.val}`); +console.log(`链表中索引 3 处的节点的值 = ${node?.val}`); -/* 查找结点 */ +/* 查找节点 */ const index = find(n0, 2); -console.log(`链表中值为 2 的结点的索引 = ${index}`); +console.log(`链表中值为 2 的节点的索引 = ${index}`); export {}; diff --git a/codes/typescript/chapter_heap/my_heap.ts b/codes/typescript/chapter_heap/my_heap.ts index 67a12592..51d0bfa0 100644 --- a/codes/typescript/chapter_heap/my_heap.ts +++ b/codes/typescript/chapter_heap/my_heap.ts @@ -13,23 +13,23 @@ class MaxHeap { constructor(nums?: number[]) { // 将列表元素原封不动添加进堆 this.maxHeap = nums === undefined ? [] : [...nums]; - // 堆化除叶结点以外的其他所有结点 + // 堆化除叶节点以外的其他所有节点 for (let i = this.parent(this.size() - 1); i >= 0; i--) { this.siftDown(i); } } - /* 获取左子结点索引 */ + /* 获取左子节点索引 */ private left(i: number): number { return 2 * i + 1; } - /* 获取右子结点索引 */ + /* 获取右子节点索引 */ private right(i: number): number { return 2 * i + 2; } - /* 获取父结点索引 */ + /* 获取父节点索引 */ private parent(i: number): number { return Math.floor((i - 1) / 2); // 向下整除 } @@ -60,20 +60,20 @@ class MaxHeap { /* 元素入堆 */ public push(val: number): void { - // 添加结点 + // 添加节点 this.maxHeap.push(val); // 从底至顶堆化 this.siftUp(this.size() - 1); } - /* 从结点 i 开始,从底至顶堆化 */ + /* 从节点 i 开始,从底至顶堆化 */ private siftUp(i: number): void { while (true) { - // 获取结点 i 的父结点 + // 获取节点 i 的父节点 const p = this.parent(i); - // 当“越过根结点”或“结点无需修复”时,结束堆化 + // 当“越过根节点”或“节点无需修复”时,结束堆化 if (p < 0 || this.maxHeap[i] <= this.maxHeap[p]) break; - // 交换两结点 + // 交换两节点 this.swap(i, p); // 循环向上堆化 i = p; @@ -84,9 +84,9 @@ class MaxHeap { public pop(): number { // 判空处理 if (this.isEmpty()) throw new RangeError('Heap is empty.'); - // 交换根结点与最右叶结点(即交换首元素与尾元素) + // 交换根节点与最右叶节点(即交换首元素与尾元素) this.swap(0, this.size() - 1); - // 删除结点 + // 删除节点 const val = this.maxHeap.pop(); // 从顶至底堆化 this.siftDown(0); @@ -94,18 +94,18 @@ class MaxHeap { return val; } - /* 从结点 i 开始,从顶至底堆化 */ + /* 从节点 i 开始,从顶至底堆化 */ private siftDown(i: number): void { while (true) { - // 判断结点 i, l, r 中值最大的结点,记为 ma + // 判断节点 i, l, r 中值最大的节点,记为 ma const l = this.left(i), r = this.right(i); let ma = i; if (l < this.size() && this.maxHeap[l] > this.maxHeap[ma]) ma = l; if (r < this.size() && this.maxHeap[r] > this.maxHeap[ma]) ma = r; - // 若结点 i 最大或索引 l, r 越界,则无需继续堆化,跳出 + // 若节点 i 最大或索引 l, r 越界,则无需继续堆化,跳出 if (ma == i) break; - // 交换两结点 + // 交换两节点 this.swap(i, ma); // 循环向下堆化 i = ma; diff --git a/codes/typescript/chapter_searching/hashing_search.ts b/codes/typescript/chapter_searching/hashing_search.ts index fe024cd0..a78bb3d8 100644 --- a/codes/typescript/chapter_searching/hashing_search.ts +++ b/codes/typescript/chapter_searching/hashing_search.ts @@ -15,7 +15,7 @@ function hashingSearchArray(map: Map, target: number): number { /* 哈希查找(链表) */ function hashingSearchLinkedList(map: Map, target: number): ListNode | null { - // 哈希表的 key: 目标结点值,value: 结点对象 + // 哈希表的 key: 目标节点值,value: 节点对象 // 若哈希表中无此 key ,返回 null return map.has(target) ? (map.get(target) as ListNode) : null; } @@ -38,10 +38,10 @@ let head = arrToLinkedList(nums); // 初始化哈希表 const map1 = new Map(); while (head != null) { - map1.set(head.val, head); // key: 结点值,value: 结点 + map1.set(head.val, head); // key: 节点值,value: 节点 head = head.next; } const node = hashingSearchLinkedList(map1, target); -console.log('目标结点值 3 的对应结点对象为', node); +console.log('目标节点值 3 的对应节点对象为', node); export {}; diff --git a/codes/typescript/chapter_searching/linear_search.ts b/codes/typescript/chapter_searching/linear_search.ts index dfd2da3c..318b9f99 100644 --- a/codes/typescript/chapter_searching/linear_search.ts +++ b/codes/typescript/chapter_searching/linear_search.ts @@ -23,13 +23,13 @@ function linearSearchArray(nums: number[], target: number): number { function linearSearchLinkedList(head: ListNode | null, target: number): ListNode | null { // 遍历链表 while (head) { - // 找到目标结点,返回之 + // 找到目标节点,返回之 if (head.val === target) { return head; } head = head.next; } - // 未找到目标结点,返回 null + // 未找到目标节点,返回 null return null; } @@ -44,6 +44,6 @@ console.log('目标元素 3 的索引 =', index); /* 在链表中执行线性查找 */ const head = arrToLinkedList(nums); const node = linearSearchLinkedList(head, target); -console.log('目标结点值 3 的对应结点对象为', node); +console.log('目标节点值 3 的对应节点对象为', node); export {}; diff --git a/codes/typescript/chapter_stack_and_queue/linkedlist_deque.ts b/codes/typescript/chapter_stack_and_queue/linkedlist_deque.ts index 6195d17a..6a6b725b 100644 --- a/codes/typescript/chapter_stack_and_queue/linkedlist_deque.ts +++ b/codes/typescript/chapter_stack_and_queue/linkedlist_deque.ts @@ -4,11 +4,11 @@ * Author: Zhuo Qinyue (1403450829@qq.com) */ -/* 双向链表结点 */ +/* 双向链表节点 */ class ListNode { - prev: ListNode; // 前驱结点引用 (指针) - next: ListNode; // 后继结点引用 (指针) - val: number; // 结点值 + prev: ListNode; // 前驱节点引用 (指针) + next: ListNode; // 后继节点引用 (指针) + val: number; // 节点值 constructor(val: number) { this.val = val; @@ -19,8 +19,8 @@ class ListNode { /* 基于双向链表实现的双向队列 */ class LinkedListDeque { - private front: ListNode; // 头结点 front - private rear: ListNode; // 尾结点 rear + private front: ListNode; // 头节点 front + private rear: ListNode; // 尾节点 rear private queSize: number; // 双向队列的长度 constructor() { @@ -40,7 +40,7 @@ class LinkedListDeque { // 将 node 添加至链表尾部 this.rear.next = node; node.prev = this.rear; - this.rear = node; // 更新尾结点 + this.rear = node; // 更新尾节点 } this.queSize++; } @@ -56,7 +56,7 @@ class LinkedListDeque { // 将 node 添加至链表头部 this.front.prev = node; node.next = this.front; - this.front = node; // 更新头结点 + this.front = node; // 更新头节点 } this.queSize++; } @@ -66,14 +66,14 @@ class LinkedListDeque { if (this.queSize === 0) { return null; } - const value: number = this.rear.val; // 存储尾结点值 - // 删除尾结点 + const value: number = this.rear.val; // 存储尾节点值 + // 删除尾节点 let temp: ListNode = this.rear.prev; if (temp !== null) { temp.next = null; this.rear.prev = null; } - this.rear = temp; // 更新尾结点 + this.rear = temp; // 更新尾节点 this.queSize--; return value; } @@ -83,14 +83,14 @@ class LinkedListDeque { if (this.queSize === 0) { return null; } - const value: number = this.front.val; // 存储尾结点值 - // 删除头结点 + const value: number = this.front.val; // 存储尾节点值 + // 删除头节点 let temp: ListNode = this.front.next; if (temp !== null) { temp.prev = null; this.front.next = null; } - this.front = temp; // 更新头结点 + this.front = temp; // 更新头节点 this.queSize--; return value; } diff --git a/codes/typescript/chapter_stack_and_queue/linkedlist_queue.ts b/codes/typescript/chapter_stack_and_queue/linkedlist_queue.ts index 7aab5b46..e403c012 100644 --- a/codes/typescript/chapter_stack_and_queue/linkedlist_queue.ts +++ b/codes/typescript/chapter_stack_and_queue/linkedlist_queue.ts @@ -8,8 +8,8 @@ import { ListNode } from '../modules/ListNode'; /* 基于链表实现的队列 */ class LinkedListQueue { - private front: ListNode | null; // 头结点 front - private rear: ListNode | null; // 尾结点 rear + private front: ListNode | null; // 头节点 front + private rear: ListNode | null; // 尾节点 rear private queSize: number = 0; constructor() { @@ -29,13 +29,13 @@ class LinkedListQueue { /* 入队 */ push(num: number): void { - // 尾结点后添加 num + // 尾节点后添加 num const node = new ListNode(num); - // 如果队列为空,则令头、尾结点都指向该结点 + // 如果队列为空,则令头、尾节点都指向该节点 if (!this.front) { this.front = node; this.rear = node; - // 如果队列不为空,则将该结点添加到尾结点后 + // 如果队列不为空,则将该节点添加到尾节点后 } else { this.rear!.next = node; this.rear = node; @@ -47,7 +47,7 @@ class LinkedListQueue { pop(): number { const num = this.peek(); if (!this.front) throw new Error('队列为空'); - // 删除头结点 + // 删除头节点 this.front = this.front.next; this.queSize--; return num; diff --git a/codes/typescript/chapter_stack_and_queue/linkedlist_stack.ts b/codes/typescript/chapter_stack_and_queue/linkedlist_stack.ts index 2e483dda..2b5517f8 100644 --- a/codes/typescript/chapter_stack_and_queue/linkedlist_stack.ts +++ b/codes/typescript/chapter_stack_and_queue/linkedlist_stack.ts @@ -8,7 +8,7 @@ import { ListNode } from '../modules/ListNode'; /* 基于链表实现的栈 */ class LinkedListStack { - private stackPeek: ListNode | null; // 将头结点作为栈顶 + private stackPeek: ListNode | null; // 将头节点作为栈顶 private stkSize: number = 0; // 栈的长度 constructor() { diff --git a/codes/typescript/chapter_tree/avl_tree.ts b/codes/typescript/chapter_tree/avl_tree.ts index a9141012..7e5951c5 100644 --- a/codes/typescript/chapter_tree/avl_tree.ts +++ b/codes/typescript/chapter_tree/avl_tree.ts @@ -12,26 +12,26 @@ class AVLTree { root: TreeNode; /*构造方法*/ constructor() { - this.root = null; //根结点 + this.root = null; //根节点 } - /* 获取结点高度 */ + /* 获取节点高度 */ height(node: TreeNode): number { - // 空结点高度为 -1 ,叶结点高度为 0 + // 空节点高度为 -1 ,叶节点高度为 0 return node === null ? -1 : node.height; } - /* 更新结点高度 */ + /* 更新节点高度 */ private updateHeight(node: TreeNode): void { - // 结点高度等于最高子树高度 + 1 + // 节点高度等于最高子树高度 + 1 node.height = Math.max(this.height(node.left), this.height(node.right)) + 1; } /* 获取平衡因子 */ balanceFactor(node: TreeNode): number { - // 空结点平衡因子为 0 + // 空节点平衡因子为 0 if (node === null) return 0; - // 结点平衡因子 = 左子树高度 - 右子树高度 + // 节点平衡因子 = 左子树高度 - 右子树高度 return this.height(node.left) - this.height(node.right); } @@ -42,10 +42,10 @@ class AVLTree { // 以 child 为原点,将 node 向右旋转 child.right = node; node.left = grandChild; - // 更新结点高度 + // 更新节点高度 this.updateHeight(node); this.updateHeight(child); - // 返回旋转后子树的根结点 + // 返回旋转后子树的根节点 return child; } @@ -56,16 +56,16 @@ class AVLTree { // 以 child 为原点,将 node 向左旋转 child.left = node; node.right = grandChild; - // 更新结点高度 + // 更新节点高度 this.updateHeight(node); this.updateHeight(child); - // 返回旋转后子树的根结点 + // 返回旋转后子树的根节点 return child; } /* 执行旋转操作,使该子树重新恢复平衡 */ private rotate(node: TreeNode): TreeNode { - // 获取结点 node 的平衡因子 + // 获取节点 node 的平衡因子 const balanceFactor = this.balanceFactor(node); // 左偏树 if (balanceFactor > 1) { @@ -93,40 +93,40 @@ class AVLTree { return node; } - /* 插入结点 */ + /* 插入节点 */ insert(val: number): TreeNode { this.root = this.insertHelper(this.root, val); return this.root; } - /* 递归插入结点(辅助方法) */ + /* 递归插入节点(辅助方法) */ private insertHelper(node: TreeNode, val: number): TreeNode { if (node === null) return new TreeNode(val); - /* 1. 查找插入位置,并插入结点 */ + /* 1. 查找插入位置,并插入节点 */ if (val < node.val) { node.left = this.insertHelper(node.left, val); } else if (val > node.val) { node.right = this.insertHelper(node.right, val); } else { - return node; // 重复结点不插入,直接返回 + return node; // 重复节点不插入,直接返回 } - this.updateHeight(node); // 更新结点高度 + this.updateHeight(node); // 更新节点高度 /* 2. 执行旋转操作,使该子树重新恢复平衡 */ node = this.rotate(node); - // 返回子树的根结点 + // 返回子树的根节点 return node; } - /* 删除结点 */ + /* 删除节点 */ remove(val: number): TreeNode { this.root = this.removeHelper(this.root, val); return this.root; } - /* 递归删除结点(辅助方法) */ + /* 递归删除节点(辅助方法) */ private removeHelper(node: TreeNode, val: number): TreeNode { if (node === null) return null; - /* 1. 查找结点,并删除之 */ + /* 1. 查找节点,并删除之 */ if (val < node.val) { node.left = this.removeHelper(node.left, val); } else if (val > node.val) { @@ -134,75 +134,75 @@ class AVLTree { } else { if (node.left === null || node.right === null) { const child = node.left !== null ? node.left : node.right; - // 子结点数量 = 0 ,直接删除 node 并返回 + // 子节点数量 = 0 ,直接删除 node 并返回 if (child === null) { return null; } else { - // 子结点数量 = 1 ,直接删除 node + // 子节点数量 = 1 ,直接删除 node node = child; } } else { - // 子结点数量 = 2 ,则将中序遍历的下个结点删除,并用该结点替换当前结点 + // 子节点数量 = 2 ,则将中序遍历的下个节点删除,并用该节点替换当前节点 const temp = this.getInOrderNext(node.right); node.right = this.removeHelper(node.right, temp.val); node.val = temp.val; } } - this.updateHeight(node); // 更新结点高度 + this.updateHeight(node); // 更新节点高度 /* 2. 执行旋转操作,使该子树重新恢复平衡 */ node = this.rotate(node); - // 返回子树的根结点 + // 返回子树的根节点 return node; } - /* 获取中序遍历中的下一个结点(仅适用于 root 有左子结点的情况) */ + /* 获取中序遍历中的下一个节点(仅适用于 root 有左子节点的情况) */ private getInOrderNext(node: TreeNode): TreeNode { if (node === null) return node; - // 循环访问左子结点,直到叶结点时为最小结点,跳出 + // 循环访问左子节点,直到叶节点时为最小节点,跳出 while (node.left !== null) { node = node.left; } return node; } - /* 查找结点 */ + /* 查找节点 */ search(val: number): TreeNode { let cur = this.root; - // 循环查找,越过叶结点后跳出 + // 循环查找,越过叶节点后跳出 while (cur !== null) { if (cur.val < val) { - // 目标结点在 cur 的右子树中 + // 目标节点在 cur 的右子树中 cur = cur.right; } else if (cur.val > val) { - // 目标结点在 cur 的左子树中 + // 目标节点在 cur 的左子树中 cur = cur.left; } else { - // 找到目标结点,跳出循环 + // 找到目标节点,跳出循环 break; } } - // 返回目标结点 + // 返回目标节点 return cur; } } function testInsert(tree: AVLTree, val: number): void { tree.insert(val); - console.log('\n插入结点 ' + val + ' 后,AVL 树为'); + console.log('\n插入节点 ' + val + ' 后,AVL 树为'); printTree(tree.root); } function testRemove(tree: AVLTree, val: number): void { tree.remove(val); - console.log('\n删除结点 ' + val + ' 后,AVL 树为'); + console.log('\n删除节点 ' + val + ' 后,AVL 树为'); printTree(tree.root); } /* Driver Code */ /* 初始化空 AVL 树 */ const avlTree = new AVLTree(); -/* 插入结点 */ -// 请关注插入结点后,AVL 树是如何保持平衡的 +/* 插入节点 */ +// 请关注插入节点后,AVL 树是如何保持平衡的 testInsert(avlTree, 1); testInsert(avlTree, 2); testInsert(avlTree, 3); @@ -214,15 +214,15 @@ testInsert(avlTree, 9); testInsert(avlTree, 10); testInsert(avlTree, 6); -/* 插入重复结点 */ +/* 插入重复节点 */ testInsert(avlTree, 7); -/* 删除结点 */ -// 请关注删除结点后,AVL 树是如何保持平衡的 -testRemove(avlTree, 8); // 删除度为 0 的结点 -testRemove(avlTree, 5); // 删除度为 1 的结点 -testRemove(avlTree, 4); // 删除度为 2 的结点 +/* 删除节点 */ +// 请关注删除节点后,AVL 树是如何保持平衡的 +testRemove(avlTree, 8); // 删除度为 0 的节点 +testRemove(avlTree, 5); // 删除度为 1 的节点 +testRemove(avlTree, 4); // 删除度为 2 的节点 -/* 查询结点 */ +/* 查询节点 */ const node = avlTree.search(7); -console.log('\n查找到的结点对象为', node, ',结点值 = ' + node.val); +console.log('\n查找到的节点对象为', node, ',节点值 = ' + node.val); diff --git a/codes/typescript/chapter_tree/binary_search_tree.ts b/codes/typescript/chapter_tree/binary_search_tree.ts index f664e743..51508a86 100644 --- a/codes/typescript/chapter_tree/binary_search_tree.ts +++ b/codes/typescript/chapter_tree/binary_search_tree.ts @@ -15,7 +15,7 @@ function BinarySearchTree(nums: number[]): void { root = buildTree(nums, 0, nums.length - 1); // 构建二叉搜索树 } -/* 获取二叉树根结点 */ +/* 获取二叉树根节点 */ function getRoot(): TreeNode | null { return root; } @@ -25,7 +25,7 @@ function buildTree(nums: number[], i: number, j: number): TreeNode | null { if (i > j) { return null; } - // 将数组中间结点作为根结点 + // 将数组中间节点作为根节点 let mid = Math.floor((i + j) / 2); let root = new TreeNode(nums[mid]); // 递归建立左子树和右子树 @@ -34,24 +34,24 @@ function buildTree(nums: number[], i: number, j: number): TreeNode | null { return root; } -/* 查找结点 */ +/* 查找节点 */ function search(num: number): TreeNode | null { let cur = root; - // 循环查找,越过叶结点后跳出 + // 循环查找,越过叶节点后跳出 while (cur !== null) { if (cur.val < num) { - cur = cur.right; // 目标结点在 cur 的右子树中 + cur = cur.right; // 目标节点在 cur 的右子树中 } else if (cur.val > num) { - cur = cur.left; // 目标结点在 cur 的左子树中 + cur = cur.left; // 目标节点在 cur 的左子树中 } else { - break; // 找到目标结点,跳出循环 + break; // 找到目标节点,跳出循环 } } - // 返回目标结点 + // 返回目标节点 return cur; } -/* 插入结点 */ +/* 插入节点 */ function insert(num: number): TreeNode | null { // 若树为空,直接提前返回 if (root === null) { @@ -59,10 +59,10 @@ function insert(num: number): TreeNode | null { } let cur = root, pre: TreeNode | null = null; - // 循环查找,越过叶结点后跳出 + // 循环查找,越过叶节点后跳出 while (cur !== null) { if (cur.val === num) { - return null; // 找到重复结点,直接返回 + return null; // 找到重复节点,直接返回 } pre = cur; if (cur.val < num) { @@ -71,7 +71,7 @@ function insert(num: number): TreeNode | null { cur = cur.left as TreeNode; // 插入位置在 cur 的左子树中 } } - // 插入结点 val + // 插入节点 val let node = new TreeNode(num); if (pre!.val < num) { pre!.right = node; @@ -81,7 +81,7 @@ function insert(num: number): TreeNode | null { return node; } -/* 删除结点 */ +/* 删除节点 */ function remove(num: number): TreeNode | null { // 若树为空,直接提前返回 if (root === null) { @@ -89,40 +89,40 @@ function remove(num: number): TreeNode | null { } let cur = root, pre: TreeNode | null = null; - // 循环查找,越过叶结点后跳出 + // 循环查找,越过叶节点后跳出 while (cur !== null) { - // 找到待删除结点,跳出循环 + // 找到待删除节点,跳出循环 if (cur.val === num) { break; } pre = cur; if (cur.val < num) { - cur = cur.right as TreeNode; // 待删除结点在 cur 的右子树中 + cur = cur.right as TreeNode; // 待删除节点在 cur 的右子树中 } else { - cur = cur.left as TreeNode; // 待删除结点在 cur 的左子树中 + cur = cur.left as TreeNode; // 待删除节点在 cur 的左子树中 } } - // 若无待删除结点,则直接返回 + // 若无待删除节点,则直接返回 if (cur === null) { return null; } - // 子结点数量 = 0 or 1 + // 子节点数量 = 0 or 1 if (cur.left === null || cur.right === null) { - // 当子结点数量 = 0 / 1 时, child = null / 该子结点 + // 当子节点数量 = 0 / 1 时, child = null / 该子节点 let child = cur.left !== null ? cur.left : cur.right; - // 删除结点 cur + // 删除节点 cur if (pre!.left === cur) { pre!.left = child; } else { pre!.right = child; } } - // 子结点数量 = 2 + // 子节点数量 = 2 else { - // 获取中序遍历中 cur 的下一个结点 + // 获取中序遍历中 cur 的下一个节点 let next = getInOrderNext(cur.right); let tmp = next!.val; - // 递归删除结点 nex + // 递归删除节点 nex remove(next!.val); // 将 nex 的值复制给 cur cur.val = tmp; @@ -130,12 +130,12 @@ function remove(num: number): TreeNode | null { return cur; } -/* 获取中序遍历中的下一个结点(仅适用于 root 有左子结点的情况) */ +/* 获取中序遍历中的下一个节点(仅适用于 root 有左子节点的情况) */ function getInOrderNext(root: TreeNode | null): TreeNode | null { if (root === null) { return null; } - // 循环访问左子结点,直到叶结点时为最小结点,跳出 + // 循环访问左子节点,直到叶节点时为最小节点,跳出 while (root.left !== null) { root = root.left; } @@ -149,24 +149,24 @@ BinarySearchTree(nums); console.log('\n初始化的二叉树为\n'); printTree(getRoot()); -/* 查找结点 */ +/* 查找节点 */ let node = search(7); -console.log('\n查找到的结点对象为 ' + node + ',结点值 = ' + node!.val); +console.log('\n查找到的节点对象为 ' + node + ',节点值 = ' + node!.val); -/* 插入结点 */ +/* 插入节点 */ node = insert(16); -console.log('\n插入结点 16 后,二叉树为\n'); +console.log('\n插入节点 16 后,二叉树为\n'); printTree(getRoot()); -/* 删除结点 */ +/* 删除节点 */ remove(1); -console.log('\n删除结点 1 后,二叉树为\n'); +console.log('\n删除节点 1 后,二叉树为\n'); printTree(getRoot()); remove(2); -console.log('\n删除结点 2 后,二叉树为\n'); +console.log('\n删除节点 2 后,二叉树为\n'); printTree(getRoot()); remove(4); -console.log('\n删除结点 4 后,二叉树为\n'); +console.log('\n删除节点 4 后,二叉树为\n'); printTree(getRoot()); export {}; diff --git a/codes/typescript/chapter_tree/binary_tree.ts b/codes/typescript/chapter_tree/binary_tree.ts index 56f8162b..c3a2f390 100644 --- a/codes/typescript/chapter_tree/binary_tree.ts +++ b/codes/typescript/chapter_tree/binary_tree.ts @@ -8,7 +8,7 @@ import { TreeNode } from '../modules/TreeNode'; import { printTree } from '../modules/PrintUtil'; /* 初始化二叉树 */ -// 初始化结点 +// 初始化节点 let n1 = new TreeNode(1), n2 = new TreeNode(2), n3 = new TreeNode(3), @@ -22,16 +22,16 @@ n2.right = n5; console.log('\n初始化二叉树\n'); printTree(n1); -/* 插入与删除结点 */ +/* 插入与删除节点 */ const P = new TreeNode(0); -// 在 n1 -> n2 中间插入结点 P +// 在 n1 -> n2 中间插入节点 P n1.left = P; P.left = n2; -console.log('\n插入结点 P 后\n'); +console.log('\n插入节点 P 后\n'); printTree(n1); -// 删除结点 P +// 删除节点 P n1.left = n2; -console.log('\n删除结点 P 后\n'); +console.log('\n删除节点 P 后\n'); printTree(n1); export {}; diff --git a/codes/typescript/chapter_tree/binary_tree_bfs.ts b/codes/typescript/chapter_tree/binary_tree_bfs.ts index 9fe7741e..5afff7e7 100644 --- a/codes/typescript/chapter_tree/binary_tree_bfs.ts +++ b/codes/typescript/chapter_tree/binary_tree_bfs.ts @@ -10,18 +10,18 @@ import { printTree } from '../modules/PrintUtil'; /* 层序遍历 */ function levelOrder(root: TreeNode | null): number[] { - // 初始化队列,加入根结点 + // 初始化队列,加入根节点 const queue = [root]; // 初始化一个列表,用于保存遍历序列 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); // 左子结点入队 + queue.push(node.left); // 左子节点入队 } if (node.right) { - queue.push(node.right); // 右子结点入队 + queue.push(node.right); // 右子节点入队 } } return list; @@ -36,6 +36,6 @@ printTree(root); /* 层序遍历 */ const list = levelOrder(root); -console.log('\n层序遍历的结点打印序列 = ' + list); +console.log('\n层序遍历的节点打印序列 = ' + list); export {}; diff --git a/codes/typescript/chapter_tree/binary_tree_dfs.ts b/codes/typescript/chapter_tree/binary_tree_dfs.ts index e082f1a1..23c84377 100644 --- a/codes/typescript/chapter_tree/binary_tree_dfs.ts +++ b/codes/typescript/chapter_tree/binary_tree_dfs.ts @@ -16,7 +16,7 @@ function preOrder(root: TreeNode | null): void { if (root === null) { return; } - // 访问优先级:根结点 -> 左子树 -> 右子树 + // 访问优先级:根节点 -> 左子树 -> 右子树 list.push(root.val); preOrder(root.left); preOrder(root.right); @@ -27,7 +27,7 @@ function inOrder(root: TreeNode | null): void { if (root === null) { return; } - // 访问优先级:左子树 -> 根结点 -> 右子树 + // 访问优先级:左子树 -> 根节点 -> 右子树 inOrder(root.left); list.push(root.val); inOrder(root.right); @@ -38,7 +38,7 @@ function postOrder(root: TreeNode | null): void { if (root === null) { return; } - // 访问优先级:左子树 -> 右子树 -> 根结点 + // 访问优先级:左子树 -> 右子树 -> 根节点 postOrder(root.left); postOrder(root.right); list.push(root.val); @@ -54,16 +54,16 @@ printTree(root); /* 前序遍历 */ list.length = 0; preOrder(root); -console.log('\n前序遍历的结点打印序列 = ' + list); +console.log('\n前序遍历的节点打印序列 = ' + list); /* 中序遍历 */ list.length = 0; inOrder(root); -console.log('\n中序遍历的结点打印序列 = ' + list); +console.log('\n中序遍历的节点打印序列 = ' + list); /* 后序遍历 */ list.length = 0; postOrder(root); -console.log('\n后序遍历的结点打印序列 = ' + list); +console.log('\n后序遍历的节点打印序列 = ' + list); export {}; diff --git a/codes/typescript/modules/TreeNode.ts b/codes/typescript/modules/TreeNode.ts index 905ce921..0ea757c4 100644 --- a/codes/typescript/modules/TreeNode.ts +++ b/codes/typescript/modules/TreeNode.ts @@ -8,10 +8,10 @@ * Definition for a binary tree node. */ class TreeNode { - val: number; // 结点值 - height: number; // 结点高度 - left: TreeNode | null; // 左子结点指针 - right: TreeNode | null; // 右子结点指针 + 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; diff --git a/codes/zig/chapter_array_and_linkedlist/linked_list.zig b/codes/zig/chapter_array_and_linkedlist/linked_list.zig index 0e56c88b..0ffef48e 100644 --- a/codes/zig/chapter_array_and_linkedlist/linked_list.zig +++ b/codes/zig/chapter_array_and_linkedlist/linked_list.zig @@ -5,14 +5,14 @@ const std = @import("std"); const inc = @import("include"); -// 在链表的结点 n0 之后插入结点 P +// 在链表的节点 n0 之后插入节点 P pub fn insert(n0: ?*inc.ListNode(i32), P: ?*inc.ListNode(i32)) void { var n1 = n0.?.next; P.?.next = n1; n0.?.next = P; } -// 删除链表的结点 n0 之后的首个结点 +// 删除链表的节点 n0 之后的首个节点 pub fn remove(n0: ?*inc.ListNode(i32)) void { if (n0.?.next == null) return; // n0 -> P -> n1 @@ -21,7 +21,7 @@ pub fn remove(n0: ?*inc.ListNode(i32)) void { n0.?.next = n1; } -// 访问链表中索引为 index 的结点 +// 访问链表中索引为 index 的节点 pub fn access(node: ?*inc.ListNode(i32), index: i32) ?*inc.ListNode(i32) { var head = node; var i: i32 = 0; @@ -32,7 +32,7 @@ pub fn access(node: ?*inc.ListNode(i32), index: i32) ?*inc.ListNode(i32) { return head; } -// 在链表中查找值为 target 的首个结点 +// 在链表中查找值为 target 的首个节点 pub fn find(node: ?*inc.ListNode(i32), target: i32) i32 { var head = node; var index: i32 = 0; @@ -47,7 +47,7 @@ pub fn find(node: ?*inc.ListNode(i32), target: i32) i32 { // Driver Code pub fn main() !void { // 初始化链表 - // 初始化各个结点 + // 初始化各个节点 var n0 = inc.ListNode(i32){.val = 1}; var n1 = inc.ListNode(i32){.val = 3}; var n2 = inc.ListNode(i32){.val = 2}; @@ -61,24 +61,24 @@ pub fn main() !void { std.debug.print("初始化的链表为", .{}); try inc.PrintUtil.printLinkedList(i32, &n0); - // 插入结点 + // 插入节点 var tmp = inc.ListNode(i32){.val = 0}; insert(&n0, &tmp); - std.debug.print("插入结点后的链表为", .{}); + std.debug.print("插入节点后的链表为", .{}); try inc.PrintUtil.printLinkedList(i32, &n0); - // 删除结点 + // 删除节点 remove(&n0); - std.debug.print("删除结点后的链表为", .{}); + std.debug.print("删除节点后的链表为", .{}); try inc.PrintUtil.printLinkedList(i32, &n0); - // 访问结点 + // 访问节点 var node = access(&n0, 3); - std.debug.print("链表中索引 3 处的结点的值 = {}\n", .{node.?.val}); + std.debug.print("链表中索引 3 处的节点的值 = {}\n", .{node.?.val}); - // 查找结点 + // 查找节点 var index = find(&n0, 2); - std.debug.print("链表中值为 2 的结点的索引 = {}\n", .{index}); + std.debug.print("链表中值为 2 的节点的索引 = {}\n", .{index}); _ = try std.io.getStdIn().reader().readByte(); } \ No newline at end of file diff --git a/codes/zig/chapter_heap/my_heap.zig b/codes/zig/chapter_heap/my_heap.zig index 059649cc..ce5f694e 100644 --- a/codes/zig/chapter_heap/my_heap.zig +++ b/codes/zig/chapter_heap/my_heap.zig @@ -18,7 +18,7 @@ pub fn MaxHeap(comptime T: type) type { self.max_heap = std.ArrayList(T).init(allocator); // 将列表元素原封不动添加进堆 try self.max_heap.?.appendSlice(nums); - // 堆化除叶结点以外的其他所有结点 + // 堆化除叶节点以外的其他所有节点 var i: usize = parent(self.size() - 1) + 1; while (i > 0) : (i -= 1) { try self.siftDown(i - 1); @@ -30,17 +30,17 @@ pub fn MaxHeap(comptime T: type) type { if (self.max_heap != null) self.max_heap.?.deinit(); } - // 获取左子结点索引 + // 获取左子节点索引 fn left(i: usize) usize { return 2 * i + 1; } - // 获取右子结点索引 + // 获取右子节点索引 fn right(i: usize) usize { return 2 * i + 2; } - // 获取父结点索引 + // 获取父节点索引 fn parent(i: usize) usize { // return (i - 1) / 2; // 向下整除 return @divFloor(i - 1, 2); @@ -72,21 +72,21 @@ pub fn MaxHeap(comptime T: type) type { // 元素入堆 pub fn push(self: *Self, val: T) !void { - // 添加结点 + // 添加节点 try self.max_heap.?.append(val); // 从底至顶堆化 try self.siftUp(self.size() - 1); } - // 从结点 i 开始,从底至顶堆化 + // 从节点 i 开始,从底至顶堆化 fn siftUp(self: *Self, i_: usize) !void { var i = i_; while (true) { - // 获取结点 i 的父结点 + // 获取节点 i 的父节点 var p = parent(i); - // 当“越过根结点”或“结点无需修复”时,结束堆化 + // 当“越过根节点”或“节点无需修复”时,结束堆化 if (p < 0 or self.max_heap.?.items[i] <= self.max_heap.?.items[p]) break; - // 交换两结点 + // 交换两节点 try self.swap(i, p); // 循环向上堆化 i = p; @@ -97,9 +97,9 @@ pub fn MaxHeap(comptime T: type) type { pub fn pop(self: *Self) !T { // 判断处理 if (self.isEmpty()) unreachable; - // 交换根结点与最右叶结点(即交换首元素与尾元素) + // 交换根节点与最右叶节点(即交换首元素与尾元素) try self.swap(0, self.size() - 1); - // 删除结点 + // 删除节点 var val = self.max_heap.?.pop(); // 从顶至底堆化 try self.siftDown(0); @@ -107,19 +107,19 @@ pub fn MaxHeap(comptime T: type) type { return val; } - // 从结点 i 开始,从顶至底堆化 + // 从节点 i 开始,从顶至底堆化 fn siftDown(self: *Self, i_: usize) !void { var i = i_; while (true) { - // 判断结点 i, l, r 中值最大的结点,记为 ma + // 判断节点 i, l, r 中值最大的节点,记为 ma var l = left(i); var r = right(i); var ma = i; if (l < self.size() and self.max_heap.?.items[l] > self.max_heap.?.items[ma]) ma = l; if (r < self.size() and self.max_heap.?.items[r] > self.max_heap.?.items[ma]) ma = r; - // 若结点 i 最大或索引 l, r 越界,则无需继续堆化,跳出 + // 若节点 i 最大或索引 l, r 越界,则无需继续堆化,跳出 if (ma == i) break; - // 交换两结点 + // 交换两节点 try self.swap(i, ma); // 循环向下堆化 i = ma; diff --git a/codes/zig/chapter_searching/hashing_search.zig b/codes/zig/chapter_searching/hashing_search.zig index ba3abba3..5cd9aa4a 100644 --- a/codes/zig/chapter_searching/hashing_search.zig +++ b/codes/zig/chapter_searching/hashing_search.zig @@ -15,7 +15,7 @@ fn hashingSearchArray(comptime T: type, map: std.AutoHashMap(T, T), target: T) T // 哈希查找(链表) fn hashingSearchLinkedList(comptime T: type, map: std.AutoHashMap(T, *inc.ListNode(T)), target: T) ?*inc.ListNode(T) { - // 哈希表的 key: 目标结点值,value: 结点对象 + // 哈希表的 key: 目标节点值,value: 节点对象 // 若哈希表中无此 key ,返回 null if (map.getKey(target) == null) return null; return map.get(target); @@ -49,7 +49,7 @@ pub fn main() !void { head = head.?.next; } var node = hashingSearchLinkedList(i32, map1, target); - std.debug.print("目标结点值 3 的对应结点对象为 ", .{}); + std.debug.print("目标节点值 3 的对应节点对象为 ", .{}); try inc.PrintUtil.printLinkedList(i32, node); _ = try std.io.getStdIn().reader().readByte(); diff --git a/codes/zig/chapter_searching/linear_search.zig b/codes/zig/chapter_searching/linear_search.zig index 151ed5ae..74e435e0 100644 --- a/codes/zig/chapter_searching/linear_search.zig +++ b/codes/zig/chapter_searching/linear_search.zig @@ -23,7 +23,7 @@ pub fn linearSearchLinkedList(comptime T: type, node: ?*inc.ListNode(T), target: var head = node; // 遍历链表 while (head != null) { - // 找到目标结点,返回之 + // 找到目标节点,返回之 if (head.?.val == target) return head; head = head.?.next; } @@ -47,7 +47,7 @@ pub fn main() !void { const mem_allocator = mem_arena.allocator(); var head = try inc.ListUtil.listToLinkedList(i32, mem_allocator, nums); var node = linearSearchLinkedList(i32, head, target); - std.debug.print("目标结点值 3 的对应结点对象为 ", .{}); + std.debug.print("目标节点值 3 的对应节点对象为 ", .{}); try inc.PrintUtil.printLinkedList(i32, node); _ = try std.io.getStdIn().reader().readByte(); diff --git a/codes/zig/chapter_stack_and_queue/linkedlist_deque.zig b/codes/zig/chapter_stack_and_queue/linkedlist_deque.zig index 0c8bae72..aade2ebb 100644 --- a/codes/zig/chapter_stack_and_queue/linkedlist_deque.zig +++ b/codes/zig/chapter_stack_and_queue/linkedlist_deque.zig @@ -5,14 +5,14 @@ const std = @import("std"); const inc = @import("include"); -// 双向链表结点 +// 双向链表节点 pub fn ListNode(comptime T: type) type { return struct { const Self = @This(); - val: T = undefined, // 结点值 - next: ?*Self = null, // 后继结点引用(指针) - prev: ?*Self = null, // 前驱结点引用(指针) + val: T = undefined, // 节点值 + next: ?*Self = null, // 后继节点引用(指针) + prev: ?*Self = null, // 前驱节点引用(指针) // Initialize a list node with specific value pub fn init(self: *Self, x: i32) void { @@ -28,8 +28,8 @@ pub fn LinkedListDeque(comptime T: type) type { return struct { const Self = @This(); - front: ?*ListNode(T) = null, // 头结点 front - rear: ?*ListNode(T) = null, // 尾结点 rear + front: ?*ListNode(T) = null, // 头节点 front + rear: ?*ListNode(T) = null, // 尾节点 rear que_size: usize = 0, // 双向队列的长度 mem_arena: ?std.heap.ArenaAllocator = null, mem_allocator: std.mem.Allocator = undefined, // 内存分配器 @@ -74,13 +74,13 @@ pub fn LinkedListDeque(comptime T: type) type { // 将 node 添加至链表头部 self.front.?.prev = node; node.next = self.front; - self.front = node; // 更新头结点 + self.front = node; // 更新头节点 // 队尾入队操作 } else { // 将 node 添加至链表尾部 self.rear.?.next = node; node.prev = self.rear; - self.rear = node; // 更新尾结点 + self.rear = node; // 更新尾节点 } self.que_size += 1; // 更新队列长度 } @@ -101,24 +101,24 @@ pub fn LinkedListDeque(comptime T: type) type { var val: T = undefined; // 队首出队操作 if (is_front) { - val = self.front.?.val; // 暂存头结点值 - // 删除头结点 + val = self.front.?.val; // 暂存头节点值 + // 删除头节点 var fNext = self.front.?.next; if (fNext != null) { fNext.?.prev = null; self.front.?.next = null; } - self.front = fNext; // 更新头结点 + self.front = fNext; // 更新头节点 // 队尾出队操作 } else { - val = self.rear.?.val; // 暂存尾结点值 - // 删除尾结点 + val = self.rear.?.val; // 暂存尾节点值 + // 删除尾节点 var rPrev = self.rear.?.prev; if (rPrev != null) { rPrev.?.next = null; self.rear.?.prev = null; } - self.rear = rPrev; // 更新尾结点 + self.rear = rPrev; // 更新尾节点 } self.que_size -= 1; // 更新队列长度 return val; diff --git a/codes/zig/chapter_stack_and_queue/linkedlist_queue.zig b/codes/zig/chapter_stack_and_queue/linkedlist_queue.zig index 78c92274..11b60459 100644 --- a/codes/zig/chapter_stack_and_queue/linkedlist_queue.zig +++ b/codes/zig/chapter_stack_and_queue/linkedlist_queue.zig @@ -10,8 +10,8 @@ pub fn LinkedListQueue(comptime T: type) type { return struct { const Self = @This(); - front: ?*inc.ListNode(T) = null, // 头结点 front - rear: ?*inc.ListNode(T) = null, // 尾结点 rear + front: ?*inc.ListNode(T) = null, // 头节点 front + rear: ?*inc.ListNode(T) = null, // 尾节点 rear que_size: usize = 0, // 队列的长度 mem_arena: ?std.heap.ArenaAllocator = null, mem_allocator: std.mem.Allocator = undefined, // 内存分配器 @@ -51,14 +51,14 @@ pub fn LinkedListQueue(comptime T: type) type { // 入队 pub fn push(self: *Self, num: T) !void { - // 尾结点后添加 num + // 尾节点后添加 num var node = try self.mem_allocator.create(inc.ListNode(T)); node.init(num); - // 如果队列为空,则令头、尾结点都指向该结点 + // 如果队列为空,则令头、尾节点都指向该节点 if (self.front == null) { self.front = node; self.rear = node; - // 如果队列不为空,则将该结点添加到尾结点后 + // 如果队列不为空,则将该节点添加到尾节点后 } else { self.rear.?.next = node; self.rear = node; @@ -69,7 +69,7 @@ pub fn LinkedListQueue(comptime T: type) type { // 出队 pub fn pop(self: *Self) T { var num = self.peek(); - // 删除头结点 + // 删除头节点 self.front = self.front.?.next; self.que_size -= 1; return num; diff --git a/codes/zig/chapter_stack_and_queue/linkedlist_stack.zig b/codes/zig/chapter_stack_and_queue/linkedlist_stack.zig index 67ab9882..4d4cc1b9 100644 --- a/codes/zig/chapter_stack_and_queue/linkedlist_stack.zig +++ b/codes/zig/chapter_stack_and_queue/linkedlist_stack.zig @@ -10,7 +10,7 @@ pub fn LinkedListStack(comptime T: type) type { return struct { const Self = @This(); - stack_top: ?*inc.ListNode(T) = null, // 将头结点作为栈顶 + stack_top: ?*inc.ListNode(T) = null, // 将头节点作为栈顶 stk_size: usize = 0, // 栈的长度 mem_arena: ?std.heap.ArenaAllocator = null, mem_allocator: std.mem.Allocator = undefined, // 内存分配器 diff --git a/codes/zig/chapter_tree/avl_tree.zig b/codes/zig/chapter_tree/avl_tree.zig index dec13c18..b6647207 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, // 内存分配器 @@ -28,24 +28,24 @@ pub fn AVLTree(comptime T: type) type { self.mem_arena.?.deinit(); } - // 获取结点高度 + // 获取节点高度 fn height(self: *Self, node: ?*inc.TreeNode(T)) i32 { _ = self; - // 空结点高度为 -1 ,叶结点高度为 0 + // 空节点高度为 -1 ,叶节点高度为 0 return if (node == null) -1 else node.?.height; } - // 更新结点高度 + // 更新节点高度 fn updateHeight(self: *Self, node: ?*inc.TreeNode(T)) void { - // 结点高度等于最高子树高度 + 1 + // 节点高度等于最高子树高度 + 1 node.?.height = std.math.max(self.height(node.?.left), self.height(node.?.right)) + 1; } // 获取平衡因子 fn balanceFactor(self: *Self, node: ?*inc.TreeNode(T)) i32 { - // 空结点平衡因子为 0 + // 空节点平衡因子为 0 if (node == null) return 0; - // 结点平衡因子 = 左子树高度 - 右子树高度 + // 节点平衡因子 = 左子树高度 - 右子树高度 return self.height(node.?.left) - self.height(node.?.right); } @@ -56,10 +56,10 @@ pub fn AVLTree(comptime T: type) type { // 以 child 为原点,将 node 向右旋转 child.?.right = node; node.?.left = grandChild; - // 更新结点高度 + // 更新节点高度 self.updateHeight(node); self.updateHeight(child); - // 返回旋转后子树的根结点 + // 返回旋转后子树的根节点 return child; } @@ -70,16 +70,16 @@ pub fn AVLTree(comptime T: type) type { // 以 child 为原点,将 node 向左旋转 child.?.left = node; node.?.right = grandChild; - // 更新结点高度 + // 更新节点高度 self.updateHeight(node); self.updateHeight(child); - // 返回旋转后子树的根结点 + // 返回旋转后子树的根节点 return child; } // 执行旋转操作,使该子树重新恢复平衡 fn rotate(self: *Self, node: ?*inc.TreeNode(T)) ?*inc.TreeNode(T) { - // 获取结点 node 的平衡因子 + // 获取节点 node 的平衡因子 var balance_factor = self.balanceFactor(node); // 左偏树 if (balance_factor > 1) { @@ -107,13 +107,13 @@ pub fn AVLTree(comptime T: type) type { return node; } - // 插入结点 + // 插入节点 fn insert(self: *Self, val: T) !?*inc.TreeNode(T) { self.root = try self.insertHelper(self.root, val); return self.root; } - // 递归插入结点(辅助方法) + // 递归插入节点(辅助方法) fn insertHelper(self: *Self, node_: ?*inc.TreeNode(T), val: T) !?*inc.TreeNode(T) { var node = node_; if (node == null) { @@ -121,32 +121,32 @@ pub fn AVLTree(comptime T: type) type { tmp_node.init(val); return tmp_node; } - // 1. 查找插入位置,并插入结点 + // 1. 查找插入位置,并插入节点 if (val < node.?.val) { node.?.left = try self.insertHelper(node.?.left, val); } else if (val > node.?.val) { node.?.right = try self.insertHelper(node.?.right, val); } else { - return node; // 重复结点不插入,直接返回 + return node; // 重复节点不插入,直接返回 } - self.updateHeight(node); // 更新结点高度 + self.updateHeight(node); // 更新节点高度 // 2. 执行旋转操作,使该子树重新恢复平衡 node = self.rotate(node); - // 返回子树的根结点 + // 返回子树的根节点 return node; } - // 删除结点 + // 删除节点 fn remove(self: *Self, val: T) ?*inc.TreeNode(T) { self.root = self.removeHelper(self.root, val); return self.root; } - // 递归删除结点(辅助方法) + // 递归删除节点(辅助方法) fn removeHelper(self: *Self, node_: ?*inc.TreeNode(T), val: T) ?*inc.TreeNode(T) { var node = node_; if (node == null) return null; - // 1. 查找结点,并删除之 + // 1. 查找节点,并删除之 if (val < node.?.val) { node.?.left = self.removeHelper(node.?.left, val); } else if (val > node.?.val) { @@ -154,56 +154,56 @@ pub fn AVLTree(comptime T: type) type { } else { if (node.?.left == null or node.?.right == null) { var child = if (node.?.left != null) node.?.left else node.?.right; - // 子结点数量 = 0 ,直接删除 node 并返回 + // 子节点数量 = 0 ,直接删除 node 并返回 if (child == null) { return null; - // 子结点数量 = 1 ,直接删除 node + // 子节点数量 = 1 ,直接删除 node } else { node = child; } } else { - // 子结点数量 = 2 ,则将中序遍历的下个结点删除,并用该结点替换当前结点 + // 子节点数量 = 2 ,则将中序遍历的下个节点删除,并用该节点替换当前节点 var temp = self.getInOrderNext(node.?.right); node.?.right = self.removeHelper(node.?.right, temp.?.val); node.?.val = temp.?.val; } } - self.updateHeight(node); // 更新结点高度 + self.updateHeight(node); // 更新节点高度 // 2. 执行旋转操作,使该子树重新恢复平衡 node = self.rotate(node); - // 返回子树的根结点 + // 返回子树的根节点 return node; } - // 获取中序遍历中的下一个结点(仅适用于 root 有左子结点的情况) + // 获取中序遍历中的下一个节点(仅适用于 root 有左子节点的情况) fn getInOrderNext(self: *Self, node_: ?*inc.TreeNode(T)) ?*inc.TreeNode(T) { _ = self; var node = node_; if (node == null) return node; - // 循环访问左子结点,直到叶结点时为最小结点,跳出 + // 循环访问左子节点,直到叶节点时为最小节点,跳出 while (node.?.left != null) { node = node.?.left; } return node; } - // 查找结点 + // 查找节点 fn search(self: *Self, val: T) ?*inc.TreeNode(T) { var cur = self.root; - // 循环查找,越过叶结点后跳出 + // 循环查找,越过叶节点后跳出 while (cur != null) { - // 目标结点在 cur 的右子树中 + // 目标节点在 cur 的右子树中 if (cur.?.val < val) { cur = cur.?.right; - // 目标结点在 cur 的左子树中 + // 目标节点在 cur 的左子树中 } else if (cur.?.val > val) { cur = cur.?.left; - // 找到目标结点,跳出循环 + // 找到目标节点,跳出循环 } else { break; } } - // 返回目标结点 + // 返回目标节点 return cur; } }; @@ -212,14 +212,14 @@ pub fn AVLTree(comptime T: type) type { pub fn testInsert(comptime T: type, tree_: *AVLTree(T), val: T) !void { var tree = tree_; _ = try tree.insert(val); - std.debug.print("\n插入结点 {} 后,AVL 树为\n", .{val}); + std.debug.print("\n插入节点 {} 后,AVL 树为\n", .{val}); try inc.PrintUtil.printTree(tree.root, null, false); } pub fn testRemove(comptime T: type, tree_: *AVLTree(T), val: T) void { var tree = tree_; _ = tree.remove(val); - std.debug.print("\n删除结点 {} 后,AVL 树为\n", .{val}); + std.debug.print("\n删除节点 {} 后,AVL 树为\n", .{val}); try inc.PrintUtil.printTree(tree.root, null, false); } @@ -230,8 +230,8 @@ pub fn main() !void { avl_tree.init(std.heap.page_allocator); defer avl_tree.deinit(); - // 插入结点 - // 请关注插入结点后,AVL 树是如何保持平衡的 + // 插入节点 + // 请关注插入节点后,AVL 树是如何保持平衡的 try testInsert(i32, &avl_tree, 1); try testInsert(i32, &avl_tree, 2); try testInsert(i32, &avl_tree, 3); @@ -243,18 +243,18 @@ pub fn main() !void { try testInsert(i32, &avl_tree, 10); try testInsert(i32, &avl_tree, 6); - // 插入重复结点 + // 插入重复节点 try testInsert(i32, &avl_tree, 7); - // 删除结点 - // 请关注删除结点后,AVL 树是如何保持平衡的 - testRemove(i32, &avl_tree, 8); // 删除度为 0 的结点 - testRemove(i32, &avl_tree, 5); // 删除度为 1 的结点 - testRemove(i32, &avl_tree, 4); // 删除度为 2 的结点 + // 删除节点 + // 请关注删除节点后,AVL 树是如何保持平衡的 + testRemove(i32, &avl_tree, 8); // 删除度为 0 的节点 + testRemove(i32, &avl_tree, 5); // 删除度为 1 的节点 + testRemove(i32, &avl_tree, 4); // 删除度为 2 的节点 - // 查找结点 + // 查找节点 var node = avl_tree.search(7).?; - std.debug.print("\n查找到的结点对象为 {any},结点值 = {}\n", .{node, node.val}); + std.debug.print("\n查找到的节点对象为 {any},节点值 = {}\n", .{node, node.val}); _ = try std.io.getStdIn().reader().readByte(); } \ No newline at end of file diff --git a/codes/zig/chapter_tree/binary_search_tree.zig b/codes/zig/chapter_tree/binary_search_tree.zig index f4d08ddc..c94cdb6c 100644 --- a/codes/zig/chapter_tree/binary_search_tree.zig +++ b/codes/zig/chapter_tree/binary_search_tree.zig @@ -33,7 +33,7 @@ pub fn BinarySearchTree(comptime T: type) type { // 构建二叉搜索树 fn buildTree(self: *Self, nums: []T, i: usize, j: usize) !?*inc.TreeNode(T) { if (i > j) return null; - // 将数组中间结点作为根结点 + // 将数组中间节点作为根节点 var mid = (i + j) / 2; var node = try self.mem_allocator.create(inc.TreeNode(T)); node.init(nums[mid]); @@ -43,40 +43,40 @@ pub fn BinarySearchTree(comptime T: type) type { return node; } - // 获取二叉树根结点 + // 获取二叉树根节点 fn getRoot(self: *Self) ?*inc.TreeNode(T) { return self.root; } - // 查找结点 + // 查找节点 fn search(self: *Self, num: T) ?*inc.TreeNode(T) { var cur = self.root; - // 循环查找,越过叶结点后跳出 + // 循环查找,越过叶节点后跳出 while (cur != null) { - // 目标结点在 cur 的右子树中 + // 目标节点在 cur 的右子树中 if (cur.?.val < num) { cur = cur.?.right; - // 目标结点在 cur 的左子树中 + // 目标节点在 cur 的左子树中 } else if (cur.?.val > num) { cur = cur.?.left; - // 找到目标结点,跳出循环 + // 找到目标节点,跳出循环 } else { break; } } - // 返回目标结点 + // 返回目标节点 return cur; } - // 插入结点 + // 插入节点 fn insert(self: *Self, num: T) !?*inc.TreeNode(T) { // 若树为空,直接提前返回 if (self.root == null) return null; var cur = self.root; var pre: ?*inc.TreeNode(T) = null; - // 循环查找,越过叶结点后跳出 + // 循环查找,越过叶节点后跳出 while (cur != null) { - // 找到重复结点,直接返回 + // 找到重复节点,直接返回 if (cur.?.val == num) return null; pre = cur; // 插入位置在 cur 的右子树中 @@ -87,7 +87,7 @@ pub fn BinarySearchTree(comptime T: type) type { cur = cur.?.left; } } - // 插入结点 val + // 插入节点 val var node = try self.mem_allocator.create(inc.TreeNode(T)); node.init(num); if (pre.?.val < num) { @@ -98,43 +98,43 @@ pub fn BinarySearchTree(comptime T: type) type { return node; } - // 删除结点 + // 删除节点 fn remove(self: *Self, num: T) ?*inc.TreeNode(T) { // 若树为空,直接提前返回 if (self.root == null) return null; var cur = self.root; var pre: ?*inc.TreeNode(T) = null; - // 循环查找,越过叶结点后跳出 + // 循环查找,越过叶节点后跳出 while (cur != null) { - // 找到待删除结点,跳出循环 + // 找到待删除节点,跳出循环 if (cur.?.val == num) break; pre = cur; - // 待删除结点在 cur 的右子树中 + // 待删除节点在 cur 的右子树中 if (cur.?.val < num) { cur = cur.?.right; - // 待删除结点在 cur 的左子树中 + // 待删除节点在 cur 的左子树中 } else { cur = cur.?.left; } } - // 若无待删除结点,则直接返回 + // 若无待删除节点,则直接返回 if (cur == null) return null; - // 子结点数量 = 0 or 1 + // 子节点数量 = 0 or 1 if (cur.?.left == null or cur.?.right == null) { - // 当子结点数量 = 0 / 1 时, child = null / 该子结点 + // 当子节点数量 = 0 / 1 时, child = null / 该子节点 var child = if (cur.?.left != null) cur.?.left else cur.?.right; - // 删除结点 cur + // 删除节点 cur if (pre.?.left == cur) { pre.?.left = child; } else { pre.?.right = child; } - // 子结点数量 = 2 + // 子节点数量 = 2 } else { - // 获取中序遍历中 cur 的下一个结点 + // 获取中序遍历中 cur 的下一个节点 var nex = self.getInOrderNext(cur.?.right); var tmp = nex.?.val; - // 递归删除结点 nex + // 递归删除节点 nex _ = self.remove(nex.?.val); // 将 nex 的值复制给 cur cur.?.val = tmp; @@ -142,12 +142,12 @@ pub fn BinarySearchTree(comptime T: type) type { return cur; } - // 获取中序遍历中的下一个结点(仅适用于 root 有左子结点的情况) + // 获取中序遍历中的下一个节点(仅适用于 root 有左子节点的情况) fn getInOrderNext(self: *Self, node: ?*inc.TreeNode(T)) ?*inc.TreeNode(T) { _ = self; var node_tmp = node; if (node_tmp == null) return null; - // 循环访问左子结点,直到叶结点时为最小结点,跳出 + // 循环访问左子节点,直到叶节点时为最小节点,跳出 while (node_tmp.?.left != null) { node_tmp = node_tmp.?.left; } @@ -166,24 +166,24 @@ pub fn main() !void { std.debug.print("初始化的二叉树为\n", .{}); try inc.PrintUtil.printTree(bst.getRoot(), null, false); - // 查找结点 + // 查找节点 var node = bst.search(7); - std.debug.print("\n查找到的结点对象为 {any},结点值 = {}\n", .{node, node.?.val}); + std.debug.print("\n查找到的节点对象为 {any},节点值 = {}\n", .{node, node.?.val}); - // 插入结点 + // 插入节点 node = try bst.insert(16); - std.debug.print("\n插入结点 16 后,二叉树为\n", .{}); + std.debug.print("\n插入节点 16 后,二叉树为\n", .{}); try inc.PrintUtil.printTree(bst.getRoot(), null, false); - // 删除结点 + // 删除节点 _ = bst.remove(1); - std.debug.print("\n删除结点 1 后,二叉树为\n", .{}); + std.debug.print("\n删除节点 1 后,二叉树为\n", .{}); try inc.PrintUtil.printTree(bst.getRoot(), null, false); _ = bst.remove(2); - std.debug.print("\n删除结点 2 后,二叉树为\n", .{}); + std.debug.print("\n删除节点 2 后,二叉树为\n", .{}); try inc.PrintUtil.printTree(bst.getRoot(), null, false); _ = bst.remove(4); - std.debug.print("\n删除结点 4 后,二叉树为\n", .{}); + std.debug.print("\n删除节点 4 后,二叉树为\n", .{}); try inc.PrintUtil.printTree(bst.getRoot(), null, false); _ = try std.io.getStdIn().reader().readByte(); diff --git a/codes/zig/chapter_tree/binary_tree.zig b/codes/zig/chapter_tree/binary_tree.zig index f193543c..db799f3f 100644 --- a/codes/zig/chapter_tree/binary_tree.zig +++ b/codes/zig/chapter_tree/binary_tree.zig @@ -8,7 +8,7 @@ const inc = @import("include"); // Driver Code pub fn main() !void { // 初始化二叉树 - // 初始化结点 + // 初始化节点 var n1 = inc.TreeNode(i32){ .val = 1 }; var n2 = inc.TreeNode(i32){ .val = 2 }; var n3 = inc.TreeNode(i32){ .val = 3 }; @@ -22,16 +22,16 @@ pub fn main() !void { std.debug.print("初始化二叉树\n", .{}); try inc.PrintUtil.printTree(&n1, null, false); - // 插入与删除结点 + // 插入与删除节点 var p = inc.TreeNode(i32){ .val = 0 }; - // 在 n1 -> n2 中间插入结点 P + // 在 n1 -> n2 中间插入节点 P n1.left = &p; p.left = &n2; - std.debug.print("插入结点 P 后\n", .{}); + std.debug.print("插入节点 P 后\n", .{}); try inc.PrintUtil.printTree(&n1, null, false); - // 删除结点 + // 删除节点 n1.left = &n2; - std.debug.print("删除结点 P 后\n", .{}); + std.debug.print("删除节点 P 后\n", .{}); try inc.PrintUtil.printTree(&n1, null, false); _ = try std.io.getStdIn().reader().readByte(); diff --git a/codes/zig/chapter_tree/binary_tree_bfs.zig b/codes/zig/chapter_tree/binary_tree_bfs.zig index dc0cb672..c58d4fbd 100644 --- a/codes/zig/chapter_tree/binary_tree_bfs.zig +++ b/codes/zig/chapter_tree/binary_tree_bfs.zig @@ -7,7 +7,7 @@ const inc = @import("include"); // 层序遍历 fn levelOrder(comptime T: type, mem_allocator: std.mem.Allocator, root: *inc.TreeNode(T)) !std.ArrayList(T) { - // 初始化队列,加入根结点 + // 初始化队列,加入根节点 const L = std.TailQueue(*inc.TreeNode(T)); var queue = L{}; var root_node = try mem_allocator.create(L.Node); @@ -18,16 +18,16 @@ fn levelOrder(comptime T: type, mem_allocator: std.mem.Allocator, root: *inc.Tre 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.?; - queue.append(tmp_node); // 左子结点入队 + queue.append(tmp_node); // 左子节点入队 } if (node.right != null) { var tmp_node = try mem_allocator.create(L.Node); tmp_node.data = node.right.?; - queue.append(tmp_node); // 右子结点入队 + queue.append(tmp_node); // 右子节点入队 } } return list; @@ -50,7 +50,7 @@ pub fn main() !void { // 层序遍历 var list = try levelOrder(i32, mem_allocator, root.?); defer list.deinit(); - std.debug.print("\n层序遍历的结点打印序列 = ", .{}); + std.debug.print("\n层序遍历的节点打印序列 = ", .{}); inc.PrintUtil.printList(i32, list); _ = try std.io.getStdIn().reader().readByte(); diff --git a/codes/zig/chapter_tree/binary_tree_dfs.zig b/codes/zig/chapter_tree/binary_tree_dfs.zig index dba49188..9eecc5df 100644 --- a/codes/zig/chapter_tree/binary_tree_dfs.zig +++ b/codes/zig/chapter_tree/binary_tree_dfs.zig @@ -10,7 +10,7 @@ var list = std.ArrayList(i32).init(std.heap.page_allocator); // 前序遍历 fn preOrder(comptime T: type, root: ?*inc.TreeNode(T)) !void { if (root == null) return; - // 访问优先级:根结点 -> 左子树 -> 右子树 + // 访问优先级:根节点 -> 左子树 -> 右子树 try list.append(root.?.val); try preOrder(T, root.?.left); try preOrder(T, root.?.right); @@ -19,7 +19,7 @@ fn preOrder(comptime T: type, root: ?*inc.TreeNode(T)) !void { // 中序遍历 fn inOrder(comptime T: type, root: ?*inc.TreeNode(T)) !void { if (root == null) return; - // 访问优先级:左子树 -> 根结点 -> 右子树 + // 访问优先级:左子树 -> 根节点 -> 右子树 try inOrder(T, root.?.left); try list.append(root.?.val); try inOrder(T, root.?.right); @@ -28,7 +28,7 @@ fn inOrder(comptime T: type, root: ?*inc.TreeNode(T)) !void { // 后序遍历 fn postOrder(comptime T: type, root: ?*inc.TreeNode(T)) !void { if (root == null) return; - // 访问优先级:左子树 -> 右子树 -> 根结点 + // 访问优先级:左子树 -> 右子树 -> 根节点 try postOrder(T, root.?.left); try postOrder(T, root.?.right); try list.append(root.?.val); @@ -51,19 +51,19 @@ pub fn main() !void { // 前序遍历 list.clearRetainingCapacity(); try preOrder(i32, root); - std.debug.print("\n前序遍历的结点打印序列 = ", .{}); + std.debug.print("\n前序遍历的节点打印序列 = ", .{}); inc.PrintUtil.printList(i32, list); // 中序遍历 list.clearRetainingCapacity(); try inOrder(i32, root); - std.debug.print("\n中序遍历的结点打印序列 = ", .{}); + std.debug.print("\n中序遍历的节点打印序列 = ", .{}); inc.PrintUtil.printList(i32, list); // 后序遍历 list.clearRetainingCapacity(); try postOrder(i32, root); - std.debug.print("\n后续遍历的结点打印序列 = ", .{}); + std.debug.print("\n后续遍历的节点打印序列 = ", .{}); inc.PrintUtil.printList(i32, list); _ = try std.io.getStdIn().reader().readByte(); diff --git a/codes/zig/include/TreeNode.zig b/codes/zig/include/TreeNode.zig index fc31ec36..2ed58291 100644 --- a/codes/zig/include/TreeNode.zig +++ b/codes/zig/include/TreeNode.zig @@ -9,10 +9,10 @@ pub fn TreeNode(comptime T: type) type { return struct { const Self = @This(); - val: T = undefined, // 结点值 - height: i32 = undefined, // 结点高度 - left: ?*Self = null, // 左子结点指针 - right: ?*Self = null, // 右子结点指针 + val: T = undefined, // 节点值 + height: i32 = undefined, // 节点高度 + left: ?*Self = null, // 左子节点指针 + right: ?*Self = null, // 右子节点指针 // Initialize a tree node with specific value pub fn init(self: *Self, x: i32) void { diff --git a/docs/chapter_appendix/contribution.assets/edit_markdown.png b/docs/chapter_appendix/contribution.assets/edit_markdown.png index 032e5d10..f2becc22 100644 Binary files a/docs/chapter_appendix/contribution.assets/edit_markdown.png and b/docs/chapter_appendix/contribution.assets/edit_markdown.png differ diff --git a/docs/chapter_array_and_linkedlist/array.assets/array_definition.png b/docs/chapter_array_and_linkedlist/array.assets/array_definition.png index 240cbac8..4a1c32c2 100644 Binary files a/docs/chapter_array_and_linkedlist/array.assets/array_definition.png and b/docs/chapter_array_and_linkedlist/array.assets/array_definition.png differ diff --git a/docs/chapter_array_and_linkedlist/array.assets/array_insert_element.png b/docs/chapter_array_and_linkedlist/array.assets/array_insert_element.png index b286f05a..77e0eaf4 100644 Binary files a/docs/chapter_array_and_linkedlist/array.assets/array_insert_element.png and b/docs/chapter_array_and_linkedlist/array.assets/array_insert_element.png differ diff --git a/docs/chapter_array_and_linkedlist/array.assets/array_memory_location_calculation.png b/docs/chapter_array_and_linkedlist/array.assets/array_memory_location_calculation.png index 7514ee18..3f848d83 100644 Binary files a/docs/chapter_array_and_linkedlist/array.assets/array_memory_location_calculation.png and b/docs/chapter_array_and_linkedlist/array.assets/array_memory_location_calculation.png differ diff --git a/docs/chapter_array_and_linkedlist/array.assets/array_remove_element.png b/docs/chapter_array_and_linkedlist/array.assets/array_remove_element.png index e2e9210c..516d5853 100644 Binary files a/docs/chapter_array_and_linkedlist/array.assets/array_remove_element.png and b/docs/chapter_array_and_linkedlist/array.assets/array_remove_element.png differ diff --git a/docs/chapter_array_and_linkedlist/linked_list.assets/linkedlist_common_types.png b/docs/chapter_array_and_linkedlist/linked_list.assets/linkedlist_common_types.png index 77320552..df5d0842 100644 Binary files a/docs/chapter_array_and_linkedlist/linked_list.assets/linkedlist_common_types.png and b/docs/chapter_array_and_linkedlist/linked_list.assets/linkedlist_common_types.png differ diff --git a/docs/chapter_array_and_linkedlist/linked_list.assets/linkedlist_definition.png b/docs/chapter_array_and_linkedlist/linked_list.assets/linkedlist_definition.png index 0a37934b..ea7d12cf 100644 Binary files a/docs/chapter_array_and_linkedlist/linked_list.assets/linkedlist_definition.png and b/docs/chapter_array_and_linkedlist/linked_list.assets/linkedlist_definition.png differ diff --git a/docs/chapter_array_and_linkedlist/linked_list.assets/linkedlist_insert_node.png b/docs/chapter_array_and_linkedlist/linked_list.assets/linkedlist_insert_node.png index 25758896..be04c698 100644 Binary files a/docs/chapter_array_and_linkedlist/linked_list.assets/linkedlist_insert_node.png and b/docs/chapter_array_and_linkedlist/linked_list.assets/linkedlist_insert_node.png differ diff --git a/docs/chapter_array_and_linkedlist/linked_list.assets/linkedlist_remove_node.png b/docs/chapter_array_and_linkedlist/linked_list.assets/linkedlist_remove_node.png index 542ea8d7..f1383a00 100644 Binary files a/docs/chapter_array_and_linkedlist/linked_list.assets/linkedlist_remove_node.png and b/docs/chapter_array_and_linkedlist/linked_list.assets/linkedlist_remove_node.png differ diff --git a/docs/chapter_array_and_linkedlist/linked_list.md b/docs/chapter_array_and_linkedlist/linked_list.md index d0867097..8e6b9f47 100755 --- a/docs/chapter_array_and_linkedlist/linked_list.md +++ b/docs/chapter_array_and_linkedlist/linked_list.md @@ -2,19 +2,19 @@ 内存空间是所有程序的公共资源,排除已被占用的内存空间,空闲内存空间通常散落在内存各处。在上一节中,我们提到存储数组的内存空间必须是连续的,而当我们需要申请一个非常大的数组时,空闲内存中可能没有这么大的连续空间。 -与数组相比,链表更具灵活性,因为它可以存储在非连续的内存空间。「链表 Linked List」是一种线性数据结构,其每个元素都是一个结点对象,各个结点之间通过指针连接,从当前结点通过指针可以访问到下一个结点。由于指针记录了下个结点的内存地址,因此无需保证内存地址的连续性,从而可以将各个结点分散存储在内存各处。 +与数组相比,链表更具灵活性,因为它可以存储在非连续的内存空间。「链表 Linked List」是一种线性数据结构,其每个元素都是一个节点对象,各个节点之间通过指针连接,从当前节点通过指针可以访问到下一个节点。由于指针记录了下个节点的内存地址,因此无需保证内存地址的连续性,从而可以将各个节点分散存储在内存各处。 -链表「结点 Node」包含两项数据,一是结点「值 Value」,二是指向下一结点的「指针 Pointer」,或称指向下一结点的「引用 Reference」。 +链表「节点 Node」包含两项数据,一是节点「值 Value」,二是指向下一节点的「指针 Pointer」,或称指向下一节点的「引用 Reference」。 ![链表定义与存储方式](linked_list.assets/linkedlist_definition.png) === "Java" ```java title="" - /* 链表结点类 */ + /* 链表节点类 */ class ListNode { - int val; // 结点值 - ListNode next; // 指向下一结点的指针(引用) + int val; // 节点值 + ListNode next; // 指向下一节点的指针(引用) ListNode(int x) { val = x; } // 构造函数 } ``` @@ -22,10 +22,10 @@ === "C++" ```cpp title="" - /* 链表结点结构体 */ + /* 链表节点结构体 */ struct ListNode { - int val; // 结点值 - ListNode *next; // 指向下一结点的指针(引用) + int val; // 节点值 + ListNode *next; // 指向下一节点的指针(引用) ListNode(int x) : val(x), next(nullptr) {} // 构造函数 }; ``` @@ -33,20 +33,20 @@ === "Python" ```python title="" - """ 链表结点类 """ + """ 链表节点类 """ class ListNode: def __init__(self, val: int): - self.val: int = val # 结点值 - self.next: Optional[ListNode] = None # 指向下一结点的指针(引用) + self.val: int = val # 节点值 + self.next: Optional[ListNode] = None # 指向下一节点的指针(引用) ``` === "Go" ```go title="" - /* 链表结点结构体 */ + /* 链表节点结构体 */ type ListNode struct { - Val int // 结点值 - Next *ListNode // 指向下一结点的指针(引用) + Val int // 节点值 + Next *ListNode // 指向下一节点的指针(引用) } // NewListNode 构造函数,创建一个新的链表 @@ -61,13 +61,13 @@ === "JavaScript" ```javascript title="" - /* 链表结点类 */ + /* 链表节点类 */ class ListNode { val; next; constructor(val, next) { - this.val = (val === undefined ? 0 : val); // 结点值 - this.next = (next === undefined ? null : next); // 指向下一结点的引用 + this.val = (val === undefined ? 0 : val); // 节点值 + this.next = (next === undefined ? null : next); // 指向下一节点的引用 } } ``` @@ -75,13 +75,13 @@ === "TypeScript" ```typescript title="" - /* 链表结点类 */ + /* 链表节点类 */ class ListNode { val: number; next: ListNode | null; constructor(val?: number, next?: ListNode | null) { - this.val = val === undefined ? 0 : val; // 结点值 - this.next = next === undefined ? null : next; // 指向下一结点的引用 + this.val = val === undefined ? 0 : val; // 节点值 + this.next = next === undefined ? null : next; // 指向下一节点的引用 } } ``` @@ -89,16 +89,16 @@ === "C" ```c title="" - /* 链表结点结构体 */ + /* 链表节点结构体 */ struct ListNode { - int val; // 结点值 - struct ListNode *next; // 指向下一结点的指针(引用) + int val; // 节点值 + struct ListNode *next; // 指向下一节点的指针(引用) }; // typedef 作用是为一种数据类型定义一个新名字 typedef struct ListNode ListNode; - /* 构造函数,初始化一个新结点 */ + /* 构造函数,初始化一个新节点 */ ListNode *newListNode(int val) { ListNode *node, *next; node = (ListNode *) malloc(sizeof(ListNode)); @@ -111,11 +111,11 @@ === "C#" ```csharp title="" - /* 链表结点类 */ + /* 链表节点类 */ class ListNode { - int val; // 结点值 - ListNode next; // 指向下一结点的引用 + int val; // 节点值 + ListNode next; // 指向下一节点的引用 ListNode(int x) => val = x; //构造函数 } ``` @@ -123,10 +123,10 @@ === "Swift" ```swift title="" - /* 链表结点类 */ + /* 链表节点类 */ class ListNode { - var val: Int // 结点值 - var next: ListNode? // 指向下一结点的指针(引用) + var val: Int // 节点值 + var next: ListNode? // 指向下一节点的指针(引用) init(x: Int) { // 构造函数 val = x @@ -137,13 +137,13 @@ === "Zig" ```zig title="" - // 链表结点类 + // 链表节点类 pub fn ListNode(comptime T: type) type { return struct { const Self = @This(); - val: T = 0, // 结点值 - next: ?*Self = null, // 指向下一结点的指针(引用) + val: T = 0, // 节点值 + next: ?*Self = null, // 指向下一节点的指针(引用) // 构造函数 pub fn init(self: *Self, x: i32) void { @@ -154,21 +154,21 @@ } ``` -!!! question "尾结点指向什么?" +!!! question "尾节点指向什么?" - 我们将链表的最后一个结点称为「尾结点」,其指向的是“空”,在 Java, C++, Python 中分别记为 `null`, `nullptr`, `None` 。在不引起歧义的前提下,本书都使用 `null` 来表示空。 + 我们将链表的最后一个节点称为「尾节点」,其指向的是“空”,在 Java, C++, Python 中分别记为 `null`, `nullptr`, `None` 。在不引起歧义的前提下,本书都使用 `null` 来表示空。 !!! question "如何称呼链表?" - 在编程语言中,数组整体就是一个变量,例如数组 `nums` ,包含各个元素 `nums[0]` , `nums[1]` 等等。而链表是由多个结点对象组成,我们通常将头结点当作链表的代称,例如头结点 `head` 和链表 `head` 实际上是同义的。 + 在编程语言中,数组整体就是一个变量,例如数组 `nums` ,包含各个元素 `nums[0]` , `nums[1]` 等等。而链表是由多个节点对象组成,我们通常将头节点当作链表的代称,例如头节点 `head` 和链表 `head` 实际上是同义的。 -**链表初始化方法**。建立链表分为两步,第一步是初始化各个结点对象,第二步是构建引用指向关系。完成后,即可以从链表的头结点(即首个结点)出发,通过指针 `next` 依次访问所有结点。 +**链表初始化方法**。建立链表分为两步,第一步是初始化各个节点对象,第二步是构建引用指向关系。完成后,即可以从链表的头节点(即首个节点)出发,通过指针 `next` 依次访问所有节点。 === "Java" ```java title="linked_list.java" /* 初始化链表 1 -> 3 -> 2 -> 5 -> 4 */ - // 初始化各个结点 + // 初始化各个节点 ListNode n0 = new ListNode(1); ListNode n1 = new ListNode(3); ListNode n2 = new ListNode(2); @@ -185,7 +185,7 @@ ```cpp title="linked_list.cpp" /* 初始化链表 1 -> 3 -> 2 -> 5 -> 4 */ - // 初始化各个结点 + // 初始化各个节点 ListNode* n0 = new ListNode(1); ListNode* n1 = new ListNode(3); ListNode* n2 = new ListNode(2); @@ -202,7 +202,7 @@ ```python title="linked_list.py" """ 初始化链表 1 -> 3 -> 2 -> 5 -> 4 """ - # 初始化各个结点 + # 初始化各个节点 n0 = ListNode(1) n1 = ListNode(3) n2 = ListNode(2) @@ -219,7 +219,7 @@ ```go title="linked_list.go" /* 初始化链表 1 -> 3 -> 2 -> 5 -> 4 */ - // 初始化各个结点 + // 初始化各个节点 n0 := NewListNode(1) n1 := NewListNode(3) n2 := NewListNode(2) @@ -236,7 +236,7 @@ ```javascript title="linked_list.js" /* 初始化链表 1 -> 3 -> 2 -> 5 -> 4 */ - // 初始化各个结点 + // 初始化各个节点 const n0 = new ListNode(1); const n1 = new ListNode(3); const n2 = new ListNode(2); @@ -253,7 +253,7 @@ ```typescript title="linked_list.ts" /* 初始化链表 1 -> 3 -> 2 -> 5 -> 4 */ - // 初始化各个结点 + // 初始化各个节点 const n0 = new ListNode(1); const n1 = new ListNode(3); const n2 = new ListNode(2); @@ -270,7 +270,7 @@ ```c title="linked_list.c" /* 初始化链表 1 -> 3 -> 2 -> 5 -> 4 */ - // 初始化各个结点 + // 初始化各个节点 ListNode* n0 = newListNode(1); ListNode* n1 = newListNode(3); ListNode* n2 = newListNode(2); @@ -287,7 +287,7 @@ ```csharp title="linked_list.cs" /* 初始化链表 1 -> 3 -> 2 -> 5 -> 4 */ - // 初始化各个结点 + // 初始化各个节点 ListNode n0 = new ListNode(1); ListNode n1 = new ListNode(3); ListNode n2 = new ListNode(2); @@ -304,7 +304,7 @@ ```swift title="linked_list.swift" /* 初始化链表 1 -> 3 -> 2 -> 5 -> 4 */ - // 初始化各个结点 + // 初始化各个节点 let n0 = ListNode(x: 1) let n1 = ListNode(x: 3) let n2 = ListNode(x: 2) @@ -321,7 +321,7 @@ ```zig title="linked_list.zig" // 初始化链表 - // 初始化各个结点 + // 初始化各个节点 var n0 = inc.ListNode(i32){.val = 1}; var n1 = inc.ListNode(i32){.val = 3}; var n2 = inc.ListNode(i32){.val = 2}; @@ -336,9 +336,9 @@ ## 链表优点 -**链表中插入与删除结点的操作效率高**。例如,如果我们想在链表中间的两个结点 `A` , `B` 之间插入一个新结点 `P` ,我们只需要改变两个结点指针即可,时间复杂度为 $O(1)$ ;相比之下,数组的插入操作效率要低得多。 +**链表中插入与删除节点的操作效率高**。例如,如果我们想在链表中间的两个节点 `A` , `B` 之间插入一个新节点 `P` ,我们只需要改变两个节点指针即可,时间复杂度为 $O(1)$ ;相比之下,数组的插入操作效率要低得多。 -![链表插入结点](linked_list.assets/linkedlist_insert_node.png) +![链表插入节点](linked_list.assets/linkedlist_insert_node.png) === "Java" @@ -400,9 +400,9 @@ [class]{}-[func]{insert} ``` -在链表中删除结点也非常方便,只需改变一个结点的指针即可。如下图所示,尽管在删除操作完成后,结点 `P` 仍然指向 `n1`,但实际上 `P` 已经不再属于此链表,因为遍历此链表时无法访问到 `P`。 +在链表中删除节点也非常方便,只需改变一个节点的指针即可。如下图所示,尽管在删除操作完成后,节点 `P` 仍然指向 `n1`,但实际上 `P` 已经不再属于此链表,因为遍历此链表时无法访问到 `P`。 -![链表删除结点](linked_list.assets/linkedlist_remove_node.png) +![链表删除节点](linked_list.assets/linkedlist_remove_node.png) === "Java" @@ -466,7 +466,7 @@ ## 链表缺点 -**链表访问结点效率较低**。如上节所述,数组可以在 $O(1)$ 时间下访问任意元素。然而,链表无法直接访问任意结点,这是因为系统需要从头结点出发,逐个向后遍历直至找到目标结点。例如,若要访问链表索引为 `index`(即第 `index + 1` 个)的结点,则需要向后遍历 `index` 轮。 +**链表访问节点效率较低**。如上节所述,数组可以在 $O(1)$ 时间下访问任意元素。然而,链表无法直接访问任意节点,这是因为系统需要从头节点出发,逐个向后遍历直至找到目标节点。例如,若要访问链表索引为 `index`(即第 `index + 1` 个)的节点,则需要向后遍历 `index` 轮。 === "Java" @@ -528,11 +528,11 @@ [class]{}-[func]{access} ``` -**链表的内存占用较大**。链表以结点为单位,每个结点除了保存值之外,还需额外保存指针(引用)。这意味着在相同数据量的情况下,链表比数组需要占用更多的内存空间。 +**链表的内存占用较大**。链表以节点为单位,每个节点除了保存值之外,还需额外保存指针(引用)。这意味着在相同数据量的情况下,链表比数组需要占用更多的内存空间。 ## 链表常用操作 -**遍历链表查找**。遍历链表,查找链表内值为 `target` 的结点,输出结点在链表中的索引。 +**遍历链表查找**。遍历链表,查找链表内值为 `target` 的节点,输出节点在链表中的索引。 === "Java" @@ -596,20 +596,20 @@ ## 常见链表类型 -**单向链表**。即上述介绍的普通链表。单向链表的结点包含值和指向下一结点的指针(引用)两项数据。我们将首个结点称为头结点,将最后一个结点成为尾结点,尾结点指向 `null` 。 +**单向链表**。即上述介绍的普通链表。单向链表的节点包含值和指向下一节点的指针(引用)两项数据。我们将首个节点称为头节点,将最后一个节点成为尾节点,尾节点指向 `null` 。 -**环形链表**。如果我们令单向链表的尾结点指向头结点(即首尾相接),则得到一个环形链表。在环形链表中,任意结点都可以视作头结点。 +**环形链表**。如果我们令单向链表的尾节点指向头节点(即首尾相接),则得到一个环形链表。在环形链表中,任意节点都可以视作头节点。 -**双向链表**。与单向链表相比,双向链表记录了两个方向的指针(引用)。双向链表的结点定义同时包含指向后继结点(下一结点)和前驱结点(上一结点)的指针。相较于单向链表,双向链表更具灵活性,可以朝两个方向遍历链表,但相应地也需要占用更多的内存空间。 +**双向链表**。与单向链表相比,双向链表记录了两个方向的指针(引用)。双向链表的节点定义同时包含指向后继节点(下一节点)和前驱节点(上一节点)的指针。相较于单向链表,双向链表更具灵活性,可以朝两个方向遍历链表,但相应地也需要占用更多的内存空间。 === "Java" ```java title="" - /* 双向链表结点类 */ + /* 双向链表节点类 */ class ListNode { - int val; // 结点值 - ListNode next; // 指向后继结点的指针(引用) - ListNode prev; // 指向前驱结点的指针(引用) + int val; // 节点值 + ListNode next; // 指向后继节点的指针(引用) + ListNode prev; // 指向前驱节点的指针(引用) ListNode(int x) { val = x; } // 构造函数 } ``` @@ -617,11 +617,11 @@ === "C++" ```cpp title="" - /* 双向链表结点结构体 */ + /* 双向链表节点结构体 */ struct ListNode { - int val; // 结点值 - ListNode *next; // 指向后继结点的指针(引用) - ListNode *prev; // 指向前驱结点的指针(引用) + int val; // 节点值 + ListNode *next; // 指向后继节点的指针(引用) + ListNode *prev; // 指向前驱节点的指针(引用) ListNode(int x) : val(x), next(nullptr), prev(nullptr) {} // 构造函数 }; ``` @@ -629,22 +629,22 @@ === "Python" ```python title="" - """ 双向链表结点类 """ + """ 双向链表节点类 """ class ListNode: def __init__(self, val: int): - self.val: int = val # 结点值 - self.next: Optional[ListNode] = None # 指向后继结点的指针(引用) - self.prev: Optional[ListNode] = None # 指向前驱结点的指针(引用) + self.val: int = val # 节点值 + self.next: Optional[ListNode] = None # 指向后继节点的指针(引用) + self.prev: Optional[ListNode] = None # 指向前驱节点的指针(引用) ``` === "Go" ```go title="" - /* 双向链表结点结构体 */ + /* 双向链表节点结构体 */ type DoublyListNode struct { - Val int // 结点值 - Next *DoublyListNode // 指向后继结点的指针(引用) - Prev *DoublyListNode // 指向前驱结点的指针(引用) + Val int // 节点值 + Next *DoublyListNode // 指向后继节点的指针(引用) + Prev *DoublyListNode // 指向前驱节点的指针(引用) } // NewDoublyListNode 初始化 @@ -660,15 +660,15 @@ === "JavaScript" ```javascript title="" - /* 双向链表结点类 */ + /* 双向链表节点类 */ class ListNode { val; next; prev; constructor(val, next) { - this.val = val === undefined ? 0 : val; // 结点值 - this.next = next === undefined ? null : next; // 指向后继结点的指针(引用) - this.prev = prev === undefined ? null : prev; // 指向前驱结点的指针(引用) + this.val = val === undefined ? 0 : val; // 节点值 + this.next = next === undefined ? null : next; // 指向后继节点的指针(引用) + this.prev = prev === undefined ? null : prev; // 指向前驱节点的指针(引用) } } ``` @@ -676,15 +676,15 @@ === "TypeScript" ```typescript title="" - /* 双向链表结点类 */ + /* 双向链表节点类 */ class ListNode { val: number; next: ListNode | null; prev: ListNode | null; constructor(val?: number, next?: ListNode | null, prev?: ListNode | null) { - this.val = val === undefined ? 0 : val; // 结点值 - this.next = next === undefined ? null : next; // 指向后继结点的指针(引用) - this.prev = prev === undefined ? null : prev; // 指向前驱结点的指针(引用) + this.val = val === undefined ? 0 : val; // 节点值 + this.next = next === undefined ? null : next; // 指向后继节点的指针(引用) + this.prev = prev === undefined ? null : prev; // 指向前驱节点的指针(引用) } } ``` @@ -698,11 +698,11 @@ === "C#" ```csharp title="" - /* 双向链表结点类 */ + /* 双向链表节点类 */ class ListNode { - int val; // 结点值 - ListNode next; // 指向后继结点的指针(引用) - ListNode prev; // 指向前驱结点的指针(引用) + int val; // 节点值 + ListNode next; // 指向后继节点的指针(引用) + ListNode prev; // 指向前驱节点的指针(引用) ListNode(int x) => val = x; // 构造函数 } ``` @@ -710,11 +710,11 @@ === "Swift" ```swift title="" - /* 双向链表结点类 */ + /* 双向链表节点类 */ class ListNode { - var val: Int // 结点值 - var next: ListNode? // 指向后继结点的指针(引用) - var prev: ListNode? // 指向前驱结点的指针(引用) + var val: Int // 节点值 + var next: ListNode? // 指向后继节点的指针(引用) + var prev: ListNode? // 指向前驱节点的指针(引用) init(x: Int) { // 构造函数 val = x @@ -725,14 +725,14 @@ === "Zig" ```zig title="" - // 双向链表结点类 + // 双向链表节点类 pub fn ListNode(comptime T: type) type { return struct { const Self = @This(); - val: T = 0, // 结点值 - next: ?*Self = null, // 指向后继结点的指针(引用) - prev: ?*Self = null, // 指向前驱结点的指针(引用) + val: T = 0, // 节点值 + next: ?*Self = null, // 指向后继节点的指针(引用) + prev: ?*Self = null, // 指向前驱节点的指针(引用) // 构造函数 pub fn init(self: *Self, x: i32) void { diff --git a/docs/chapter_array_and_linkedlist/summary.md b/docs/chapter_array_and_linkedlist/summary.md index 996e5308..b7497a4c 100644 --- a/docs/chapter_array_and_linkedlist/summary.md +++ b/docs/chapter_array_and_linkedlist/summary.md @@ -2,7 +2,7 @@ - 数组和链表是两种基本数据结构,分别代表数据在计算机内存中的连续空间存储和离散空间存储方式。两者的优缺点呈现出互补的特性。 - 数组支持随机访问、占用内存较少;但插入和删除元素效率低,且初始化后长度不可变。 -- 链表通过更改指针实现高效的结点插入与删除,且可以灵活调整长度;但结点访问效率低、占用内存较多。常见的链表类型包括单向链表、循环链表、双向链表。 +- 链表通过更改指针实现高效的节点插入与删除,且可以灵活调整长度;但节点访问效率低、占用内存较多。常见的链表类型包括单向链表、循环链表、双向链表。 - 动态数组,又称列表,是基于数组实现的一种数据结构。它保留了数组的优势,同时可以灵活调整长度。列表的出现极大地提高了数组的易用性,但可能导致部分内存空间浪费。 - 下表总结并对比了数组与链表的各项特性。 @@ -19,7 +19,7 @@ !!! note "缓存局部性" - 在计算机中,数据读写速度排序是“硬盘 < 内存 < CPU 缓存”。当我们访问数组元素时,计算机不仅会加载它,还会缓存其周围的其它数据,从而借助高速缓存来提升后续操作的执行速度。链表则不然,计算机只能挨个地缓存各个结点,这样的多次“搬运”降低了整体效率。 + 在计算机中,数据读写速度排序是“硬盘 < 内存 < CPU 缓存”。当我们访问数组元素时,计算机不仅会加载它,还会缓存其周围的其它数据,从而借助高速缓存来提升后续操作的执行速度。链表则不然,计算机只能挨个地缓存各个节点,这样的多次“搬运”降低了整体效率。 - 下表对比了数组与链表在各种操作上的效率。 diff --git a/docs/chapter_computational_complexity/space_complexity.assets/space_complexity_common_types.png b/docs/chapter_computational_complexity/space_complexity.assets/space_complexity_common_types.png index e07f6e3a..ffc63eb3 100644 Binary files a/docs/chapter_computational_complexity/space_complexity.assets/space_complexity_common_types.png and b/docs/chapter_computational_complexity/space_complexity.assets/space_complexity_common_types.png differ diff --git a/docs/chapter_computational_complexity/space_complexity.assets/space_complexity_exponential.png b/docs/chapter_computational_complexity/space_complexity.assets/space_complexity_exponential.png index 5074542c..4756e3b5 100644 Binary files a/docs/chapter_computational_complexity/space_complexity.assets/space_complexity_exponential.png and b/docs/chapter_computational_complexity/space_complexity.assets/space_complexity_exponential.png differ diff --git a/docs/chapter_computational_complexity/space_complexity.assets/space_complexity_recursive_linear.png b/docs/chapter_computational_complexity/space_complexity.assets/space_complexity_recursive_linear.png index 7f7c7e1a..ce14ea29 100644 Binary files a/docs/chapter_computational_complexity/space_complexity.assets/space_complexity_recursive_linear.png and b/docs/chapter_computational_complexity/space_complexity.assets/space_complexity_recursive_linear.png differ diff --git a/docs/chapter_computational_complexity/space_complexity.assets/space_complexity_recursive_quadratic.png b/docs/chapter_computational_complexity/space_complexity.assets/space_complexity_recursive_quadratic.png index c454404c..6ec49979 100644 Binary files a/docs/chapter_computational_complexity/space_complexity.assets/space_complexity_recursive_quadratic.png and b/docs/chapter_computational_complexity/space_complexity.assets/space_complexity_recursive_quadratic.png differ diff --git a/docs/chapter_computational_complexity/space_complexity.assets/space_types.png b/docs/chapter_computational_complexity/space_complexity.assets/space_types.png index 1fd77a72..2aa3d377 100644 Binary files a/docs/chapter_computational_complexity/space_complexity.assets/space_types.png and b/docs/chapter_computational_complexity/space_complexity.assets/space_types.png differ diff --git a/docs/chapter_computational_complexity/space_complexity.md b/docs/chapter_computational_complexity/space_complexity.md index ee6d2cea..71486dd0 100755 --- a/docs/chapter_computational_complexity/space_complexity.md +++ b/docs/chapter_computational_complexity/space_complexity.md @@ -78,8 +78,8 @@ """ 类 """ class Node: def __init__(self, x: int): - self.val: int = x # 结点值 - self.next: Optional[Node] = None # 指向下一结点的指针(引用) + self.val: int = x # 节点值 + self.next: Optional[Node] = None # 指向下一节点的指针(引用) """ 函数 """ def function() -> int: @@ -131,8 +131,8 @@ val; next; constructor(val) { - this.val = val === undefined ? 0 : val; // 结点值 - this.next = null; // 指向下一结点的引用 + this.val = val === undefined ? 0 : val; // 节点值 + this.next = null; // 指向下一节点的引用 } } @@ -159,8 +159,8 @@ val: number; next: Node | null; constructor(val?: number) { - this.val = val === undefined ? 0 : val; // 结点值 - this.next = null; // 指向下一结点的引用 + this.val = val === undefined ? 0 : val; // 节点值 + this.next = null; // 指向下一节点的引用 } } @@ -890,7 +890,7 @@ $$ ### 指数阶 $O(2^n)$ -指数阶常见于二叉树。高度为 $n$ 的「满二叉树」的结点数量为 $2^n - 1$ ,占用 $O(2^n)$ 空间。 +指数阶常见于二叉树。高度为 $n$ 的「满二叉树」的节点数量为 $2^n - 1$ ,占用 $O(2^n)$ 空间。 === "Java" diff --git a/docs/chapter_computational_complexity/time_complexity.assets/asymptotic_upper_bound.png b/docs/chapter_computational_complexity/time_complexity.assets/asymptotic_upper_bound.png index 9d426349..91494fdb 100644 Binary files a/docs/chapter_computational_complexity/time_complexity.assets/asymptotic_upper_bound.png and b/docs/chapter_computational_complexity/time_complexity.assets/asymptotic_upper_bound.png differ diff --git a/docs/chapter_computational_complexity/time_complexity.assets/time_complexity_common_types.png b/docs/chapter_computational_complexity/time_complexity.assets/time_complexity_common_types.png index 31ce85a2..0494758d 100644 Binary files a/docs/chapter_computational_complexity/time_complexity.assets/time_complexity_common_types.png and b/docs/chapter_computational_complexity/time_complexity.assets/time_complexity_common_types.png differ diff --git a/docs/chapter_computational_complexity/time_complexity.assets/time_complexity_constant_linear_quadratic.png b/docs/chapter_computational_complexity/time_complexity.assets/time_complexity_constant_linear_quadratic.png index 2532ffa4..ffca66e0 100644 Binary files a/docs/chapter_computational_complexity/time_complexity.assets/time_complexity_constant_linear_quadratic.png and b/docs/chapter_computational_complexity/time_complexity.assets/time_complexity_constant_linear_quadratic.png differ diff --git a/docs/chapter_computational_complexity/time_complexity.assets/time_complexity_exponential.png b/docs/chapter_computational_complexity/time_complexity.assets/time_complexity_exponential.png index f4f96376..15bfdfa7 100644 Binary files a/docs/chapter_computational_complexity/time_complexity.assets/time_complexity_exponential.png and b/docs/chapter_computational_complexity/time_complexity.assets/time_complexity_exponential.png differ diff --git a/docs/chapter_computational_complexity/time_complexity.assets/time_complexity_factorial.png b/docs/chapter_computational_complexity/time_complexity.assets/time_complexity_factorial.png index 48834467..92221db1 100644 Binary files a/docs/chapter_computational_complexity/time_complexity.assets/time_complexity_factorial.png and b/docs/chapter_computational_complexity/time_complexity.assets/time_complexity_factorial.png differ diff --git a/docs/chapter_computational_complexity/time_complexity.assets/time_complexity_logarithmic.png b/docs/chapter_computational_complexity/time_complexity.assets/time_complexity_logarithmic.png index c3343abd..f93a42f2 100644 Binary files a/docs/chapter_computational_complexity/time_complexity.assets/time_complexity_logarithmic.png and b/docs/chapter_computational_complexity/time_complexity.assets/time_complexity_logarithmic.png differ diff --git a/docs/chapter_computational_complexity/time_complexity.assets/time_complexity_logarithmic_linear.png b/docs/chapter_computational_complexity/time_complexity.assets/time_complexity_logarithmic_linear.png index b7552b52..e60dfaf3 100644 Binary files a/docs/chapter_computational_complexity/time_complexity.assets/time_complexity_logarithmic_linear.png and b/docs/chapter_computational_complexity/time_complexity.assets/time_complexity_logarithmic_linear.png differ diff --git a/docs/chapter_computational_complexity/time_complexity.assets/time_complexity_simple_example.png b/docs/chapter_computational_complexity/time_complexity.assets/time_complexity_simple_example.png index 622c76f1..45989dbb 100644 Binary files a/docs/chapter_computational_complexity/time_complexity.assets/time_complexity_simple_example.png and b/docs/chapter_computational_complexity/time_complexity.assets/time_complexity_simple_example.png differ diff --git a/docs/chapter_data_structure/classification_of_data_structure.assets/classification_logic_structure.png b/docs/chapter_data_structure/classification_of_data_structure.assets/classification_logic_structure.png index 192c855a..7066b7e4 100644 Binary files a/docs/chapter_data_structure/classification_of_data_structure.assets/classification_logic_structure.png and b/docs/chapter_data_structure/classification_of_data_structure.assets/classification_logic_structure.png differ diff --git a/docs/chapter_data_structure/classification_of_data_structure.assets/classification_phisical_structure.png b/docs/chapter_data_structure/classification_of_data_structure.assets/classification_phisical_structure.png index be69670c..574cc391 100644 Binary files a/docs/chapter_data_structure/classification_of_data_structure.assets/classification_phisical_structure.png and b/docs/chapter_data_structure/classification_of_data_structure.assets/classification_phisical_structure.png differ diff --git a/docs/chapter_data_structure/classification_of_data_structure.md b/docs/chapter_data_structure/classification_of_data_structure.md index 06c16a64..079cde1f 100644 --- a/docs/chapter_data_structure/classification_of_data_structure.md +++ b/docs/chapter_data_structure/classification_of_data_structure.md @@ -4,7 +4,7 @@ ## 逻辑结构:线性与非线性 -**「逻辑结构」揭示了数据元素之间的逻辑关系**。在数组和链表中,数据按照顺序依次排列,体现了数据之间的线性关系;而在树中,数据从顶部向下按层次排列,表现出祖先与后代之间的派生关系;图则由结点和边构成,反映了复杂的网络关系。 +**「逻辑结构」揭示了数据元素之间的逻辑关系**。在数组和链表中,数据按照顺序依次排列,体现了数据之间的线性关系;而在树中,数据从顶部向下按层次排列,表现出祖先与后代之间的派生关系;图则由节点和边构成,反映了复杂的网络关系。 逻辑结构通常分为「线性」和「非线性」两类。线性结构比较直观,指数据在逻辑关系上呈线性排列;非线性结构则相反,呈非线性排列,例如网状或树状结构。 diff --git a/docs/chapter_data_structure/data_and_memory.assets/computer_memory_location.png b/docs/chapter_data_structure/data_and_memory.assets/computer_memory_location.png index fb82a459..d0d6997d 100644 Binary files a/docs/chapter_data_structure/data_and_memory.assets/computer_memory_location.png and b/docs/chapter_data_structure/data_and_memory.assets/computer_memory_location.png differ diff --git a/docs/chapter_data_structure/data_and_memory.assets/ieee_754_float.png b/docs/chapter_data_structure/data_and_memory.assets/ieee_754_float.png index 27b49d0a..897c8b7e 100644 Binary files a/docs/chapter_data_structure/data_and_memory.assets/ieee_754_float.png and b/docs/chapter_data_structure/data_and_memory.assets/ieee_754_float.png differ diff --git a/docs/chapter_graph/graph.assets/adjacency_list.png b/docs/chapter_graph/graph.assets/adjacency_list.png index 4cb3b7b3..b7d7767c 100644 Binary files a/docs/chapter_graph/graph.assets/adjacency_list.png and b/docs/chapter_graph/graph.assets/adjacency_list.png differ diff --git a/docs/chapter_graph/graph.assets/adjacency_matrix.png b/docs/chapter_graph/graph.assets/adjacency_matrix.png index 2c3ecdb8..880fd4c1 100644 Binary files a/docs/chapter_graph/graph.assets/adjacency_matrix.png and b/docs/chapter_graph/graph.assets/adjacency_matrix.png differ diff --git a/docs/chapter_graph/graph.assets/connected_graph.png b/docs/chapter_graph/graph.assets/connected_graph.png index e7e76530..5e9c10a3 100644 Binary files a/docs/chapter_graph/graph.assets/connected_graph.png and b/docs/chapter_graph/graph.assets/connected_graph.png differ diff --git a/docs/chapter_graph/graph.assets/directed_graph.png b/docs/chapter_graph/graph.assets/directed_graph.png index e3affc6f..632d837e 100644 Binary files a/docs/chapter_graph/graph.assets/directed_graph.png and b/docs/chapter_graph/graph.assets/directed_graph.png differ diff --git a/docs/chapter_graph/graph.assets/linkedlist_tree_graph.png b/docs/chapter_graph/graph.assets/linkedlist_tree_graph.png index 2cae356d..6f3653d6 100644 Binary files a/docs/chapter_graph/graph.assets/linkedlist_tree_graph.png and b/docs/chapter_graph/graph.assets/linkedlist_tree_graph.png differ diff --git a/docs/chapter_graph/graph.assets/weighted_graph.png b/docs/chapter_graph/graph.assets/weighted_graph.png index 97a9f8fd..0dc25661 100644 Binary files a/docs/chapter_graph/graph.assets/weighted_graph.png and b/docs/chapter_graph/graph.assets/weighted_graph.png differ diff --git a/docs/chapter_graph/graph.md b/docs/chapter_graph/graph.md index 1ba32b93..3cd0759f 100644 --- a/docs/chapter_graph/graph.md +++ b/docs/chapter_graph/graph.md @@ -12,7 +12,7 @@ $$ ![链表、树、图之间的关系](graph.assets/linkedlist_tree_graph.png) -那么,图与其他数据结构的关系是什么?如果我们把「顶点」看作结点,把「边」看作连接各个结点的指针,则可将「图」看作是一种从「链表」拓展而来的数据结构。**相较于线性关系(链表)和分治关系(树),网络关系(图)的自由度更高,从而更为复杂**。 +那么,图与其他数据结构的关系是什么?如果我们把「顶点」看作节点,把「边」看作连接各个节点的指针,则可将「图」看作是一种从「链表」拓展而来的数据结构。**相较于线性关系(链表)和分治关系(树),网络关系(图)的自由度更高,从而更为复杂**。 ## 图常见类型 @@ -62,7 +62,7 @@ $$ ### 邻接表 -「邻接表 Adjacency List」使用 $n$ 个链表来表示图,链表结点表示顶点。第 $i$ 条链表对应顶点 $i$ ,其中存储了该顶点的所有邻接顶点(即与该顶点相连的顶点)。 +「邻接表 Adjacency List」使用 $n$ 个链表来表示图,链表节点表示顶点。第 $i$ 条链表对应顶点 $i$ ,其中存储了该顶点的所有邻接顶点(即与该顶点相连的顶点)。 ![图的邻接表表示](graph.assets/adjacency_list.png) diff --git a/docs/chapter_graph/graph_operations.assets/adjacency_list_add_edge.png b/docs/chapter_graph/graph_operations.assets/adjacency_list_add_edge.png index d521d257..8eb8925e 100644 Binary files a/docs/chapter_graph/graph_operations.assets/adjacency_list_add_edge.png and b/docs/chapter_graph/graph_operations.assets/adjacency_list_add_edge.png differ diff --git a/docs/chapter_graph/graph_operations.assets/adjacency_list_add_vertex.png b/docs/chapter_graph/graph_operations.assets/adjacency_list_add_vertex.png index 1909e844..f9af5e56 100644 Binary files a/docs/chapter_graph/graph_operations.assets/adjacency_list_add_vertex.png and b/docs/chapter_graph/graph_operations.assets/adjacency_list_add_vertex.png differ diff --git a/docs/chapter_graph/graph_operations.assets/adjacency_list_initialization.png b/docs/chapter_graph/graph_operations.assets/adjacency_list_initialization.png index 7335a7c5..b9187885 100644 Binary files a/docs/chapter_graph/graph_operations.assets/adjacency_list_initialization.png and b/docs/chapter_graph/graph_operations.assets/adjacency_list_initialization.png differ diff --git a/docs/chapter_graph/graph_operations.assets/adjacency_list_remove_edge.png b/docs/chapter_graph/graph_operations.assets/adjacency_list_remove_edge.png index 2374cbbf..f2bd5690 100644 Binary files a/docs/chapter_graph/graph_operations.assets/adjacency_list_remove_edge.png and b/docs/chapter_graph/graph_operations.assets/adjacency_list_remove_edge.png differ diff --git a/docs/chapter_graph/graph_operations.assets/adjacency_list_remove_vertex.png b/docs/chapter_graph/graph_operations.assets/adjacency_list_remove_vertex.png index 7fb4627f..b6b9a38f 100644 Binary files a/docs/chapter_graph/graph_operations.assets/adjacency_list_remove_vertex.png and b/docs/chapter_graph/graph_operations.assets/adjacency_list_remove_vertex.png differ diff --git a/docs/chapter_graph/graph_operations.assets/adjacency_matrix_add_edge.png b/docs/chapter_graph/graph_operations.assets/adjacency_matrix_add_edge.png index a1745730..08cfbdd6 100644 Binary files a/docs/chapter_graph/graph_operations.assets/adjacency_matrix_add_edge.png and b/docs/chapter_graph/graph_operations.assets/adjacency_matrix_add_edge.png differ diff --git a/docs/chapter_graph/graph_operations.assets/adjacency_matrix_add_vertex.png b/docs/chapter_graph/graph_operations.assets/adjacency_matrix_add_vertex.png index 53c908e0..323e8af1 100644 Binary files a/docs/chapter_graph/graph_operations.assets/adjacency_matrix_add_vertex.png and b/docs/chapter_graph/graph_operations.assets/adjacency_matrix_add_vertex.png differ diff --git a/docs/chapter_graph/graph_operations.assets/adjacency_matrix_initialization.png b/docs/chapter_graph/graph_operations.assets/adjacency_matrix_initialization.png index c3466489..6734d00a 100644 Binary files a/docs/chapter_graph/graph_operations.assets/adjacency_matrix_initialization.png and b/docs/chapter_graph/graph_operations.assets/adjacency_matrix_initialization.png differ diff --git a/docs/chapter_graph/graph_operations.assets/adjacency_matrix_remove_edge.png b/docs/chapter_graph/graph_operations.assets/adjacency_matrix_remove_edge.png index cc0cd519..3da9fc10 100644 Binary files a/docs/chapter_graph/graph_operations.assets/adjacency_matrix_remove_edge.png and b/docs/chapter_graph/graph_operations.assets/adjacency_matrix_remove_edge.png differ diff --git a/docs/chapter_graph/graph_operations.assets/adjacency_matrix_remove_vertex.png b/docs/chapter_graph/graph_operations.assets/adjacency_matrix_remove_vertex.png index ca239cda..ea1b101e 100644 Binary files a/docs/chapter_graph/graph_operations.assets/adjacency_matrix_remove_vertex.png and b/docs/chapter_graph/graph_operations.assets/adjacency_matrix_remove_vertex.png differ diff --git a/docs/chapter_graph/graph_operations.md b/docs/chapter_graph/graph_operations.md index fe4a77be..8325486b 100644 --- a/docs/chapter_graph/graph_operations.md +++ b/docs/chapter_graph/graph_operations.md @@ -94,7 +94,7 @@ - **添加边**:在顶点对应链表的末尾添加边即可,使用 $O(1)$ 时间。因为是无向图,所以需要同时添加两个方向的边。 - **删除边**:在顶点对应链表中查找并删除指定边,使用 $O(m)$ 时间。在无向图中,需要同时删除两个方向的边。 -- **添加顶点**:在邻接表中添加一个链表,并将新增顶点作为链表头结点,使用 $O(1)$ 时间。 +- **添加顶点**:在邻接表中添加一个链表,并将新增顶点作为链表头节点,使用 $O(1)$ 时间。 - **删除顶点**:需遍历整个邻接表,删除包含指定顶点的所有边,使用 $O(1)$ 时间。 - **初始化**:在邻接表中创建 $n$ 个顶点和 $2m$ 条边,使用 $O(n + m)$ 时间。 @@ -113,7 +113,7 @@ === "删除顶点" ![adjacency_list_remove_vertex](graph_operations.assets/adjacency_list_remove_vertex.png) -以下是基于邻接表实现图的代码示例。细心的同学可能注意到,**我们在邻接表中使用 `Vertex` 结点类来表示顶点**,这样做的原因有: +以下是基于邻接表实现图的代码示例。细心的同学可能注意到,**我们在邻接表中使用 `Vertex` 节点类来表示顶点**,这样做的原因有: - 如果我们选择通过顶点值来区分不同顶点,那么值重复的顶点将无法被区分。 - 如果类似邻接矩阵那样,使用顶点列表索引来区分不同顶点。那么,假设我们想要删除索引为 $i$ 的顶点,则需要遍历整个邻接表,将其中 $> i$ 的索引全部减 $1$,这样操作效率较低。 diff --git a/docs/chapter_graph/graph_traversal.assets/graph_bfs.png b/docs/chapter_graph/graph_traversal.assets/graph_bfs.png index da53cbaa..08ef3190 100644 Binary files a/docs/chapter_graph/graph_traversal.assets/graph_bfs.png and b/docs/chapter_graph/graph_traversal.assets/graph_bfs.png differ diff --git a/docs/chapter_graph/graph_traversal.assets/graph_bfs_step1.png b/docs/chapter_graph/graph_traversal.assets/graph_bfs_step1.png index fa347f1b..36638b82 100644 Binary files a/docs/chapter_graph/graph_traversal.assets/graph_bfs_step1.png and b/docs/chapter_graph/graph_traversal.assets/graph_bfs_step1.png differ diff --git a/docs/chapter_graph/graph_traversal.assets/graph_bfs_step10.png b/docs/chapter_graph/graph_traversal.assets/graph_bfs_step10.png index ccf68bb7..97fc1b94 100644 Binary files a/docs/chapter_graph/graph_traversal.assets/graph_bfs_step10.png and b/docs/chapter_graph/graph_traversal.assets/graph_bfs_step10.png differ diff --git a/docs/chapter_graph/graph_traversal.assets/graph_bfs_step11.png b/docs/chapter_graph/graph_traversal.assets/graph_bfs_step11.png index 29ad7c4c..872e726e 100644 Binary files a/docs/chapter_graph/graph_traversal.assets/graph_bfs_step11.png and b/docs/chapter_graph/graph_traversal.assets/graph_bfs_step11.png differ diff --git a/docs/chapter_graph/graph_traversal.assets/graph_bfs_step2.png b/docs/chapter_graph/graph_traversal.assets/graph_bfs_step2.png index 027a466e..0c69ffe5 100644 Binary files a/docs/chapter_graph/graph_traversal.assets/graph_bfs_step2.png and b/docs/chapter_graph/graph_traversal.assets/graph_bfs_step2.png differ diff --git a/docs/chapter_graph/graph_traversal.assets/graph_bfs_step3.png b/docs/chapter_graph/graph_traversal.assets/graph_bfs_step3.png index 6fe0ea6e..cfc00651 100644 Binary files a/docs/chapter_graph/graph_traversal.assets/graph_bfs_step3.png and b/docs/chapter_graph/graph_traversal.assets/graph_bfs_step3.png differ diff --git a/docs/chapter_graph/graph_traversal.assets/graph_bfs_step4.png b/docs/chapter_graph/graph_traversal.assets/graph_bfs_step4.png index 3c023d9b..cccb9aa5 100644 Binary files a/docs/chapter_graph/graph_traversal.assets/graph_bfs_step4.png and b/docs/chapter_graph/graph_traversal.assets/graph_bfs_step4.png differ diff --git a/docs/chapter_graph/graph_traversal.assets/graph_bfs_step5.png b/docs/chapter_graph/graph_traversal.assets/graph_bfs_step5.png index 28234f2a..efbb8d16 100644 Binary files a/docs/chapter_graph/graph_traversal.assets/graph_bfs_step5.png and b/docs/chapter_graph/graph_traversal.assets/graph_bfs_step5.png differ diff --git a/docs/chapter_graph/graph_traversal.assets/graph_bfs_step6.png b/docs/chapter_graph/graph_traversal.assets/graph_bfs_step6.png index a909bdfc..c709d351 100644 Binary files a/docs/chapter_graph/graph_traversal.assets/graph_bfs_step6.png and b/docs/chapter_graph/graph_traversal.assets/graph_bfs_step6.png differ diff --git a/docs/chapter_graph/graph_traversal.assets/graph_bfs_step7.png b/docs/chapter_graph/graph_traversal.assets/graph_bfs_step7.png index f80b03dd..c9084860 100644 Binary files a/docs/chapter_graph/graph_traversal.assets/graph_bfs_step7.png and b/docs/chapter_graph/graph_traversal.assets/graph_bfs_step7.png differ diff --git a/docs/chapter_graph/graph_traversal.assets/graph_bfs_step8.png b/docs/chapter_graph/graph_traversal.assets/graph_bfs_step8.png index c7c01b81..ee660474 100644 Binary files a/docs/chapter_graph/graph_traversal.assets/graph_bfs_step8.png and b/docs/chapter_graph/graph_traversal.assets/graph_bfs_step8.png differ diff --git a/docs/chapter_graph/graph_traversal.assets/graph_bfs_step9.png b/docs/chapter_graph/graph_traversal.assets/graph_bfs_step9.png index 94755998..e7ceb7a8 100644 Binary files a/docs/chapter_graph/graph_traversal.assets/graph_bfs_step9.png and b/docs/chapter_graph/graph_traversal.assets/graph_bfs_step9.png differ diff --git a/docs/chapter_graph/graph_traversal.assets/graph_dfs.png b/docs/chapter_graph/graph_traversal.assets/graph_dfs.png index 2116a55e..a26c51f7 100644 Binary files a/docs/chapter_graph/graph_traversal.assets/graph_dfs.png and b/docs/chapter_graph/graph_traversal.assets/graph_dfs.png differ diff --git a/docs/chapter_graph/graph_traversal.assets/graph_dfs_step1.png b/docs/chapter_graph/graph_traversal.assets/graph_dfs_step1.png index d94eff93..ee706b74 100644 Binary files a/docs/chapter_graph/graph_traversal.assets/graph_dfs_step1.png and b/docs/chapter_graph/graph_traversal.assets/graph_dfs_step1.png differ diff --git a/docs/chapter_graph/graph_traversal.assets/graph_dfs_step10.png b/docs/chapter_graph/graph_traversal.assets/graph_dfs_step10.png index 9d00294d..e34d1df2 100644 Binary files a/docs/chapter_graph/graph_traversal.assets/graph_dfs_step10.png and b/docs/chapter_graph/graph_traversal.assets/graph_dfs_step10.png differ diff --git a/docs/chapter_graph/graph_traversal.assets/graph_dfs_step11.png b/docs/chapter_graph/graph_traversal.assets/graph_dfs_step11.png index 9533f1e7..49a3fb96 100644 Binary files a/docs/chapter_graph/graph_traversal.assets/graph_dfs_step11.png and b/docs/chapter_graph/graph_traversal.assets/graph_dfs_step11.png differ diff --git a/docs/chapter_graph/graph_traversal.assets/graph_dfs_step2.png b/docs/chapter_graph/graph_traversal.assets/graph_dfs_step2.png index 991e835b..13bae891 100644 Binary files a/docs/chapter_graph/graph_traversal.assets/graph_dfs_step2.png and b/docs/chapter_graph/graph_traversal.assets/graph_dfs_step2.png differ diff --git a/docs/chapter_graph/graph_traversal.assets/graph_dfs_step3.png b/docs/chapter_graph/graph_traversal.assets/graph_dfs_step3.png index d0b63e57..3c4c4b1e 100644 Binary files a/docs/chapter_graph/graph_traversal.assets/graph_dfs_step3.png and b/docs/chapter_graph/graph_traversal.assets/graph_dfs_step3.png differ diff --git a/docs/chapter_graph/graph_traversal.assets/graph_dfs_step4.png b/docs/chapter_graph/graph_traversal.assets/graph_dfs_step4.png index becffab3..9e0286e0 100644 Binary files a/docs/chapter_graph/graph_traversal.assets/graph_dfs_step4.png and b/docs/chapter_graph/graph_traversal.assets/graph_dfs_step4.png differ diff --git a/docs/chapter_graph/graph_traversal.assets/graph_dfs_step5.png b/docs/chapter_graph/graph_traversal.assets/graph_dfs_step5.png index 0e5cd953..6da4b0d8 100644 Binary files a/docs/chapter_graph/graph_traversal.assets/graph_dfs_step5.png and b/docs/chapter_graph/graph_traversal.assets/graph_dfs_step5.png differ diff --git a/docs/chapter_graph/graph_traversal.assets/graph_dfs_step6.png b/docs/chapter_graph/graph_traversal.assets/graph_dfs_step6.png index d9ea117c..2cccc731 100644 Binary files a/docs/chapter_graph/graph_traversal.assets/graph_dfs_step6.png and b/docs/chapter_graph/graph_traversal.assets/graph_dfs_step6.png differ diff --git a/docs/chapter_graph/graph_traversal.assets/graph_dfs_step7.png b/docs/chapter_graph/graph_traversal.assets/graph_dfs_step7.png index 1503a697..2291e24f 100644 Binary files a/docs/chapter_graph/graph_traversal.assets/graph_dfs_step7.png and b/docs/chapter_graph/graph_traversal.assets/graph_dfs_step7.png differ diff --git a/docs/chapter_graph/graph_traversal.assets/graph_dfs_step8.png b/docs/chapter_graph/graph_traversal.assets/graph_dfs_step8.png index 92dee73f..e464862f 100644 Binary files a/docs/chapter_graph/graph_traversal.assets/graph_dfs_step8.png and b/docs/chapter_graph/graph_traversal.assets/graph_dfs_step8.png differ diff --git a/docs/chapter_graph/graph_traversal.assets/graph_dfs_step9.png b/docs/chapter_graph/graph_traversal.assets/graph_dfs_step9.png index 5982b88c..b19b5c38 100644 Binary files a/docs/chapter_graph/graph_traversal.assets/graph_dfs_step9.png and b/docs/chapter_graph/graph_traversal.assets/graph_dfs_step9.png differ diff --git a/docs/chapter_graph/graph_traversal.md b/docs/chapter_graph/graph_traversal.md index 72667f5f..b568e39d 100644 --- a/docs/chapter_graph/graph_traversal.md +++ b/docs/chapter_graph/graph_traversal.md @@ -22,7 +22,7 @@ BFS 通常借助「队列」来实现。队列具有“先入先出”的性质 2. 在循环的每轮迭代中,弹出队首顶点并记录访问,然后将该顶点的所有邻接顶点加入到队列尾部; 3. 循环步骤 `2.` ,直到所有顶点被访问完成后结束; -为了防止重复遍历顶点,我们需要借助一个哈希表 `visited` 来记录哪些结点已被访问。 +为了防止重复遍历顶点,我们需要借助一个哈希表 `visited` 来记录哪些节点已被访问。 === "Java" diff --git a/docs/chapter_hashing/hash_collision.assets/hash_collision_chaining.png b/docs/chapter_hashing/hash_collision.assets/hash_collision_chaining.png index e0c91ec5..6653bfa1 100644 Binary files a/docs/chapter_hashing/hash_collision.assets/hash_collision_chaining.png and b/docs/chapter_hashing/hash_collision.assets/hash_collision_chaining.png differ diff --git a/docs/chapter_hashing/hash_collision.assets/hash_collision_linear_probing.png b/docs/chapter_hashing/hash_collision.assets/hash_collision_linear_probing.png index 96b3478a..31263aab 100644 Binary files a/docs/chapter_hashing/hash_collision.assets/hash_collision_linear_probing.png and b/docs/chapter_hashing/hash_collision.assets/hash_collision_linear_probing.png differ diff --git a/docs/chapter_hashing/hash_collision.md b/docs/chapter_hashing/hash_collision.md index 1ebf444f..c2e49b46 100644 --- a/docs/chapter_hashing/hash_collision.md +++ b/docs/chapter_hashing/hash_collision.md @@ -24,13 +24,13 @@ 链式地址下,哈希表的操作方法包括: -- **查询元素**:输入 key ,经过哈希函数得到数组索引,即可访问链表头结点,然后遍历链表并对比 key 以查找目标键值对。 -- **添加元素**:先通过哈希函数访问链表头结点,然后将结点(即键值对)添加到链表中。 -- **删除元素**:根据哈希函数的结果访问链表头部,接着遍历链表以查找目标结点,并将其删除。 +- **查询元素**:输入 key ,经过哈希函数得到数组索引,即可访问链表头节点,然后遍历链表并对比 key 以查找目标键值对。 +- **添加元素**:先通过哈希函数访问链表头节点,然后将节点(即键值对)添加到链表中。 +- **删除元素**:根据哈希函数的结果访问链表头部,接着遍历链表以查找目标节点,并将其删除。 尽管链式地址法解决了哈希冲突问题,但仍存在一些局限性,包括: -- **占用空间增大**,由于链表或二叉树包含结点指针,相比数组更加耗费内存空间; +- **占用空间增大**,由于链表或二叉树包含节点指针,相比数组更加耗费内存空间; - **查询效率降低**,因为需要线性遍历链表来查找对应元素; 为了提高操作效率,**可以将链表转换为「AVL 树」或「红黑树」**,将查询操作的时间复杂度优化至 $O(\log n)$ 。 diff --git a/docs/chapter_hashing/hash_map.assets/hash_collision.png b/docs/chapter_hashing/hash_map.assets/hash_collision.png index 91d7ff3a..2d5d91e1 100644 Binary files a/docs/chapter_hashing/hash_map.assets/hash_collision.png and b/docs/chapter_hashing/hash_map.assets/hash_collision.png differ diff --git a/docs/chapter_hashing/hash_map.assets/hash_function.png b/docs/chapter_hashing/hash_map.assets/hash_function.png index f47b21a7..18e0f011 100644 Binary files a/docs/chapter_hashing/hash_map.assets/hash_function.png and b/docs/chapter_hashing/hash_map.assets/hash_function.png differ diff --git a/docs/chapter_hashing/hash_map.assets/hash_map.png b/docs/chapter_hashing/hash_map.assets/hash_map.png index 68ba0f4f..124dacd3 100644 Binary files a/docs/chapter_hashing/hash_map.assets/hash_map.png and b/docs/chapter_hashing/hash_map.assets/hash_map.png differ diff --git a/docs/chapter_hashing/hash_map.md b/docs/chapter_hashing/hash_map.md index 5c096212..12968eaa 100755 --- a/docs/chapter_hashing/hash_map.md +++ b/docs/chapter_hashing/hash_map.md @@ -12,8 +12,8 @@ 1. **无序数组**:每个元素为 `[学号, 姓名]` ; 2. **有序数组**:将 `1.` 中的数组按照学号从小到大排序; -3. **链表**:每个结点的值为 `[学号, 姓名]` ; -4. **二叉搜索树**:每个结点的值为 `[学号, 姓名]` ,根据学号大小来构建树; +3. **链表**:每个节点的值为 `[学号, 姓名]` ; +4. **二叉搜索树**:每个节点的值为 `[学号, 姓名]` ,根据学号大小来构建树; 各项操作的时间复杂度如下表所示(详解可见[二叉搜索树章节](https://www.hello-algo.com/chapter_tree/binary_search_tree/))。无论是查找元素还是增删元素,哈希表的时间复杂度都是 $O(1)$,全面胜出! diff --git a/docs/chapter_heap/build_heap.assets/heapify_operations_count.png b/docs/chapter_heap/build_heap.assets/heapify_operations_count.png index d4095968..079c53e1 100644 Binary files a/docs/chapter_heap/build_heap.assets/heapify_operations_count.png and b/docs/chapter_heap/build_heap.assets/heapify_operations_count.png differ diff --git a/docs/chapter_heap/build_heap.md b/docs/chapter_heap/build_heap.md index 8f64e189..4d3ff08c 100644 --- a/docs/chapter_heap/build_heap.md +++ b/docs/chapter_heap/build_heap.md @@ -1,18 +1,18 @@ # 建堆操作 * -如果我们想要根据输入列表来生成一个堆,这样的操作被称为「建堆」。 +如果我们想要根据输入列表生成一个堆,这个过程被称为「建堆」。 ## 两种建堆方法 ### 借助入堆方法实现 -最直接地,考虑借助「元素入堆」方法,先建立一个空堆,**再将列表元素依次入堆即可**。 +最直接的方法是借助“元素入堆操作”实现,首先创建一个空堆,然后将列表元素依次添加到堆中。 -设元素数量为 $n$ ,则最后一个元素入堆的时间复杂度为 $O(\log n)$ ,在依次入堆时,堆的平均长度为 $\frac{n}{2}$ ,因此该方法的总体时间复杂度为 $O(n \log n)$ 。 +设元素数量为 $n$ ,则最后一个元素入堆的时间复杂度为 $O(\log n)$ 。在依次添加元素时,堆的平均长度为 $\frac{n}{2}$ ,因此该方法的总体时间复杂度为 $O(n \log n)$ 。 ### 基于堆化操作实现 -有趣的是,存在一种更加高效的建堆方法,时间复杂度可以达到 $O(n)$ 。我们先将列表所有元素原封不动添加进堆,**然后迭代地对各个结点执行「从顶至底堆化」**。当然,**无需对叶结点执行堆化**,因为其没有子结点。 +有趣的是,存在一种更高效的建堆方法,其时间复杂度仅为 $O(n)$ 。我们先将列表所有元素原封不动添加到堆中,**然后迭代地对各个节点执行“从顶至底堆化”**。当然,**我们不需要对叶节点执行堆化操作**,因为它们没有子节点。 === "Java" @@ -76,24 +76,24 @@ ## 复杂度分析 -第二种建堆方法的时间复杂度为什么是 $O(n)$ 呢?我们来展开推算一下。 +为什么第二种建堆方法的时间复杂度是 $O(n)$ ?我们来展开推算一下。 -- 完全二叉树中,设结点总数为 $n$ ,则叶结点数量为 $(n + 1) / 2$ ,其中 $/$ 为向下整除。因此在排除叶结点后,需要堆化结点数量为 $(n - 1)/2$ ,即为 $O(n)$ ; -- 从顶至底堆化中,每个结点最多堆化至叶结点,因此最大迭代次数为二叉树高度 $O(\log n)$ ; +- 完全二叉树中,设节点总数为 $n$ ,则叶节点数量为 $(n + 1) / 2$ ,其中 $/$ 为向下整除。因此,在排除叶节点后,需要堆化的节点数量为 $(n - 1)/2$ ,复杂度为 $O(n)$ ; +- 在从顶至底堆化的过程中,每个节点最多堆化到叶节点,因此最大迭代次数为二叉树高度 $O(\log n)$ ; -将上述两者相乘,可得时间复杂度为 $O(n \log n)$ 。这个估算结果不够准确,因为我们没有考虑到 **二叉树底层结点远多于顶层结点** 的性质。 +将上述两者相乘,可得到建堆过程的时间复杂度为 $O(n \log n)$。**然而,这个估算结果并不准确,因为我们没有考虑到二叉树底层节点数量远多于顶层节点的特性**。 -下面我们来展开计算。为了减小计算难度,我们假设树是一个「完美二叉树」,该假设不会影响计算结果的正确性。设二叉树(即堆)结点数量为 $n$ ,树高度为 $h$ 。上文提到,**结点堆化最大迭代次数等于该结点到叶结点的距离,而这正是“结点高度”**。 +接下来我们来进行更为详细的计算。为了减小计算难度,我们假设树是一个“完美二叉树”,该假设不会影响计算结果的正确性。设二叉树(即堆)节点数量为 $n$ ,树高度为 $h$ 。上文提到,**节点堆化最大迭代次数等于该节点到叶节点的距离,而该距离正是“节点高度”**。 -![完美二叉树的各层结点数量](build_heap.assets/heapify_operations_count.png) +![完美二叉树的各层节点数量](build_heap.assets/heapify_operations_count.png) -因此,我们将各层的“结点数量 $\times$ 结点高度”求和,即可得到 **所有结点的堆化的迭代次数总和**。 +因此,我们可以将各层的“节点数量 $\times$ 节点高度”求和,**从而得到所有节点的堆化迭代次数的总和**。 $$ T(h) = 2^0h + 2^1(h-1) + 2^2(h-2) + \cdots + 2^{(h-1)}\times1 $$ -化简上式需要借助中学的数列知识,先对 $T(h)$ 乘以 $2$ ,易得 +化简上式需要借助中学的数列知识,先对 $T(h)$ 乘以 $2$ ,得到 $$ \begin{aligned} @@ -108,7 +108,7 @@ $$ 2T(h) - T(h) = T(h) = -2^0h + 2^1 + 2^2 + \cdots + 2^{h-1} + 2^h $$ -观察上式,$T(h)$ 是一个等比数列,可直接使用求和公式,得到时间复杂度为 +观察上式,发现 $T(h)$ 是一个等比数列,可直接使用求和公式,得到时间复杂度为 $$ \begin{aligned} @@ -118,4 +118,4 @@ T(h) & = 2 \frac{1 - 2^h}{1 - 2} - h \newline \end{aligned} $$ -进一步地,高度为 $h$ 的完美二叉树的结点数量为 $n = 2^{h+1} - 1$ ,易得复杂度为 $O(2^h) = O(n)$ 。以上推算表明,**输入列表并建堆的时间复杂度为 $O(n)$ ,非常高效**。 +进一步地,高度为 $h$ 的完美二叉树的节点数量为 $n = 2^{h+1} - 1$ ,易得复杂度为 $O(2^h) = O(n)$ 。以上推算表明,**输入列表并建堆的时间复杂度为 $O(n)$ ,非常高效**。 diff --git a/docs/chapter_heap/heap.assets/heap_pop_step1.png b/docs/chapter_heap/heap.assets/heap_pop_step1.png index 40ade82c..d8593777 100644 Binary files a/docs/chapter_heap/heap.assets/heap_pop_step1.png and b/docs/chapter_heap/heap.assets/heap_pop_step1.png differ diff --git a/docs/chapter_heap/heap.assets/heap_pop_step10.png b/docs/chapter_heap/heap.assets/heap_pop_step10.png index 3e117b74..a71bc29c 100644 Binary files a/docs/chapter_heap/heap.assets/heap_pop_step10.png and b/docs/chapter_heap/heap.assets/heap_pop_step10.png differ diff --git a/docs/chapter_heap/heap.assets/heap_pop_step2.png b/docs/chapter_heap/heap.assets/heap_pop_step2.png index c9755910..0ae3f031 100644 Binary files a/docs/chapter_heap/heap.assets/heap_pop_step2.png and b/docs/chapter_heap/heap.assets/heap_pop_step2.png differ diff --git a/docs/chapter_heap/heap.assets/heap_pop_step3.png b/docs/chapter_heap/heap.assets/heap_pop_step3.png index 68d5a775..f62f74fc 100644 Binary files a/docs/chapter_heap/heap.assets/heap_pop_step3.png and b/docs/chapter_heap/heap.assets/heap_pop_step3.png differ diff --git a/docs/chapter_heap/heap.assets/heap_pop_step4.png b/docs/chapter_heap/heap.assets/heap_pop_step4.png index 727e62fd..459a4522 100644 Binary files a/docs/chapter_heap/heap.assets/heap_pop_step4.png and b/docs/chapter_heap/heap.assets/heap_pop_step4.png differ diff --git a/docs/chapter_heap/heap.assets/heap_pop_step5.png b/docs/chapter_heap/heap.assets/heap_pop_step5.png index 86659442..ecad3567 100644 Binary files a/docs/chapter_heap/heap.assets/heap_pop_step5.png and b/docs/chapter_heap/heap.assets/heap_pop_step5.png differ diff --git a/docs/chapter_heap/heap.assets/heap_pop_step6.png b/docs/chapter_heap/heap.assets/heap_pop_step6.png index 99f91923..33a00cf5 100644 Binary files a/docs/chapter_heap/heap.assets/heap_pop_step6.png and b/docs/chapter_heap/heap.assets/heap_pop_step6.png differ diff --git a/docs/chapter_heap/heap.assets/heap_pop_step7.png b/docs/chapter_heap/heap.assets/heap_pop_step7.png index 24f81b6f..228e8019 100644 Binary files a/docs/chapter_heap/heap.assets/heap_pop_step7.png and b/docs/chapter_heap/heap.assets/heap_pop_step7.png differ diff --git a/docs/chapter_heap/heap.assets/heap_pop_step8.png b/docs/chapter_heap/heap.assets/heap_pop_step8.png index eef69239..06098434 100644 Binary files a/docs/chapter_heap/heap.assets/heap_pop_step8.png and b/docs/chapter_heap/heap.assets/heap_pop_step8.png differ diff --git a/docs/chapter_heap/heap.assets/heap_pop_step9.png b/docs/chapter_heap/heap.assets/heap_pop_step9.png index d11f5543..0672abe3 100644 Binary files a/docs/chapter_heap/heap.assets/heap_pop_step9.png and b/docs/chapter_heap/heap.assets/heap_pop_step9.png differ diff --git a/docs/chapter_heap/heap.assets/heap_push_step1.png b/docs/chapter_heap/heap.assets/heap_push_step1.png index 830093e0..cb046641 100644 Binary files a/docs/chapter_heap/heap.assets/heap_push_step1.png and b/docs/chapter_heap/heap.assets/heap_push_step1.png differ diff --git a/docs/chapter_heap/heap.assets/heap_push_step2.png b/docs/chapter_heap/heap.assets/heap_push_step2.png index e692e61f..49d6765b 100644 Binary files a/docs/chapter_heap/heap.assets/heap_push_step2.png and b/docs/chapter_heap/heap.assets/heap_push_step2.png differ diff --git a/docs/chapter_heap/heap.assets/heap_push_step3.png b/docs/chapter_heap/heap.assets/heap_push_step3.png index f75050dd..addd2748 100644 Binary files a/docs/chapter_heap/heap.assets/heap_push_step3.png and b/docs/chapter_heap/heap.assets/heap_push_step3.png differ diff --git a/docs/chapter_heap/heap.assets/heap_push_step4.png b/docs/chapter_heap/heap.assets/heap_push_step4.png index 7d938bce..69eac84d 100644 Binary files a/docs/chapter_heap/heap.assets/heap_push_step4.png and b/docs/chapter_heap/heap.assets/heap_push_step4.png differ diff --git a/docs/chapter_heap/heap.assets/heap_push_step5.png b/docs/chapter_heap/heap.assets/heap_push_step5.png index 10c0ad0a..1ed9dd42 100644 Binary files a/docs/chapter_heap/heap.assets/heap_push_step5.png and b/docs/chapter_heap/heap.assets/heap_push_step5.png differ diff --git a/docs/chapter_heap/heap.assets/heap_push_step6.png b/docs/chapter_heap/heap.assets/heap_push_step6.png index 29222381..1a9a7ae3 100644 Binary files a/docs/chapter_heap/heap.assets/heap_push_step6.png and b/docs/chapter_heap/heap.assets/heap_push_step6.png differ diff --git a/docs/chapter_heap/heap.assets/min_heap_and_max_heap.png b/docs/chapter_heap/heap.assets/min_heap_and_max_heap.png index cee747ac..435ce7f2 100644 Binary files a/docs/chapter_heap/heap.assets/min_heap_and_max_heap.png and b/docs/chapter_heap/heap.assets/min_heap_and_max_heap.png differ diff --git a/docs/chapter_heap/heap.assets/representation_of_heap.png b/docs/chapter_heap/heap.assets/representation_of_heap.png index 9427b935..a267d24d 100644 Binary files a/docs/chapter_heap/heap.assets/representation_of_heap.png and b/docs/chapter_heap/heap.assets/representation_of_heap.png differ diff --git a/docs/chapter_heap/heap.md b/docs/chapter_heap/heap.md index c549402a..c8285688 100644 --- a/docs/chapter_heap/heap.md +++ b/docs/chapter_heap/heap.md @@ -2,16 +2,16 @@ 「堆 Heap」是一棵限定条件下的「完全二叉树」。根据成立条件,堆主要分为两种类型: -- 「大顶堆 Max Heap」,任意结点的值 $\geq$ 其子结点的值; -- 「小顶堆 Min Heap」,任意结点的值 $\leq$ 其子结点的值; +- 「大顶堆 Max Heap」,任意节点的值 $\geq$ 其子节点的值; +- 「小顶堆 Min Heap」,任意节点的值 $\leq$ 其子节点的值; ![小顶堆与大顶堆](heap.assets/min_heap_and_max_heap.png) ## 堆术语与性质 -- 由于堆是完全二叉树,因此最底层结点靠左填充,其它层结点皆被填满。 -- 二叉树中的根结点对应「堆顶」,底层最靠右结点对应「堆底」。 -- 对于大顶堆 / 小顶堆,其堆顶元素(即根结点)的值最大 / 最小。 +- 由于堆是完全二叉树,因此最底层节点靠左填充,其它层节点皆被填满。 +- 二叉树中的根节点对应「堆顶」,底层最靠右节点对应「堆底」。 +- 对于大顶堆 / 小顶堆,其堆顶元素(即根节点)的值最大 / 最小。 ## 堆常用操作 @@ -308,9 +308,9 @@ 在二叉树章节我们学过,「完全二叉树」非常适合使用「数组」来表示,而堆恰好是一棵完全二叉树,**因而我们采用「数组」来存储「堆」**。 -**二叉树指针**。使用数组表示二叉树时,元素代表结点值,索引代表结点在二叉树中的位置,**而结点指针通过索引映射公式来实现**。 +**二叉树指针**。使用数组表示二叉树时,元素代表节点值,索引代表节点在二叉树中的位置,**而节点指针通过索引映射公式来实现**。 -具体地,给定索引 $i$ ,那么其左子结点索引为 $2i + 1$ 、右子结点索引为 $2i + 2$ 、父结点索引为 $(i - 1) / 2$ (向下整除)。当索引越界时,代表空结点或结点不存在。 +具体地,给定索引 $i$ ,那么其左子节点索引为 $2i + 1$ 、右子节点索引为 $2i + 2$ 、父节点索引为 $(i - 1) / 2$ (向下整除)。当索引越界时,代表空节点或节点不存在。 ![堆的表示与存储](heap.assets/representation_of_heap.png) @@ -418,7 +418,7 @@ ### 访问堆顶元素 -堆顶元素是二叉树的根结点,即列表首元素。 +堆顶元素是二叉树的根节点,即列表首元素。 === "Java" @@ -482,9 +482,9 @@ ### 元素入堆 -给定元素 `val` ,我们先将其添加到堆底。添加后,由于 `val` 可能大于堆中其它元素,此时堆的成立条件可能已经被破坏,**因此需要修复从插入结点到根结点这条路径上的各个结点**,该操作被称为「堆化 Heapify」。 +给定元素 `val` ,我们先将其添加到堆底。添加后,由于 `val` 可能大于堆中其它元素,此时堆的成立条件可能已经被破坏,**因此需要修复从插入节点到根节点这条路径上的各个节点**,该操作被称为「堆化 Heapify」。 -考虑从入堆结点开始,**从底至顶执行堆化**。具体地,比较插入结点与其父结点的值,若插入结点更大则将它们交换;并循环以上操作,从底至顶地修复堆中的各个结点;直至越过根结点时结束,或当遇到无需交换的结点时提前结束。 +考虑从入堆节点开始,**从底至顶执行堆化**。具体地,比较插入节点与其父节点的值,若插入节点更大则将它们交换;并循环以上操作,从底至顶地修复堆中的各个节点;直至越过根节点时结束,或当遇到无需交换的节点时提前结束。 === "<1>" ![元素入堆步骤](heap.assets/heap_push_step1.png) @@ -504,7 +504,7 @@ === "<6>" ![heap_push_step6](heap.assets/heap_push_step6.png) -设结点总数为 $n$ ,则树的高度为 $O(\log n)$ ,易得堆化操作的循环轮数最多为 $O(\log n)$ ,**因而元素入堆操作的时间复杂度为 $O(\log n)$** 。 +设节点总数为 $n$ ,则树的高度为 $O(\log n)$ ,易得堆化操作的循环轮数最多为 $O(\log n)$ ,**因而元素入堆操作的时间复杂度为 $O(\log n)$** 。 === "Java" @@ -588,13 +588,13 @@ ### 堆顶元素出堆 -堆顶元素是二叉树根结点,即列表首元素,如果我们直接将首元素从列表中删除,则二叉树中所有结点都会随之发生移位(索引发生变化),这样后续使用堆化修复就很麻烦了。为了尽量减少元素索引变动,采取以下操作步骤: +堆顶元素是二叉树根节点,即列表首元素,如果我们直接将首元素从列表中删除,则二叉树中所有节点都会随之发生移位(索引发生变化),这样后续使用堆化修复就很麻烦了。为了尽量减少元素索引变动,采取以下操作步骤: -1. 交换堆顶元素与堆底元素(即交换根结点与最右叶结点); +1. 交换堆顶元素与堆底元素(即交换根节点与最右叶节点); 2. 交换完成后,将堆底从列表中删除(注意,因为已经交换,实际上删除的是原来的堆顶元素); -3. 从根结点开始,**从顶至底执行堆化**; +3. 从根节点开始,**从顶至底执行堆化**; -顾名思义,**从顶至底堆化的操作方向与从底至顶堆化相反**,我们比较根结点的值与其两个子结点的值,将最大的子结点与根结点执行交换,并循环以上操作,直到越过叶结点时结束,或当遇到无需交换的结点时提前结束。 +顾名思义,**从顶至底堆化的操作方向与从底至顶堆化相反**,我们比较根节点的值与其两个子节点的值,将最大的子节点与根节点执行交换,并循环以上操作,直到越过叶节点时结束,或当遇到无需交换的节点时提前结束。 === "<1>" ![堆顶元素出堆步骤](heap.assets/heap_pop_step1.png) diff --git a/docs/chapter_introduction/algorithms_are_everywhere.assets/look_up_dictionary_step_1.png b/docs/chapter_introduction/algorithms_are_everywhere.assets/look_up_dictionary_step_1.png index b94a8aa6..9eda07d7 100644 Binary files a/docs/chapter_introduction/algorithms_are_everywhere.assets/look_up_dictionary_step_1.png and b/docs/chapter_introduction/algorithms_are_everywhere.assets/look_up_dictionary_step_1.png differ diff --git a/docs/chapter_introduction/algorithms_are_everywhere.assets/look_up_dictionary_step_2.png b/docs/chapter_introduction/algorithms_are_everywhere.assets/look_up_dictionary_step_2.png index 39dbedfc..e0840387 100644 Binary files a/docs/chapter_introduction/algorithms_are_everywhere.assets/look_up_dictionary_step_2.png and b/docs/chapter_introduction/algorithms_are_everywhere.assets/look_up_dictionary_step_2.png differ diff --git a/docs/chapter_introduction/algorithms_are_everywhere.assets/look_up_dictionary_step_3.png b/docs/chapter_introduction/algorithms_are_everywhere.assets/look_up_dictionary_step_3.png index 1463b84d..2c0459f8 100644 Binary files a/docs/chapter_introduction/algorithms_are_everywhere.assets/look_up_dictionary_step_3.png and b/docs/chapter_introduction/algorithms_are_everywhere.assets/look_up_dictionary_step_3.png differ diff --git a/docs/chapter_introduction/algorithms_are_everywhere.assets/look_up_dictionary_step_4.png b/docs/chapter_introduction/algorithms_are_everywhere.assets/look_up_dictionary_step_4.png index f01d1c7c..45f9eb2b 100644 Binary files a/docs/chapter_introduction/algorithms_are_everywhere.assets/look_up_dictionary_step_4.png and b/docs/chapter_introduction/algorithms_are_everywhere.assets/look_up_dictionary_step_4.png differ diff --git a/docs/chapter_introduction/algorithms_are_everywhere.assets/look_up_dictionary_step_5.png b/docs/chapter_introduction/algorithms_are_everywhere.assets/look_up_dictionary_step_5.png index d73a2f05..95cd445c 100644 Binary files a/docs/chapter_introduction/algorithms_are_everywhere.assets/look_up_dictionary_step_5.png and b/docs/chapter_introduction/algorithms_are_everywhere.assets/look_up_dictionary_step_5.png differ diff --git a/docs/chapter_introduction/what_is_dsa.assets/relationship_between_data_structure_and_algorithm.png b/docs/chapter_introduction/what_is_dsa.assets/relationship_between_data_structure_and_algorithm.png index bc053429..320a55f7 100644 Binary files a/docs/chapter_introduction/what_is_dsa.assets/relationship_between_data_structure_and_algorithm.png and b/docs/chapter_introduction/what_is_dsa.assets/relationship_between_data_structure_and_algorithm.png differ diff --git a/docs/chapter_preface/about_the_book.assets/hello_algo_mindmap.png b/docs/chapter_preface/about_the_book.assets/hello_algo_mindmap.png index c0f3dc06..b20b57f4 100644 Binary files a/docs/chapter_preface/about_the_book.assets/hello_algo_mindmap.png and b/docs/chapter_preface/about_the_book.assets/hello_algo_mindmap.png differ diff --git a/docs/chapter_preface/suggestions.assets/code_md_to_repo.png b/docs/chapter_preface/suggestions.assets/code_md_to_repo.png index 892f8902..7f1deca6 100644 Binary files a/docs/chapter_preface/suggestions.assets/code_md_to_repo.png and b/docs/chapter_preface/suggestions.assets/code_md_to_repo.png differ diff --git a/docs/chapter_preface/suggestions.assets/download_code.png b/docs/chapter_preface/suggestions.assets/download_code.png index 89d62ef9..66e20158 100644 Binary files a/docs/chapter_preface/suggestions.assets/download_code.png and b/docs/chapter_preface/suggestions.assets/download_code.png differ diff --git a/docs/chapter_preface/suggestions.assets/learning_route.png b/docs/chapter_preface/suggestions.assets/learning_route.png index 80641339..ccca4eeb 100644 Binary files a/docs/chapter_preface/suggestions.assets/learning_route.png and b/docs/chapter_preface/suggestions.assets/learning_route.png differ diff --git a/docs/chapter_searching/binary_search.assets/binary_search_step1.png b/docs/chapter_searching/binary_search.assets/binary_search_step1.png index 158ee811..51ae5905 100644 Binary files a/docs/chapter_searching/binary_search.assets/binary_search_step1.png and b/docs/chapter_searching/binary_search.assets/binary_search_step1.png differ diff --git a/docs/chapter_searching/binary_search.assets/binary_search_step2.png b/docs/chapter_searching/binary_search.assets/binary_search_step2.png index 20fe3d48..00a60ea0 100644 Binary files a/docs/chapter_searching/binary_search.assets/binary_search_step2.png and b/docs/chapter_searching/binary_search.assets/binary_search_step2.png differ diff --git a/docs/chapter_searching/binary_search.assets/binary_search_step3.png b/docs/chapter_searching/binary_search.assets/binary_search_step3.png index 34939df3..ad3b851f 100644 Binary files a/docs/chapter_searching/binary_search.assets/binary_search_step3.png and b/docs/chapter_searching/binary_search.assets/binary_search_step3.png differ diff --git a/docs/chapter_searching/binary_search.assets/binary_search_step4.png b/docs/chapter_searching/binary_search.assets/binary_search_step4.png index c1aad531..41578dc0 100644 Binary files a/docs/chapter_searching/binary_search.assets/binary_search_step4.png and b/docs/chapter_searching/binary_search.assets/binary_search_step4.png differ diff --git a/docs/chapter_searching/binary_search.assets/binary_search_step5.png b/docs/chapter_searching/binary_search.assets/binary_search_step5.png index 54f4ab23..68f5d786 100644 Binary files a/docs/chapter_searching/binary_search.assets/binary_search_step5.png and b/docs/chapter_searching/binary_search.assets/binary_search_step5.png differ diff --git a/docs/chapter_searching/binary_search.assets/binary_search_step6.png b/docs/chapter_searching/binary_search.assets/binary_search_step6.png index 0da399b2..6208bf5d 100644 Binary files a/docs/chapter_searching/binary_search.assets/binary_search_step6.png and b/docs/chapter_searching/binary_search.assets/binary_search_step6.png differ diff --git a/docs/chapter_searching/binary_search.assets/binary_search_step7.png b/docs/chapter_searching/binary_search.assets/binary_search_step7.png index 4e76757b..f292942a 100644 Binary files a/docs/chapter_searching/binary_search.assets/binary_search_step7.png and b/docs/chapter_searching/binary_search.assets/binary_search_step7.png differ diff --git a/docs/chapter_searching/hashing_search.assets/hash_search_index.png b/docs/chapter_searching/hashing_search.assets/hash_search_index.png index ab1b5215..777250b7 100644 Binary files a/docs/chapter_searching/hashing_search.assets/hash_search_index.png and b/docs/chapter_searching/hashing_search.assets/hash_search_index.png differ diff --git a/docs/chapter_searching/hashing_search.assets/hash_search_listnode.png b/docs/chapter_searching/hashing_search.assets/hash_search_listnode.png index e7574799..7e310072 100644 Binary files a/docs/chapter_searching/hashing_search.assets/hash_search_listnode.png and b/docs/chapter_searching/hashing_search.assets/hash_search_listnode.png differ diff --git a/docs/chapter_searching/hashing_search.md b/docs/chapter_searching/hashing_search.md index d7e12a00..255628d3 100755 --- a/docs/chapter_searching/hashing_search.md +++ b/docs/chapter_searching/hashing_search.md @@ -72,9 +72,9 @@ [class]{}-[func]{hashingSearchArray} ``` -再比如,如果我们想要给定一个目标结点值 `target` ,获取对应的链表结点对象,那么也可以使用哈希查找实现。 +再比如,如果我们想要给定一个目标节点值 `target` ,获取对应的链表节点对象,那么也可以使用哈希查找实现。 -![哈希查找链表结点](hashing_search.assets/hash_search_listnode.png) +![哈希查找链表节点](hashing_search.assets/hash_search_listnode.png) === "Java" diff --git a/docs/chapter_searching/linear_search.assets/linear_search.png b/docs/chapter_searching/linear_search.assets/linear_search.png index 60389c81..ca56d5ef 100644 Binary files a/docs/chapter_searching/linear_search.assets/linear_search.png and b/docs/chapter_searching/linear_search.assets/linear_search.png differ diff --git a/docs/chapter_searching/linear_search.md b/docs/chapter_searching/linear_search.md index 3a83c29d..0bd67525 100755 --- a/docs/chapter_searching/linear_search.md +++ b/docs/chapter_searching/linear_search.md @@ -68,7 +68,7 @@ [class]{}-[func]{linearSearchArray} ``` -再比如,我们想要在给定一个目标结点值 `target` ,返回此结点对象,也可以在链表中进行线性查找。 +再比如,我们想要在给定一个目标节点值 `target` ,返回此节点对象,也可以在链表中进行线性查找。 === "Java" diff --git a/docs/chapter_sorting/bubble_sort.assets/bubble_operation_step1.png b/docs/chapter_sorting/bubble_sort.assets/bubble_operation_step1.png index 60b635ff..40a6cff7 100644 Binary files a/docs/chapter_sorting/bubble_sort.assets/bubble_operation_step1.png and b/docs/chapter_sorting/bubble_sort.assets/bubble_operation_step1.png differ diff --git a/docs/chapter_sorting/bubble_sort.assets/bubble_operation_step2.png b/docs/chapter_sorting/bubble_sort.assets/bubble_operation_step2.png index a06241fa..ad6f69f1 100644 Binary files a/docs/chapter_sorting/bubble_sort.assets/bubble_operation_step2.png and b/docs/chapter_sorting/bubble_sort.assets/bubble_operation_step2.png differ diff --git a/docs/chapter_sorting/bubble_sort.assets/bubble_operation_step3.png b/docs/chapter_sorting/bubble_sort.assets/bubble_operation_step3.png index a15f1fdc..d8b521d1 100644 Binary files a/docs/chapter_sorting/bubble_sort.assets/bubble_operation_step3.png and b/docs/chapter_sorting/bubble_sort.assets/bubble_operation_step3.png differ diff --git a/docs/chapter_sorting/bubble_sort.assets/bubble_operation_step4.png b/docs/chapter_sorting/bubble_sort.assets/bubble_operation_step4.png index 53b333e5..31865cbe 100644 Binary files a/docs/chapter_sorting/bubble_sort.assets/bubble_operation_step4.png and b/docs/chapter_sorting/bubble_sort.assets/bubble_operation_step4.png differ diff --git a/docs/chapter_sorting/bubble_sort.assets/bubble_operation_step5.png b/docs/chapter_sorting/bubble_sort.assets/bubble_operation_step5.png index 635498e9..6a07b46e 100644 Binary files a/docs/chapter_sorting/bubble_sort.assets/bubble_operation_step5.png and b/docs/chapter_sorting/bubble_sort.assets/bubble_operation_step5.png differ diff --git a/docs/chapter_sorting/bubble_sort.assets/bubble_operation_step6.png b/docs/chapter_sorting/bubble_sort.assets/bubble_operation_step6.png index 4fced66e..7fa2eaf7 100644 Binary files a/docs/chapter_sorting/bubble_sort.assets/bubble_operation_step6.png and b/docs/chapter_sorting/bubble_sort.assets/bubble_operation_step6.png differ diff --git a/docs/chapter_sorting/bubble_sort.assets/bubble_operation_step7.png b/docs/chapter_sorting/bubble_sort.assets/bubble_operation_step7.png index db9d8817..552e9f95 100644 Binary files a/docs/chapter_sorting/bubble_sort.assets/bubble_operation_step7.png and b/docs/chapter_sorting/bubble_sort.assets/bubble_operation_step7.png differ diff --git a/docs/chapter_sorting/bubble_sort.assets/bubble_sort_overview.png b/docs/chapter_sorting/bubble_sort.assets/bubble_sort_overview.png index 85554c9e..746ec6e8 100644 Binary files a/docs/chapter_sorting/bubble_sort.assets/bubble_sort_overview.png and b/docs/chapter_sorting/bubble_sort.assets/bubble_sort_overview.png differ diff --git a/docs/chapter_sorting/bucket_sort.assets/bucket_sort_overview.png b/docs/chapter_sorting/bucket_sort.assets/bucket_sort_overview.png index b4e11b02..4fc4768a 100644 Binary files a/docs/chapter_sorting/bucket_sort.assets/bucket_sort_overview.png and b/docs/chapter_sorting/bucket_sort.assets/bucket_sort_overview.png differ diff --git a/docs/chapter_sorting/bucket_sort.assets/scatter_in_buckets_distribution.png b/docs/chapter_sorting/bucket_sort.assets/scatter_in_buckets_distribution.png index f79c3733..07547112 100644 Binary files a/docs/chapter_sorting/bucket_sort.assets/scatter_in_buckets_distribution.png and b/docs/chapter_sorting/bucket_sort.assets/scatter_in_buckets_distribution.png differ diff --git a/docs/chapter_sorting/bucket_sort.assets/scatter_in_buckets_recursively.png b/docs/chapter_sorting/bucket_sort.assets/scatter_in_buckets_recursively.png index e7d34f64..c08598de 100644 Binary files a/docs/chapter_sorting/bucket_sort.assets/scatter_in_buckets_recursively.png and b/docs/chapter_sorting/bucket_sort.assets/scatter_in_buckets_recursively.png differ diff --git a/docs/chapter_sorting/bucket_sort.md b/docs/chapter_sorting/bucket_sort.md index 918c3a17..2a3e6784 100644 --- a/docs/chapter_sorting/bucket_sort.md +++ b/docs/chapter_sorting/bucket_sort.md @@ -92,7 +92,7 @@ 桶排序的时间复杂度理论上可以达到 $O(n)$ ,**难点是需要将元素均匀分配到各个桶中**,因为现实中的数据往往都不是均匀分布的。举个例子,假设我们想要把淘宝的所有商品根据价格范围平均分配到 10 个桶中,然而商品价格不是均匀分布的,100 元以下非常多、1000 元以上非常少;如果我们将价格区间平均划为 10 份,那么各个桶内的商品数量差距会非常大。 -为了实现平均分配,我们可以先大致设置一个分界线,将数据粗略分到 3 个桶,分配完后,**再把商品较多的桶继续划分为 3 个桶,直至所有桶内元素数量大致平均为止**。此方法本质上是生成一个递归树,让叶结点的值尽量平均。当然,不一定非要划分为 3 个桶,可以根据数据特点灵活选取。 +为了实现平均分配,我们可以先大致设置一个分界线,将数据粗略分到 3 个桶,分配完后,**再把商品较多的桶继续划分为 3 个桶,直至所有桶内元素数量大致平均为止**。此方法本质上是生成一个递归树,让叶节点的值尽量平均。当然,不一定非要划分为 3 个桶,可以根据数据特点灵活选取。 ![递归划分桶](bucket_sort.assets/scatter_in_buckets_recursively.png) diff --git a/docs/chapter_sorting/counting_sort.assets/counting_sort_overview.png b/docs/chapter_sorting/counting_sort.assets/counting_sort_overview.png index eb5708b2..9c893744 100644 Binary files a/docs/chapter_sorting/counting_sort.assets/counting_sort_overview.png and b/docs/chapter_sorting/counting_sort.assets/counting_sort_overview.png differ diff --git a/docs/chapter_sorting/counting_sort.assets/counting_sort_step1.png b/docs/chapter_sorting/counting_sort.assets/counting_sort_step1.png index 02bc0d53..29070a50 100644 Binary files a/docs/chapter_sorting/counting_sort.assets/counting_sort_step1.png and b/docs/chapter_sorting/counting_sort.assets/counting_sort_step1.png differ diff --git a/docs/chapter_sorting/counting_sort.assets/counting_sort_step2.png b/docs/chapter_sorting/counting_sort.assets/counting_sort_step2.png index 49820082..24baf6f0 100644 Binary files a/docs/chapter_sorting/counting_sort.assets/counting_sort_step2.png and b/docs/chapter_sorting/counting_sort.assets/counting_sort_step2.png differ diff --git a/docs/chapter_sorting/counting_sort.assets/counting_sort_step3.png b/docs/chapter_sorting/counting_sort.assets/counting_sort_step3.png index 40886ecf..bee79d9f 100644 Binary files a/docs/chapter_sorting/counting_sort.assets/counting_sort_step3.png and b/docs/chapter_sorting/counting_sort.assets/counting_sort_step3.png differ diff --git a/docs/chapter_sorting/counting_sort.assets/counting_sort_step4.png b/docs/chapter_sorting/counting_sort.assets/counting_sort_step4.png index 96ee248f..9b5625ee 100644 Binary files a/docs/chapter_sorting/counting_sort.assets/counting_sort_step4.png and b/docs/chapter_sorting/counting_sort.assets/counting_sort_step4.png differ diff --git a/docs/chapter_sorting/counting_sort.assets/counting_sort_step5.png b/docs/chapter_sorting/counting_sort.assets/counting_sort_step5.png index 5dd52aa1..2f3d8434 100644 Binary files a/docs/chapter_sorting/counting_sort.assets/counting_sort_step5.png and b/docs/chapter_sorting/counting_sort.assets/counting_sort_step5.png differ diff --git a/docs/chapter_sorting/counting_sort.assets/counting_sort_step6.png b/docs/chapter_sorting/counting_sort.assets/counting_sort_step6.png index b6128f1b..009ecdf0 100644 Binary files a/docs/chapter_sorting/counting_sort.assets/counting_sort_step6.png and b/docs/chapter_sorting/counting_sort.assets/counting_sort_step6.png differ diff --git a/docs/chapter_sorting/counting_sort.assets/counting_sort_step7.png b/docs/chapter_sorting/counting_sort.assets/counting_sort_step7.png index 32508c23..8819621b 100644 Binary files a/docs/chapter_sorting/counting_sort.assets/counting_sort_step7.png and b/docs/chapter_sorting/counting_sort.assets/counting_sort_step7.png differ diff --git a/docs/chapter_sorting/counting_sort.assets/counting_sort_step8.png b/docs/chapter_sorting/counting_sort.assets/counting_sort_step8.png index 003865f6..5118ab4a 100644 Binary files a/docs/chapter_sorting/counting_sort.assets/counting_sort_step8.png and b/docs/chapter_sorting/counting_sort.assets/counting_sort_step8.png differ diff --git a/docs/chapter_sorting/insertion_sort.assets/insertion_operation.png b/docs/chapter_sorting/insertion_sort.assets/insertion_operation.png index 7a1c6dfb..0a68d20b 100644 Binary files a/docs/chapter_sorting/insertion_sort.assets/insertion_operation.png and b/docs/chapter_sorting/insertion_sort.assets/insertion_operation.png differ diff --git a/docs/chapter_sorting/insertion_sort.assets/insertion_sort_overview.png b/docs/chapter_sorting/insertion_sort.assets/insertion_sort_overview.png index 378080e2..ebb20d07 100644 Binary files a/docs/chapter_sorting/insertion_sort.assets/insertion_sort_overview.png and b/docs/chapter_sorting/insertion_sort.assets/insertion_sort_overview.png differ diff --git a/docs/chapter_sorting/intro_to_sort.assets/sorting_examples.png b/docs/chapter_sorting/intro_to_sort.assets/sorting_examples.png index dfcf5ce7..997d067d 100644 Binary files a/docs/chapter_sorting/intro_to_sort.assets/sorting_examples.png and b/docs/chapter_sorting/intro_to_sort.assets/sorting_examples.png differ diff --git a/docs/chapter_sorting/merge_sort.assets/merge_sort_overview.png b/docs/chapter_sorting/merge_sort.assets/merge_sort_overview.png index 70add09d..420a2b70 100644 Binary files a/docs/chapter_sorting/merge_sort.assets/merge_sort_overview.png and b/docs/chapter_sorting/merge_sort.assets/merge_sort_overview.png differ diff --git a/docs/chapter_sorting/merge_sort.assets/merge_sort_step1.png b/docs/chapter_sorting/merge_sort.assets/merge_sort_step1.png index 2e290878..5dea7ec5 100644 Binary files a/docs/chapter_sorting/merge_sort.assets/merge_sort_step1.png and b/docs/chapter_sorting/merge_sort.assets/merge_sort_step1.png differ diff --git a/docs/chapter_sorting/merge_sort.assets/merge_sort_step10.png b/docs/chapter_sorting/merge_sort.assets/merge_sort_step10.png index f67b4d70..ba7e0f47 100644 Binary files a/docs/chapter_sorting/merge_sort.assets/merge_sort_step10.png and b/docs/chapter_sorting/merge_sort.assets/merge_sort_step10.png differ diff --git a/docs/chapter_sorting/merge_sort.assets/merge_sort_step2.png b/docs/chapter_sorting/merge_sort.assets/merge_sort_step2.png index 926070e2..fdc31fb5 100644 Binary files a/docs/chapter_sorting/merge_sort.assets/merge_sort_step2.png and b/docs/chapter_sorting/merge_sort.assets/merge_sort_step2.png differ diff --git a/docs/chapter_sorting/merge_sort.assets/merge_sort_step3.png b/docs/chapter_sorting/merge_sort.assets/merge_sort_step3.png index 78ecb46f..0635b837 100644 Binary files a/docs/chapter_sorting/merge_sort.assets/merge_sort_step3.png and b/docs/chapter_sorting/merge_sort.assets/merge_sort_step3.png differ diff --git a/docs/chapter_sorting/merge_sort.assets/merge_sort_step4.png b/docs/chapter_sorting/merge_sort.assets/merge_sort_step4.png index 22ac4651..c97e15f0 100644 Binary files a/docs/chapter_sorting/merge_sort.assets/merge_sort_step4.png and b/docs/chapter_sorting/merge_sort.assets/merge_sort_step4.png differ diff --git a/docs/chapter_sorting/merge_sort.assets/merge_sort_step5.png b/docs/chapter_sorting/merge_sort.assets/merge_sort_step5.png index e89fbe22..a12eb844 100644 Binary files a/docs/chapter_sorting/merge_sort.assets/merge_sort_step5.png and b/docs/chapter_sorting/merge_sort.assets/merge_sort_step5.png differ diff --git a/docs/chapter_sorting/merge_sort.assets/merge_sort_step6.png b/docs/chapter_sorting/merge_sort.assets/merge_sort_step6.png index bfa73328..c37525ec 100644 Binary files a/docs/chapter_sorting/merge_sort.assets/merge_sort_step6.png and b/docs/chapter_sorting/merge_sort.assets/merge_sort_step6.png differ diff --git a/docs/chapter_sorting/merge_sort.assets/merge_sort_step7.png b/docs/chapter_sorting/merge_sort.assets/merge_sort_step7.png index 6f9b4e47..171e2790 100644 Binary files a/docs/chapter_sorting/merge_sort.assets/merge_sort_step7.png and b/docs/chapter_sorting/merge_sort.assets/merge_sort_step7.png differ diff --git a/docs/chapter_sorting/merge_sort.assets/merge_sort_step8.png b/docs/chapter_sorting/merge_sort.assets/merge_sort_step8.png index 4287f044..236fb68d 100644 Binary files a/docs/chapter_sorting/merge_sort.assets/merge_sort_step8.png and b/docs/chapter_sorting/merge_sort.assets/merge_sort_step8.png differ diff --git a/docs/chapter_sorting/merge_sort.assets/merge_sort_step9.png b/docs/chapter_sorting/merge_sort.assets/merge_sort_step9.png index 2d17a932..c3c741fc 100644 Binary files a/docs/chapter_sorting/merge_sort.assets/merge_sort_step9.png and b/docs/chapter_sorting/merge_sort.assets/merge_sort_step9.png differ diff --git a/docs/chapter_sorting/merge_sort.md b/docs/chapter_sorting/merge_sort.md index 52c4c683..39d7d957 100755 --- a/docs/chapter_sorting/merge_sort.md +++ b/docs/chapter_sorting/merge_sort.md @@ -50,7 +50,7 @@ 观察发现,归并排序的递归顺序就是二叉树的「后序遍历」。 -- **后序遍历**:先递归左子树、再递归右子树、最后处理根结点。 +- **后序遍历**:先递归左子树、再递归右子树、最后处理根节点。 - **归并排序**:先递归左子树、再递归右子树、最后处理合并。 === "Java" @@ -154,7 +154,7 @@ 归并排序有一个很特别的优势,用于排序链表时有很好的性能表现,**空间复杂度可被优化至 $O(1)$** ,这是因为: -- 由于链表可仅通过改变指针来实现结点增删,因此“将两个短有序链表合并为一个长有序链表”无需使用额外空间,即回溯合并阶段不用像排序数组一样建立辅助数组 `tmp` ; +- 由于链表可仅通过改变指针来实现节点增删,因此“将两个短有序链表合并为一个长有序链表”无需使用额外空间,即回溯合并阶段不用像排序数组一样建立辅助数组 `tmp` ; - 通过使用「迭代」代替「递归划分」,可省去递归使用的栈帧空间; > 详情参考:[148. 排序链表](https://leetcode-cn.com/problems/sort-list/solution/sort-list-gui-bing-pai-xu-lian-biao-by-jyd/) diff --git a/docs/chapter_sorting/quick_sort.assets/pivot_division_step1.png b/docs/chapter_sorting/quick_sort.assets/pivot_division_step1.png index dc2bf85d..2de33457 100644 Binary files a/docs/chapter_sorting/quick_sort.assets/pivot_division_step1.png and b/docs/chapter_sorting/quick_sort.assets/pivot_division_step1.png differ diff --git a/docs/chapter_sorting/quick_sort.assets/pivot_division_step2.png b/docs/chapter_sorting/quick_sort.assets/pivot_division_step2.png index ee2ca0b2..d0668ea0 100644 Binary files a/docs/chapter_sorting/quick_sort.assets/pivot_division_step2.png and b/docs/chapter_sorting/quick_sort.assets/pivot_division_step2.png differ diff --git a/docs/chapter_sorting/quick_sort.assets/pivot_division_step3.png b/docs/chapter_sorting/quick_sort.assets/pivot_division_step3.png index f7125e23..53f555bf 100644 Binary files a/docs/chapter_sorting/quick_sort.assets/pivot_division_step3.png and b/docs/chapter_sorting/quick_sort.assets/pivot_division_step3.png differ diff --git a/docs/chapter_sorting/quick_sort.assets/pivot_division_step4.png b/docs/chapter_sorting/quick_sort.assets/pivot_division_step4.png index 4629b9ec..b962d868 100644 Binary files a/docs/chapter_sorting/quick_sort.assets/pivot_division_step4.png and b/docs/chapter_sorting/quick_sort.assets/pivot_division_step4.png differ diff --git a/docs/chapter_sorting/quick_sort.assets/pivot_division_step5.png b/docs/chapter_sorting/quick_sort.assets/pivot_division_step5.png index 25734069..f805171e 100644 Binary files a/docs/chapter_sorting/quick_sort.assets/pivot_division_step5.png and b/docs/chapter_sorting/quick_sort.assets/pivot_division_step5.png differ diff --git a/docs/chapter_sorting/quick_sort.assets/pivot_division_step6.png b/docs/chapter_sorting/quick_sort.assets/pivot_division_step6.png index 9edce956..ef1c5192 100644 Binary files a/docs/chapter_sorting/quick_sort.assets/pivot_division_step6.png and b/docs/chapter_sorting/quick_sort.assets/pivot_division_step6.png differ diff --git a/docs/chapter_sorting/quick_sort.assets/pivot_division_step7.png b/docs/chapter_sorting/quick_sort.assets/pivot_division_step7.png index 3efdd6c0..cb18664b 100644 Binary files a/docs/chapter_sorting/quick_sort.assets/pivot_division_step7.png and b/docs/chapter_sorting/quick_sort.assets/pivot_division_step7.png differ diff --git a/docs/chapter_sorting/quick_sort.assets/pivot_division_step8.png b/docs/chapter_sorting/quick_sort.assets/pivot_division_step8.png index 206cb81f..38e7365f 100644 Binary files a/docs/chapter_sorting/quick_sort.assets/pivot_division_step8.png and b/docs/chapter_sorting/quick_sort.assets/pivot_division_step8.png differ diff --git a/docs/chapter_sorting/quick_sort.assets/pivot_division_step9.png b/docs/chapter_sorting/quick_sort.assets/pivot_division_step9.png index 706fd154..c0e950d4 100644 Binary files a/docs/chapter_sorting/quick_sort.assets/pivot_division_step9.png and b/docs/chapter_sorting/quick_sort.assets/pivot_division_step9.png differ diff --git a/docs/chapter_sorting/quick_sort.assets/quick_sort_overview.png b/docs/chapter_sorting/quick_sort.assets/quick_sort_overview.png index db3c7b75..39787f0a 100644 Binary files a/docs/chapter_sorting/quick_sort.assets/quick_sort_overview.png and b/docs/chapter_sorting/quick_sort.assets/quick_sort_overview.png differ diff --git a/docs/chapter_sorting/radix_sort.assets/radix_sort_overview.png b/docs/chapter_sorting/radix_sort.assets/radix_sort_overview.png index a88b53ad..c92b184c 100644 Binary files a/docs/chapter_sorting/radix_sort.assets/radix_sort_overview.png and b/docs/chapter_sorting/radix_sort.assets/radix_sort_overview.png differ diff --git a/docs/chapter_sorting/summary.assets/sorting_algorithms_comparison.png b/docs/chapter_sorting/summary.assets/sorting_algorithms_comparison.png index 5c11896a..2ff2877c 100644 Binary files a/docs/chapter_sorting/summary.assets/sorting_algorithms_comparison.png and b/docs/chapter_sorting/summary.assets/sorting_algorithms_comparison.png differ diff --git a/docs/chapter_stack_and_queue/deque.assets/array_deque.png b/docs/chapter_stack_and_queue/deque.assets/array_deque.png index 3ef1c288..8cec6521 100644 Binary files a/docs/chapter_stack_and_queue/deque.assets/array_deque.png and b/docs/chapter_stack_and_queue/deque.assets/array_deque.png differ diff --git a/docs/chapter_stack_and_queue/deque.assets/array_deque_pop_first.png b/docs/chapter_stack_and_queue/deque.assets/array_deque_pop_first.png index 8137d016..2d89de3d 100644 Binary files a/docs/chapter_stack_and_queue/deque.assets/array_deque_pop_first.png and b/docs/chapter_stack_and_queue/deque.assets/array_deque_pop_first.png differ diff --git a/docs/chapter_stack_and_queue/deque.assets/array_deque_pop_last.png b/docs/chapter_stack_and_queue/deque.assets/array_deque_pop_last.png index 7c759310..a31edef8 100644 Binary files a/docs/chapter_stack_and_queue/deque.assets/array_deque_pop_last.png and b/docs/chapter_stack_and_queue/deque.assets/array_deque_pop_last.png differ diff --git a/docs/chapter_stack_and_queue/deque.assets/array_deque_push_first.png b/docs/chapter_stack_and_queue/deque.assets/array_deque_push_first.png index 04120335..cfb02a3c 100644 Binary files a/docs/chapter_stack_and_queue/deque.assets/array_deque_push_first.png and b/docs/chapter_stack_and_queue/deque.assets/array_deque_push_first.png differ diff --git a/docs/chapter_stack_and_queue/deque.assets/array_deque_push_last.png b/docs/chapter_stack_and_queue/deque.assets/array_deque_push_last.png index 33816de8..ef071a3c 100644 Binary files a/docs/chapter_stack_and_queue/deque.assets/array_deque_push_last.png and b/docs/chapter_stack_and_queue/deque.assets/array_deque_push_last.png differ diff --git a/docs/chapter_stack_and_queue/deque.assets/deque_operations.png b/docs/chapter_stack_and_queue/deque.assets/deque_operations.png index da8e03c0..b8c7ba48 100644 Binary files a/docs/chapter_stack_and_queue/deque.assets/deque_operations.png and b/docs/chapter_stack_and_queue/deque.assets/deque_operations.png differ diff --git a/docs/chapter_stack_and_queue/deque.assets/linkedlist_deque.png b/docs/chapter_stack_and_queue/deque.assets/linkedlist_deque.png index 407bd620..d03a6215 100644 Binary files a/docs/chapter_stack_and_queue/deque.assets/linkedlist_deque.png and b/docs/chapter_stack_and_queue/deque.assets/linkedlist_deque.png differ diff --git a/docs/chapter_stack_and_queue/deque.assets/linkedlist_deque_pop_first.png b/docs/chapter_stack_and_queue/deque.assets/linkedlist_deque_pop_first.png index 22bb8630..d5da2e72 100644 Binary files a/docs/chapter_stack_and_queue/deque.assets/linkedlist_deque_pop_first.png and b/docs/chapter_stack_and_queue/deque.assets/linkedlist_deque_pop_first.png differ diff --git a/docs/chapter_stack_and_queue/deque.assets/linkedlist_deque_pop_last.png b/docs/chapter_stack_and_queue/deque.assets/linkedlist_deque_pop_last.png index f05b270f..39c53bfc 100644 Binary files a/docs/chapter_stack_and_queue/deque.assets/linkedlist_deque_pop_last.png and b/docs/chapter_stack_and_queue/deque.assets/linkedlist_deque_pop_last.png differ diff --git a/docs/chapter_stack_and_queue/deque.assets/linkedlist_deque_push_first.png b/docs/chapter_stack_and_queue/deque.assets/linkedlist_deque_push_first.png index 2f0d0e53..a170d5c8 100644 Binary files a/docs/chapter_stack_and_queue/deque.assets/linkedlist_deque_push_first.png and b/docs/chapter_stack_and_queue/deque.assets/linkedlist_deque_push_first.png differ diff --git a/docs/chapter_stack_and_queue/deque.assets/linkedlist_deque_push_last.png b/docs/chapter_stack_and_queue/deque.assets/linkedlist_deque_push_last.png index 811cb97c..4d1e710e 100644 Binary files a/docs/chapter_stack_and_queue/deque.assets/linkedlist_deque_push_last.png and b/docs/chapter_stack_and_queue/deque.assets/linkedlist_deque_push_last.png differ diff --git a/docs/chapter_stack_and_queue/deque.md b/docs/chapter_stack_and_queue/deque.md index c5b39e77..d888d64d 100644 --- a/docs/chapter_stack_and_queue/deque.md +++ b/docs/chapter_stack_and_queue/deque.md @@ -289,11 +289,11 @@ ### 基于双向链表的实现 -回忆上节内容,由于可以方便地删除链表头结点(对应出队操作),以及在链表尾结点后添加新结点(对应入队操作),因此我们使用普通单向链表来实现队列。 +回忆上节内容,由于可以方便地删除链表头节点(对应出队操作),以及在链表尾节点后添加新节点(对应入队操作),因此我们使用普通单向链表来实现队列。 而双向队列的头部和尾部都可以执行入队与出队操作,换言之,双向队列的操作是“首尾对称”的,也需要实现另一个对称方向的操作。因此,双向队列需要使用「双向链表」来实现。 -我们将双向链表的头结点和尾结点分别看作双向队列的队首和队尾,并且实现在两端都能添加与删除结点。 +我们将双向链表的头节点和尾节点分别看作双向队列的队首和队尾,并且实现在两端都能添加与删除节点。 === "LinkedListDeque" ![基于链表实现双向队列的入队出队操作](deque.assets/linkedlist_deque.png) diff --git a/docs/chapter_stack_and_queue/queue.assets/array_queue.png b/docs/chapter_stack_and_queue/queue.assets/array_queue.png index e4e17d03..3ee9812c 100644 Binary files a/docs/chapter_stack_and_queue/queue.assets/array_queue.png and b/docs/chapter_stack_and_queue/queue.assets/array_queue.png differ diff --git a/docs/chapter_stack_and_queue/queue.assets/array_queue_pop.png b/docs/chapter_stack_and_queue/queue.assets/array_queue_pop.png index 3cfb3b42..b3540fdb 100644 Binary files a/docs/chapter_stack_and_queue/queue.assets/array_queue_pop.png and b/docs/chapter_stack_and_queue/queue.assets/array_queue_pop.png differ diff --git a/docs/chapter_stack_and_queue/queue.assets/array_queue_push.png b/docs/chapter_stack_and_queue/queue.assets/array_queue_push.png index b1926ab7..d4c661d4 100644 Binary files a/docs/chapter_stack_and_queue/queue.assets/array_queue_push.png and b/docs/chapter_stack_and_queue/queue.assets/array_queue_push.png differ diff --git a/docs/chapter_stack_and_queue/queue.assets/linkedlist_queue.png b/docs/chapter_stack_and_queue/queue.assets/linkedlist_queue.png index 160d781b..a3e0e2ed 100644 Binary files a/docs/chapter_stack_and_queue/queue.assets/linkedlist_queue.png and b/docs/chapter_stack_and_queue/queue.assets/linkedlist_queue.png differ diff --git a/docs/chapter_stack_and_queue/queue.assets/linkedlist_queue_pop.png b/docs/chapter_stack_and_queue/queue.assets/linkedlist_queue_pop.png index f964e460..9b8d5481 100644 Binary files a/docs/chapter_stack_and_queue/queue.assets/linkedlist_queue_pop.png and b/docs/chapter_stack_and_queue/queue.assets/linkedlist_queue_pop.png differ diff --git a/docs/chapter_stack_and_queue/queue.assets/linkedlist_queue_push.png b/docs/chapter_stack_and_queue/queue.assets/linkedlist_queue_push.png index baebb145..f80bb7e7 100644 Binary files a/docs/chapter_stack_and_queue/queue.assets/linkedlist_queue_push.png and b/docs/chapter_stack_and_queue/queue.assets/linkedlist_queue_push.png differ diff --git a/docs/chapter_stack_and_queue/queue.assets/queue_operations.png b/docs/chapter_stack_and_queue/queue.assets/queue_operations.png index 80bb031c..b57372d9 100644 Binary files a/docs/chapter_stack_and_queue/queue.assets/queue_operations.png and b/docs/chapter_stack_and_queue/queue.assets/queue_operations.png differ diff --git a/docs/chapter_stack_and_queue/queue.md b/docs/chapter_stack_and_queue/queue.md index b88c9168..d7f9c934 100755 --- a/docs/chapter_stack_and_queue/queue.md +++ b/docs/chapter_stack_and_queue/queue.md @@ -258,7 +258,7 @@ ### 基于链表的实现 -我们将链表的「头结点」和「尾结点」分别看作是队首和队尾,并规定队尾只可添加结点,队首只可删除结点。 +我们将链表的「头节点」和「尾节点」分别看作是队首和队尾,并规定队尾只可添加节点,队首只可删除节点。 === "LinkedListQueue" ![基于链表实现队列的入队出队操作](queue.assets/linkedlist_queue.png) diff --git a/docs/chapter_stack_and_queue/stack.assets/array_stack.png b/docs/chapter_stack_and_queue/stack.assets/array_stack.png index 9667bba6..c422b92f 100644 Binary files a/docs/chapter_stack_and_queue/stack.assets/array_stack.png and b/docs/chapter_stack_and_queue/stack.assets/array_stack.png differ diff --git a/docs/chapter_stack_and_queue/stack.assets/array_stack_pop.png b/docs/chapter_stack_and_queue/stack.assets/array_stack_pop.png index e846ae81..3377d162 100644 Binary files a/docs/chapter_stack_and_queue/stack.assets/array_stack_pop.png and b/docs/chapter_stack_and_queue/stack.assets/array_stack_pop.png differ diff --git a/docs/chapter_stack_and_queue/stack.assets/array_stack_push.png b/docs/chapter_stack_and_queue/stack.assets/array_stack_push.png index ba8a11f2..79cd2425 100644 Binary files a/docs/chapter_stack_and_queue/stack.assets/array_stack_push.png and b/docs/chapter_stack_and_queue/stack.assets/array_stack_push.png differ diff --git a/docs/chapter_stack_and_queue/stack.assets/linkedlist_stack.png b/docs/chapter_stack_and_queue/stack.assets/linkedlist_stack.png index f1149347..03cbda28 100644 Binary files a/docs/chapter_stack_and_queue/stack.assets/linkedlist_stack.png and b/docs/chapter_stack_and_queue/stack.assets/linkedlist_stack.png differ diff --git a/docs/chapter_stack_and_queue/stack.assets/linkedlist_stack_pop.png b/docs/chapter_stack_and_queue/stack.assets/linkedlist_stack_pop.png index fc7babba..45c61709 100644 Binary files a/docs/chapter_stack_and_queue/stack.assets/linkedlist_stack_pop.png and b/docs/chapter_stack_and_queue/stack.assets/linkedlist_stack_pop.png differ diff --git a/docs/chapter_stack_and_queue/stack.assets/linkedlist_stack_push.png b/docs/chapter_stack_and_queue/stack.assets/linkedlist_stack_push.png index 71bc925e..7df0c77e 100644 Binary files a/docs/chapter_stack_and_queue/stack.assets/linkedlist_stack_push.png and b/docs/chapter_stack_and_queue/stack.assets/linkedlist_stack_push.png differ diff --git a/docs/chapter_stack_and_queue/stack.assets/stack_operations.png b/docs/chapter_stack_and_queue/stack.assets/stack_operations.png index 945d0fe8..2173d944 100644 Binary files a/docs/chapter_stack_and_queue/stack.assets/stack_operations.png and b/docs/chapter_stack_and_queue/stack.assets/stack_operations.png differ diff --git a/docs/chapter_stack_and_queue/stack.md b/docs/chapter_stack_and_queue/stack.md index 5a4cc85d..0ea89ea6 100755 --- a/docs/chapter_stack_and_queue/stack.md +++ b/docs/chapter_stack_and_queue/stack.md @@ -258,9 +258,9 @@ ### 基于链表的实现 -使用「链表」实现栈时,将链表的头结点看作栈顶,将尾结点看作栈底。 +使用「链表」实现栈时,将链表的头节点看作栈顶,将尾节点看作栈底。 -对于入栈操作,将元素插入到链表头部即可,这种结点添加方式被称为“头插法”。而对于出栈操作,则将头结点从链表中删除即可。 +对于入栈操作,将元素插入到链表头部即可,这种节点添加方式被称为“头插法”。而对于出栈操作,则将头节点从链表中删除即可。 === "LinkedListStack" ![基于链表实现栈的入栈出栈操作](stack.assets/linkedlist_stack.png) @@ -418,7 +418,7 @@ 在数组(列表)实现中,入栈与出栈操作都是在预先分配好的连续内存中操作,具有很好的缓存本地性,效率很好。然而,如果入栈时超出数组容量,则会触发扩容机制,那么该次入栈操作的时间复杂度为 $O(n)$ 。 -在链表实现中,链表的扩容非常灵活,不存在上述数组扩容时变慢的问题。然而,入栈操作需要初始化结点对象并修改指针,因而效率不如数组。进一步地思考,如果入栈元素不是 `int` 而是结点对象,那么就可以省去初始化步骤,从而提升效率。 +在链表实现中,链表的扩容非常灵活,不存在上述数组扩容时变慢的问题。然而,入栈操作需要初始化节点对象并修改指针,因而效率不如数组。进一步地思考,如果入栈元素不是 `int` 而是节点对象,那么就可以省去初始化步骤,从而提升效率。 综上所述,当入栈与出栈操作的元素是基本数据类型(例如 `int` , `double` )时,则结论如下: @@ -429,7 +429,7 @@ 在初始化列表时,系统会给列表分配“初始容量”,该容量可能超过我们的需求。并且扩容机制一般是按照特定倍率(比如 2 倍)进行扩容,扩容后的容量也可能超出我们的需求。因此,**数组实现栈会造成一定的空间浪费**。 -当然,由于结点需要额外存储指针,因此 **链表结点比数组元素占用更大**。 +当然,由于节点需要额外存储指针,因此 **链表节点比数组元素占用更大**。 综上,我们不能简单地确定哪种实现更加省内存,需要 case-by-case 地分析。 diff --git a/docs/chapter_stack_and_queue/summary.md b/docs/chapter_stack_and_queue/summary.md index 1e13b6e1..787ca66f 100644 --- a/docs/chapter_stack_and_queue/summary.md +++ b/docs/chapter_stack_and_queue/summary.md @@ -2,6 +2,6 @@ - 栈是一种遵循先入后出的数据结构,可以使用数组或链表实现。 - 在时间效率方面,栈的数组实现具有更好的平均效率,但扩容时会导致单次入栈操作的时间复杂度劣化至 $O(n)$ 。相对地,栈的链表实现具有更加稳定的效率表现。 -- 在空间效率方面,栈的数组实现会造成一定空间浪费,然而链表结点比数组元素占用内存更大。 +- 在空间效率方面,栈的数组实现会造成一定空间浪费,然而链表节点比数组元素占用内存更大。 - 队列是一种遵循先入先出的数据结构,可以使用数组或链表实现。对于两种实现的时间效率与空间效率对比,与上述栈的结论相同。 - 双向队列的两端都可以添加与删除元素。 diff --git a/docs/chapter_tree/avl_tree.assets/avltree_degradation_from_inserting_node.png b/docs/chapter_tree/avl_tree.assets/avltree_degradation_from_inserting_node.png index c28d5b74..15080808 100644 Binary files a/docs/chapter_tree/avl_tree.assets/avltree_degradation_from_inserting_node.png and b/docs/chapter_tree/avl_tree.assets/avltree_degradation_from_inserting_node.png differ diff --git a/docs/chapter_tree/avl_tree.assets/avltree_degradation_from_removing_node.png b/docs/chapter_tree/avl_tree.assets/avltree_degradation_from_removing_node.png index 19ecc6fe..1ba22fd8 100644 Binary files a/docs/chapter_tree/avl_tree.assets/avltree_degradation_from_removing_node.png and b/docs/chapter_tree/avl_tree.assets/avltree_degradation_from_removing_node.png differ diff --git a/docs/chapter_tree/avl_tree.assets/avltree_left_right_rotate.png b/docs/chapter_tree/avl_tree.assets/avltree_left_right_rotate.png index 5b37e598..02afb13f 100644 Binary files a/docs/chapter_tree/avl_tree.assets/avltree_left_right_rotate.png and b/docs/chapter_tree/avl_tree.assets/avltree_left_right_rotate.png differ diff --git a/docs/chapter_tree/avl_tree.assets/avltree_left_rotate.png b/docs/chapter_tree/avl_tree.assets/avltree_left_rotate.png index 199a7d45..0b4842bd 100644 Binary files a/docs/chapter_tree/avl_tree.assets/avltree_left_rotate.png and b/docs/chapter_tree/avl_tree.assets/avltree_left_rotate.png differ diff --git a/docs/chapter_tree/avl_tree.assets/avltree_left_rotate_with_grandchild.png b/docs/chapter_tree/avl_tree.assets/avltree_left_rotate_with_grandchild.png index cd6cdf3d..7c690fe2 100644 Binary files a/docs/chapter_tree/avl_tree.assets/avltree_left_rotate_with_grandchild.png and b/docs/chapter_tree/avl_tree.assets/avltree_left_rotate_with_grandchild.png differ diff --git a/docs/chapter_tree/avl_tree.assets/avltree_right_left_rotate.png b/docs/chapter_tree/avl_tree.assets/avltree_right_left_rotate.png index 846f1fce..ed18f651 100644 Binary files a/docs/chapter_tree/avl_tree.assets/avltree_right_left_rotate.png and b/docs/chapter_tree/avl_tree.assets/avltree_right_left_rotate.png differ diff --git a/docs/chapter_tree/avl_tree.assets/avltree_right_rotate_step1.png b/docs/chapter_tree/avl_tree.assets/avltree_right_rotate_step1.png index a010a8e2..dcee29fe 100644 Binary files a/docs/chapter_tree/avl_tree.assets/avltree_right_rotate_step1.png and b/docs/chapter_tree/avl_tree.assets/avltree_right_rotate_step1.png differ diff --git a/docs/chapter_tree/avl_tree.assets/avltree_right_rotate_step2.png b/docs/chapter_tree/avl_tree.assets/avltree_right_rotate_step2.png index 462bd576..fcc6ba87 100644 Binary files a/docs/chapter_tree/avl_tree.assets/avltree_right_rotate_step2.png and b/docs/chapter_tree/avl_tree.assets/avltree_right_rotate_step2.png differ diff --git a/docs/chapter_tree/avl_tree.assets/avltree_right_rotate_step3.png b/docs/chapter_tree/avl_tree.assets/avltree_right_rotate_step3.png index 0080b218..f0fce12c 100644 Binary files a/docs/chapter_tree/avl_tree.assets/avltree_right_rotate_step3.png and b/docs/chapter_tree/avl_tree.assets/avltree_right_rotate_step3.png differ diff --git a/docs/chapter_tree/avl_tree.assets/avltree_right_rotate_step4.png b/docs/chapter_tree/avl_tree.assets/avltree_right_rotate_step4.png index e3a5509c..41180815 100644 Binary files a/docs/chapter_tree/avl_tree.assets/avltree_right_rotate_step4.png and b/docs/chapter_tree/avl_tree.assets/avltree_right_rotate_step4.png differ diff --git a/docs/chapter_tree/avl_tree.assets/avltree_right_rotate_with_grandchild.png b/docs/chapter_tree/avl_tree.assets/avltree_right_rotate_with_grandchild.png index 65a89474..28273df7 100644 Binary files a/docs/chapter_tree/avl_tree.assets/avltree_right_rotate_with_grandchild.png and b/docs/chapter_tree/avl_tree.assets/avltree_right_rotate_with_grandchild.png differ diff --git a/docs/chapter_tree/avl_tree.assets/avltree_rotation_cases.png b/docs/chapter_tree/avl_tree.assets/avltree_rotation_cases.png index 2fb56b03..522683a9 100644 Binary files a/docs/chapter_tree/avl_tree.assets/avltree_rotation_cases.png and b/docs/chapter_tree/avl_tree.assets/avltree_rotation_cases.png differ diff --git a/docs/chapter_tree/avl_tree.md b/docs/chapter_tree/avl_tree.md index 7a077b70..a1596798 100644 --- a/docs/chapter_tree/avl_tree.md +++ b/docs/chapter_tree/avl_tree.md @@ -2,15 +2,15 @@ 在「二叉搜索树」章节中提到,在进行多次插入与删除操作后,二叉搜索树可能会退化为链表。此时所有操作的时间复杂度都会由 $O(\log n)$ 劣化至 $O(n)$ 。 -如下图所示,执行两步删除结点后,该二叉搜索树就会退化为链表。 +如下图所示,执行两步删除节点后,该二叉搜索树就会退化为链表。 -![AVL 树在删除结点后发生退化](avl_tree.assets/avltree_degradation_from_removing_node.png) +![AVL 树在删除节点后发生退化](avl_tree.assets/avltree_degradation_from_removing_node.png) -再比如,在以下完美二叉树中插入两个结点后,树严重向左偏斜,查找操作的时间复杂度也随之发生劣化。 +再比如,在以下完美二叉树中插入两个节点后,树严重向左偏斜,查找操作的时间复杂度也随之发生劣化。 -![AVL 树在插入结点后发生退化](avl_tree.assets/avltree_degradation_from_inserting_node.png) +![AVL 树在插入节点后发生退化](avl_tree.assets/avltree_degradation_from_inserting_node.png) -G. M. Adelson-Velsky 和 E. M. Landis 在其 1962 年发表的论文 "An algorithm for the organization of information" 中提出了「AVL 树」。**论文中描述了一系列操作,使得在不断添加与删除结点后,AVL 树仍然不会发生退化**,进而使得各种操作的时间复杂度均能保持在 $O(\log n)$ 级别。 +G. M. Adelson-Velsky 和 E. M. Landis 在其 1962 年发表的论文 "An algorithm for the organization of information" 中提出了「AVL 树」。**论文中描述了一系列操作,使得在不断添加与删除节点后,AVL 树仍然不会发生退化**,进而使得各种操作的时间复杂度均能保持在 $O(\log n)$ 级别。 换言之,在频繁增删查改的使用场景中,AVL 树可始终保持很高的数据增删查改效率,具有很好的应用价值。 @@ -18,19 +18,19 @@ G. M. Adelson-Velsky 和 E. M. Landis 在其 1962 年发表的论文 "An algorit 「AVL 树」既是「二叉搜索树」又是「平衡二叉树」,同时满足这两种二叉树的所有性质,因此又被称为「平衡二叉搜索树」。 -### 结点高度 +### 节点高度 -在 AVL 树的操作中,需要获取结点「高度 Height」,所以给 AVL 树的结点类添加 `height` 变量。 +在 AVL 树的操作中,需要获取节点「高度 Height」,所以给 AVL 树的节点类添加 `height` 变量。 === "Java" ```java title="" - /* AVL 树结点类 */ + /* AVL 树节点类 */ class TreeNode { - public int val; // 结点值 - public int height; // 结点高度 - public TreeNode left; // 左子结点 - public TreeNode right; // 右子结点 + public int val; // 节点值 + public int height; // 节点高度 + public TreeNode left; // 左子节点 + public TreeNode right; // 右子节点 public TreeNode(int x) { val = x; } } ``` @@ -38,12 +38,12 @@ G. M. Adelson-Velsky 和 E. M. Landis 在其 1962 年发表的论文 "An algorit === "C++" ```cpp title="" - /* AVL 树结点类 */ + /* AVL 树节点类 */ struct TreeNode { - int val{}; // 结点值 - int height = 0; // 结点高度 - TreeNode *left{}; // 左子结点 - TreeNode *right{}; // 右子结点 + int val{}; // 节点值 + int height = 0; // 节点高度 + TreeNode *left{}; // 左子节点 + TreeNode *right{}; // 右子节点 TreeNode() = default; explicit TreeNode(int x) : val(x){} }; @@ -52,24 +52,24 @@ G. M. Adelson-Velsky 和 E. M. Landis 在其 1962 年发表的论文 "An algorit === "Python" ```python title="" - """ AVL 树结点类 """ + """ AVL 树节点类 """ class TreeNode: def __init__(self, val: int): - self.val: int = val # 结点值 - self.height: int = 0 # 结点高度 - self.left: Optional[TreeNode] = None # 左子结点引用 - self.right: Optional[TreeNode] = None # 右子结点引用 + self.val: int = val # 节点值 + self.height: int = 0 # 节点高度 + self.left: Optional[TreeNode] = None # 左子节点引用 + self.right: Optional[TreeNode] = None # 右子节点引用 ``` === "Go" ```go title="" - /* AVL 树结点类 */ + /* AVL 树节点类 */ type TreeNode struct { - Val int // 结点值 - Height int // 结点高度 - Left *TreeNode // 左子结点引用 - Right *TreeNode // 右子结点引用 + Val int // 节点值 + Height int // 节点高度 + Left *TreeNode // 左子节点引用 + Right *TreeNode // 右子节点引用 } ``` @@ -77,10 +77,10 @@ G. M. Adelson-Velsky 和 E. M. Landis 在其 1962 年发表的论文 "An algorit ```javascript title="" class TreeNode { - val; // 结点值 - height; //结点高度 - left; // 左子结点指针 - right; // 右子结点指针 + val; // 节点值 + height; //节点高度 + left; // 左子节点指针 + right; // 右子节点指针 constructor(val, left, right, height) { this.val = val === undefined ? 0 : val; this.height = height === undefined ? 0 : height; @@ -94,10 +94,10 @@ G. M. Adelson-Velsky 和 E. M. Landis 在其 1962 年发表的论文 "An algorit ```typescript title="" class TreeNode { - val: number; // 结点值 - height: number; // 结点高度 - left: TreeNode | null; // 左子结点指针 - right: TreeNode | null; // 右子结点指针 + 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; @@ -116,12 +116,12 @@ G. M. Adelson-Velsky 和 E. M. Landis 在其 1962 年发表的论文 "An algorit === "C#" ```csharp title="" - /* AVL 树结点类 */ + /* AVL 树节点类 */ class TreeNode { - public int val; // 结点值 - public int height; // 结点高度 - public TreeNode? left; // 左子结点 - public TreeNode? right; // 右子结点 + public int val; // 节点值 + public int height; // 节点高度 + public TreeNode? left; // 左子节点 + public TreeNode? right; // 右子节点 public TreeNode(int x) { val = x; } } ``` @@ -129,12 +129,12 @@ G. M. Adelson-Velsky 和 E. M. Landis 在其 1962 年发表的论文 "An algorit === "Swift" ```swift title="" - /* AVL 树结点类 */ + /* AVL 树节点类 */ class TreeNode { - var val: Int // 结点值 - var height: Int // 结点高度 - var left: TreeNode? // 左子结点 - var right: TreeNode? // 右子结点 + var val: Int // 节点值 + var height: Int // 节点高度 + var left: TreeNode? // 左子节点 + var right: TreeNode? // 右子节点 init(x: Int) { val = x @@ -149,7 +149,7 @@ G. M. Adelson-Velsky 和 E. M. Landis 在其 1962 年发表的论文 "An algorit ``` -「结点高度」是最远叶结点到该结点的距离,即走过的「边」的数量。需要特别注意,**叶结点的高度为 0 ,空结点的高度为 -1**。我们封装两个工具函数,分别用于获取与更新结点的高度。 +「节点高度」是最远叶节点到该节点的距离,即走过的「边」的数量。需要特别注意,**叶节点的高度为 0 ,空节点的高度为 -1**。我们封装两个工具函数,分别用于获取与更新节点的高度。 === "Java" @@ -231,9 +231,9 @@ G. M. Adelson-Velsky 和 E. M. Landis 在其 1962 年发表的论文 "An algorit [class]{AVLTree}-[func]{updateHeight} ``` -### 结点平衡因子 +### 节点平衡因子 -结点的「平衡因子 Balance Factor」是 **结点的左子树高度减去右子树高度**,并定义空结点的平衡因子为 0 。同样地,我们将获取结点平衡因子封装成函数,以便后续使用。 +节点的「平衡因子 Balance Factor」是 **节点的左子树高度减去右子树高度**,并定义空节点的平衡因子为 0 。同样地,我们将获取节点平衡因子封装成函数,以便后续使用。 === "Java" @@ -297,17 +297,17 @@ G. M. Adelson-Velsky 和 E. M. Landis 在其 1962 年发表的论文 "An algorit !!! note - 设平衡因子为 $f$ ,则一棵 AVL 树的任意结点的平衡因子皆满足 $-1 \le f \le 1$ 。 + 设平衡因子为 $f$ ,则一棵 AVL 树的任意节点的平衡因子皆满足 $-1 \le f \le 1$ 。 ## AVL 树旋转 -AVL 树的独特之处在于「旋转 Rotation」的操作,其可 **在不影响二叉树中序遍历序列的前提下,使失衡结点重新恢复平衡**。换言之,旋转操作既可以使树保持为「二叉搜索树」,也可以使树重新恢复为「平衡二叉树」。 +AVL 树的独特之处在于「旋转 Rotation」的操作,其可 **在不影响二叉树中序遍历序列的前提下,使失衡节点重新恢复平衡**。换言之,旋转操作既可以使树保持为「二叉搜索树」,也可以使树重新恢复为「平衡二叉树」。 -我们将平衡因子的绝对值 $> 1$ 的结点称为「失衡结点」。根据结点的失衡情况,旋转操作分为 **右旋、左旋、先右旋后左旋、先左旋后右旋**,接下来我们来一起来看看它们是如何操作的。 +我们将平衡因子的绝对值 $> 1$ 的节点称为「失衡节点」。根据节点的失衡情况,旋转操作分为 **右旋、左旋、先右旋后左旋、先左旋后右旋**,接下来我们来一起来看看它们是如何操作的。 ### Case 1 - 右旋 -如下图所示(结点下方为「平衡因子」),从底至顶看,二叉树中首个失衡结点是 **结点 3**。我们聚焦在以该失衡结点为根结点的子树上,将该结点记为 `node` ,将其左子结点记为 `child` ,执行「右旋」操作。完成右旋后,该子树已经恢复平衡,并且仍然为二叉搜索树。 +如下图所示(节点下方为「平衡因子」),从底至顶看,二叉树中首个失衡节点是 **节点 3**。我们聚焦在以该失衡节点为根节点的子树上,将该节点记为 `node` ,将其左子节点记为 `child` ,执行「右旋」操作。完成右旋后,该子树已经恢复平衡,并且仍然为二叉搜索树。 === "<1>" ![右旋操作步骤](avl_tree.assets/avltree_right_rotate_step1.png) @@ -321,11 +321,11 @@ AVL 树的独特之处在于「旋转 Rotation」的操作,其可 **在不影 === "<4>" ![avltree_right_rotate_step4](avl_tree.assets/avltree_right_rotate_step4.png) -进而,如果结点 `child` 本身有右子结点(记为 `grandChild` ),则需要在「右旋」中添加一步:将 `grandChild` 作为 `node` 的左子结点。 +进而,如果节点 `child` 本身有右子节点(记为 `grandChild` ),则需要在「右旋」中添加一步:将 `grandChild` 作为 `node` 的左子节点。 ![有 grandChild 的右旋操作](avl_tree.assets/avltree_right_rotate_with_grandchild.png) -“向右旋转”是一种形象化的说法,实际需要通过修改结点指针实现,代码如下所示。 +“向右旋转”是一种形象化的说法,实际需要通过修改节点指针实现,代码如下所示。 === "Java" @@ -393,7 +393,7 @@ AVL 树的独特之处在于「旋转 Rotation」的操作,其可 **在不影 ![左旋操作](avl_tree.assets/avltree_left_rotate.png) -同理,若结点 `child` 本身有左子结点(记为 `grandChild` ),则需要在「左旋」中添加一步:将 `grandChild` 作为 `node` 的右子结点。 +同理,若节点 `child` 本身有左子节点(记为 `grandChild` ),则需要在「左旋」中添加一步:将 `grandChild` 作为 `node` 的右子节点。 ![有 grandChild 的左旋操作](avl_tree.assets/avltree_left_rotate_with_grandchild.png) @@ -461,7 +461,7 @@ AVL 树的独特之处在于「旋转 Rotation」的操作,其可 **在不影 ### Case 3 - 先左后右 -对于下图的失衡结点 3 ,**单一使用左旋或右旋都无法使子树恢复平衡**,此时需要「先左旋后右旋」,即先对 `child` 执行「左旋」,再对 `node` 执行「右旋」。 +对于下图的失衡节点 3 ,**单一使用左旋或右旋都无法使子树恢复平衡**,此时需要「先左旋后右旋」,即先对 `child` 执行「左旋」,再对 `node` 执行「右旋」。 ![先左旋后右旋](avl_tree.assets/avltree_left_right_rotate.png) @@ -477,11 +477,11 @@ AVL 树的独特之处在于「旋转 Rotation」的操作,其可 **在不影 ![AVL 树的四种旋转情况](avl_tree.assets/avltree_rotation_cases.png) -具体地,在代码中使用 **失衡结点的平衡因子、较高一侧子结点的平衡因子** 来确定失衡结点属于上图中的哪种情况。 +具体地,在代码中使用 **失衡节点的平衡因子、较高一侧子节点的平衡因子** 来确定失衡节点属于上图中的哪种情况。
-| 失衡结点的平衡因子 | 子结点的平衡因子 | 应采用的旋转方法 | +| 失衡节点的平衡因子 | 子节点的平衡因子 | 应采用的旋转方法 | | ------------------ | ---------------- | ---------------- | | $>0$ (即左偏树) | $\geq 0$ | 右旋 | | $>0$ (即左偏树) | $<0$ | 先左旋后右旋 | @@ -490,7 +490,7 @@ AVL 树的独特之处在于「旋转 Rotation」的操作,其可 **在不影
-为方便使用,我们将旋转操作封装成一个函数。至此,**我们可以使用此函数来旋转各种失衡情况,使失衡结点重新恢复平衡**。 +为方便使用,我们将旋转操作封装成一个函数。至此,**我们可以使用此函数来旋转各种失衡情况,使失衡节点重新恢复平衡**。 === "Java" @@ -554,9 +554,9 @@ AVL 树的独特之处在于「旋转 Rotation」的操作,其可 **在不影 ## AVL 树常用操作 -### 插入结点 +### 插入节点 -「AVL 树」的结点插入操作与「二叉搜索树」主体类似。不同的是,在插入结点后,从该结点到根结点的路径上会出现一系列「失衡结点」。所以,**我们需要从该结点开始,从底至顶地执行旋转操作,使所有失衡结点恢复平衡**。 +「AVL 树」的节点插入操作与「二叉搜索树」主体类似。不同的是,在插入节点后,从该节点到根节点的路径上会出现一系列「失衡节点」。所以,**我们需要从该节点开始,从底至顶地执行旋转操作,使所有失衡节点恢复平衡**。 === "Java" @@ -638,9 +638,9 @@ AVL 树的独特之处在于「旋转 Rotation」的操作,其可 **在不影 [class]{AVLTree}-[func]{insertHelper} ``` -### 删除结点 +### 删除节点 -「AVL 树」删除结点操作与「二叉搜索树」删除结点操作总体相同。类似地,**在删除结点后,也需要从底至顶地执行旋转操作,使所有失衡结点恢复平衡**。 +「AVL 树」删除节点操作与「二叉搜索树」删除节点操作总体相同。类似地,**在删除节点后,也需要从底至顶地执行旋转操作,使所有失衡节点恢复平衡**。 === "Java" @@ -742,9 +742,9 @@ AVL 树的独特之处在于「旋转 Rotation」的操作,其可 **在不影 [class]{AVLTree}-[func]{getInOrderNext} ``` -### 查找结点 +### 查找节点 -「AVL 树」的结点查找操作与「二叉搜索树」一致,在此不再赘述。 +「AVL 树」的节点查找操作与「二叉搜索树」一致,在此不再赘述。 ## AVL 树典型应用 @@ -753,4 +753,4 @@ AVL 树的独特之处在于「旋转 Rotation」的操作,其可 **在不影 !!! question "为什么红黑树比 AVL 树更受欢迎?" - 红黑树的平衡条件相对宽松,因此在红黑树中插入与删除结点所需的旋转操作相对更少,结点增删操作相比 AVL 树的效率更高。 + 红黑树的平衡条件相对宽松,因此在红黑树中插入与删除节点所需的旋转操作相对更少,节点增删操作相比 AVL 树的效率更高。 diff --git a/docs/chapter_tree/binary_search_tree.assets/binary_search_tree.png b/docs/chapter_tree/binary_search_tree.assets/binary_search_tree.png index 6ca6f02f..32273347 100644 Binary files a/docs/chapter_tree/binary_search_tree.assets/binary_search_tree.png and b/docs/chapter_tree/binary_search_tree.assets/binary_search_tree.png differ diff --git a/docs/chapter_tree/binary_search_tree.assets/bst_degradation.png b/docs/chapter_tree/binary_search_tree.assets/bst_degradation.png index 45c9a8fa..b8aee34c 100644 Binary files a/docs/chapter_tree/binary_search_tree.assets/bst_degradation.png and b/docs/chapter_tree/binary_search_tree.assets/bst_degradation.png differ diff --git a/docs/chapter_tree/binary_search_tree.assets/bst_inorder_traversal.png b/docs/chapter_tree/binary_search_tree.assets/bst_inorder_traversal.png index 8eb04ed1..22d55096 100644 Binary files a/docs/chapter_tree/binary_search_tree.assets/bst_inorder_traversal.png and b/docs/chapter_tree/binary_search_tree.assets/bst_inorder_traversal.png differ diff --git a/docs/chapter_tree/binary_search_tree.assets/bst_insert.png b/docs/chapter_tree/binary_search_tree.assets/bst_insert.png index 1fc2826d..47395648 100644 Binary files a/docs/chapter_tree/binary_search_tree.assets/bst_insert.png and b/docs/chapter_tree/binary_search_tree.assets/bst_insert.png differ diff --git a/docs/chapter_tree/binary_search_tree.assets/bst_remove_case1.png b/docs/chapter_tree/binary_search_tree.assets/bst_remove_case1.png index 50aa6add..0c27ac65 100644 Binary files a/docs/chapter_tree/binary_search_tree.assets/bst_remove_case1.png and b/docs/chapter_tree/binary_search_tree.assets/bst_remove_case1.png differ diff --git a/docs/chapter_tree/binary_search_tree.assets/bst_remove_case2.png b/docs/chapter_tree/binary_search_tree.assets/bst_remove_case2.png index 26650d00..e12af967 100644 Binary files a/docs/chapter_tree/binary_search_tree.assets/bst_remove_case2.png and b/docs/chapter_tree/binary_search_tree.assets/bst_remove_case2.png differ diff --git a/docs/chapter_tree/binary_search_tree.assets/bst_remove_case3_step1.png b/docs/chapter_tree/binary_search_tree.assets/bst_remove_case3_step1.png index ec7cb659..df85fad4 100644 Binary files a/docs/chapter_tree/binary_search_tree.assets/bst_remove_case3_step1.png and b/docs/chapter_tree/binary_search_tree.assets/bst_remove_case3_step1.png differ diff --git a/docs/chapter_tree/binary_search_tree.assets/bst_remove_case3_step2.png b/docs/chapter_tree/binary_search_tree.assets/bst_remove_case3_step2.png index b18d9240..2fb88f58 100644 Binary files a/docs/chapter_tree/binary_search_tree.assets/bst_remove_case3_step2.png and b/docs/chapter_tree/binary_search_tree.assets/bst_remove_case3_step2.png differ diff --git a/docs/chapter_tree/binary_search_tree.assets/bst_remove_case3_step3.png b/docs/chapter_tree/binary_search_tree.assets/bst_remove_case3_step3.png index 817ef75a..6a0a0ecf 100644 Binary files a/docs/chapter_tree/binary_search_tree.assets/bst_remove_case3_step3.png and b/docs/chapter_tree/binary_search_tree.assets/bst_remove_case3_step3.png differ diff --git a/docs/chapter_tree/binary_search_tree.assets/bst_remove_case3_step4.png b/docs/chapter_tree/binary_search_tree.assets/bst_remove_case3_step4.png index 94052b2d..7dcdf22d 100644 Binary files a/docs/chapter_tree/binary_search_tree.assets/bst_remove_case3_step4.png and b/docs/chapter_tree/binary_search_tree.assets/bst_remove_case3_step4.png differ diff --git a/docs/chapter_tree/binary_search_tree.assets/bst_search_step1.png b/docs/chapter_tree/binary_search_tree.assets/bst_search_step1.png index e0e82692..be56bedc 100644 Binary files a/docs/chapter_tree/binary_search_tree.assets/bst_search_step1.png and b/docs/chapter_tree/binary_search_tree.assets/bst_search_step1.png differ diff --git a/docs/chapter_tree/binary_search_tree.assets/bst_search_step2.png b/docs/chapter_tree/binary_search_tree.assets/bst_search_step2.png index abde715f..616e2826 100644 Binary files a/docs/chapter_tree/binary_search_tree.assets/bst_search_step2.png and b/docs/chapter_tree/binary_search_tree.assets/bst_search_step2.png differ diff --git a/docs/chapter_tree/binary_search_tree.assets/bst_search_step3.png b/docs/chapter_tree/binary_search_tree.assets/bst_search_step3.png index 4d5cbdc4..c2e69abb 100644 Binary files a/docs/chapter_tree/binary_search_tree.assets/bst_search_step3.png and b/docs/chapter_tree/binary_search_tree.assets/bst_search_step3.png differ diff --git a/docs/chapter_tree/binary_search_tree.assets/bst_search_step4.png b/docs/chapter_tree/binary_search_tree.assets/bst_search_step4.png index b516b14e..f7a7f11e 100644 Binary files a/docs/chapter_tree/binary_search_tree.assets/bst_search_step4.png and b/docs/chapter_tree/binary_search_tree.assets/bst_search_step4.png differ diff --git a/docs/chapter_tree/binary_search_tree.md b/docs/chapter_tree/binary_search_tree.md index 621d6474..043034e9 100755 --- a/docs/chapter_tree/binary_search_tree.md +++ b/docs/chapter_tree/binary_search_tree.md @@ -2,23 +2,23 @@ 「二叉搜索树 Binary Search Tree」满足以下条件: -1. 对于根结点,左子树中所有结点的值 $<$ 根结点的值 $<$ 右子树中所有结点的值; -2. 任意结点的左子树和右子树也是二叉搜索树,即也满足条件 `1.` ; +1. 对于根节点,左子树中所有节点的值 $<$ 根节点的值 $<$ 右子树中所有节点的值; +2. 任意节点的左子树和右子树也是二叉搜索树,即也满足条件 `1.` ; ![二叉搜索树](binary_search_tree.assets/binary_search_tree.png) ## 二叉搜索树的操作 -### 查找结点 +### 查找节点 -给定目标结点值 `num` ,可以根据二叉搜索树的性质来查找。我们声明一个结点 `cur` ,从二叉树的根结点 `root` 出发,循环比较结点值 `cur.val` 和 `num` 之间的大小关系 +给定目标节点值 `num` ,可以根据二叉搜索树的性质来查找。我们声明一个节点 `cur` ,从二叉树的根节点 `root` 出发,循环比较节点值 `cur.val` 和 `num` 之间的大小关系 -- 若 `cur.val < num` ,说明目标结点在 `cur` 的右子树中,因此执行 `cur = cur.right` ; -- 若 `cur.val > num` ,说明目标结点在 `cur` 的左子树中,因此执行 `cur = cur.left` ; -- 若 `cur.val = num` ,说明找到目标结点,跳出循环并返回该结点即可; +- 若 `cur.val < num` ,说明目标节点在 `cur` 的右子树中,因此执行 `cur = cur.right` ; +- 若 `cur.val > num` ,说明目标节点在 `cur` 的左子树中,因此执行 `cur = cur.left` ; +- 若 `cur.val = num` ,说明找到目标节点,跳出循环并返回该节点即可; === "<1>" - ![查找结点步骤](binary_search_tree.assets/bst_search_step1.png) + ![查找节点步骤](binary_search_tree.assets/bst_search_step1.png) === "<2>" ![bst_search_step2](binary_search_tree.assets/bst_search_step2.png) @@ -91,16 +91,16 @@ [class]{BinarySearchTree}-[func]{search} ``` -### 插入结点 +### 插入节点 -给定一个待插入元素 `num` ,为了保持二叉搜索树“左子树 < 根结点 < 右子树”的性质,插入操作分为两步: +给定一个待插入元素 `num` ,为了保持二叉搜索树“左子树 < 根节点 < 右子树”的性质,插入操作分为两步: -1. **查找插入位置**:与查找操作类似,我们从根结点出发,根据当前结点值和 `num` 的大小关系循环向下搜索,直到越过叶结点(遍历到 $\text{null}$ )时跳出循环; -2. **在该位置插入结点**:初始化结点 `num` ,将该结点放到 $\text{null}$ 的位置 ; +1. **查找插入位置**:与查找操作类似,我们从根节点出发,根据当前节点值和 `num` 的大小关系循环向下搜索,直到越过叶节点(遍历到 $\text{null}$ )时跳出循环; +2. **在该位置插入节点**:初始化节点 `num` ,将该节点放到 $\text{null}$ 的位置 ; -二叉搜索树不允许存在重复结点,否则将会违背其定义。因此若待插入结点在树中已经存在,则不执行插入,直接返回即可。 +二叉搜索树不允许存在重复节点,否则将会违背其定义。因此若待插入节点在树中已经存在,则不执行插入,直接返回即可。 -![在二叉搜索树中插入结点](binary_search_tree.assets/bst_insert.png) +![在二叉搜索树中插入节点](binary_search_tree.assets/bst_insert.png) === "Java" @@ -162,30 +162,30 @@ [class]{BinarySearchTree}-[func]{insert} ``` -为了插入结点,需要借助 **辅助结点 `pre`** 保存上一轮循环的结点,这样在遍历到 $\text{null}$ 时,我们也可以获取到其父结点,从而完成结点插入操作。 +为了插入节点,需要借助 **辅助节点 `pre`** 保存上一轮循环的节点,这样在遍历到 $\text{null}$ 时,我们也可以获取到其父节点,从而完成节点插入操作。 -与查找结点相同,插入结点使用 $O(\log n)$ 时间。 +与查找节点相同,插入节点使用 $O(\log n)$ 时间。 -### 删除结点 +### 删除节点 -与插入结点一样,我们需要在删除操作后维持二叉搜索树的“左子树 < 根结点 < 右子树”的性质。首先,我们需要在二叉树中执行查找操作,获取待删除结点。接下来,根据待删除结点的子结点数量,删除操作需要分为三种情况: +与插入节点一样,我们需要在删除操作后维持二叉搜索树的“左子树 < 根节点 < 右子树”的性质。首先,我们需要在二叉树中执行查找操作,获取待删除节点。接下来,根据待删除节点的子节点数量,删除操作需要分为三种情况: -**当待删除结点的子结点数量 $= 0$ 时**,表明待删除结点是叶结点,直接删除即可。 +**当待删除节点的子节点数量 $= 0$ 时**,表明待删除节点是叶节点,直接删除即可。 -![在二叉搜索树中删除结点(度为 0)](binary_search_tree.assets/bst_remove_case1.png) +![在二叉搜索树中删除节点(度为 0)](binary_search_tree.assets/bst_remove_case1.png) -**当待删除结点的子结点数量 $= 1$ 时**,将待删除结点替换为其子结点即可。 +**当待删除节点的子节点数量 $= 1$ 时**,将待删除节点替换为其子节点即可。 -![在二叉搜索树中删除结点(度为 1)](binary_search_tree.assets/bst_remove_case2.png) +![在二叉搜索树中删除节点(度为 1)](binary_search_tree.assets/bst_remove_case2.png) -**当待删除结点的子结点数量 $= 2$ 时**,删除操作分为三步: +**当待删除节点的子节点数量 $= 2$ 时**,删除操作分为三步: -1. 找到待删除结点在 **中序遍历序列** 中的下一个结点,记为 `nex` ; -2. 在树中递归删除结点 `nex` ; -3. 使用 `nex` 替换待删除结点; +1. 找到待删除节点在 **中序遍历序列** 中的下一个节点,记为 `nex` ; +2. 在树中递归删除节点 `nex` ; +3. 使用 `nex` 替换待删除节点; === "<1>" - ![删除结点(度为 2)步骤](binary_search_tree.assets/bst_remove_case3_step1.png) + ![删除节点(度为 2)步骤](binary_search_tree.assets/bst_remove_case3_step1.png) === "<2>" ![bst_remove_case3_step2](binary_search_tree.assets/bst_remove_case3_step2.png) @@ -196,7 +196,7 @@ === "<4>" ![bst_remove_case3_step4](binary_search_tree.assets/bst_remove_case3_step4.png) -删除结点操作也使用 $O(\log n)$ 时间,其中查找待删除结点 $O(\log n)$ ,获取中序遍历后继结点 $O(\log n)$ 。 +删除节点操作也使用 $O(\log n)$ 时间,其中查找待删除节点 $O(\log n)$ ,获取中序遍历后继节点 $O(\log n)$ 。 === "Java" @@ -280,7 +280,7 @@ ### 排序 -我们知道,「中序遍历」遵循“左 $\rightarrow$ 根 $\rightarrow$ 右”的遍历优先级,而二叉搜索树遵循“左子结点 $<$ 根结点 $<$ 右子结点”的大小关系。因此,在二叉搜索树中进行中序遍历时,总是会优先遍历下一个最小结点,从而得出一条重要性质:**二叉搜索树的中序遍历序列是升序的**。 +我们知道,「中序遍历」遵循“左 $\rightarrow$ 根 $\rightarrow$ 右”的遍历优先级,而二叉搜索树遵循“左子节点 $<$ 根节点 $<$ 右子节点”的大小关系。因此,在二叉搜索树中进行中序遍历时,总是会优先遍历下一个最小节点,从而得出一条重要性质:**二叉搜索树的中序遍历序列是升序的**。 借助中序遍历升序的性质,我们在二叉搜索树中获取有序数据仅需 $O(n)$ 时间,而无需额外排序,非常高效。 @@ -317,9 +317,9 @@ ## 二叉搜索树的退化 -理想情况下,我们希望二叉搜索树的是“左右平衡”的(详见「平衡二叉树」章节),此时可以在 $\log n$ 轮循环内查找任意结点。 +理想情况下,我们希望二叉搜索树的是“左右平衡”的(详见「平衡二叉树」章节),此时可以在 $\log n$ 轮循环内查找任意节点。 -如果我们动态地在二叉搜索树中插入与删除结点,**则可能导致二叉树退化为链表**,此时各种操作的时间复杂度也退化之 $O(n)$ 。 +如果我们动态地在二叉搜索树中插入与删除节点,**则可能导致二叉树退化为链表**,此时各种操作的时间复杂度也退化之 $O(n)$ 。 !!! note diff --git a/docs/chapter_tree/binary_tree.assets/array_representation_complete_binary_tree.png b/docs/chapter_tree/binary_tree.assets/array_representation_complete_binary_tree.png index d6b7bfb0..8c0571b8 100644 Binary files a/docs/chapter_tree/binary_tree.assets/array_representation_complete_binary_tree.png and b/docs/chapter_tree/binary_tree.assets/array_representation_complete_binary_tree.png differ diff --git a/docs/chapter_tree/binary_tree.assets/array_representation_mapping.png b/docs/chapter_tree/binary_tree.assets/array_representation_mapping.png index 11a6aad9..ccad300b 100644 Binary files a/docs/chapter_tree/binary_tree.assets/array_representation_mapping.png and b/docs/chapter_tree/binary_tree.assets/array_representation_mapping.png differ diff --git a/docs/chapter_tree/binary_tree.assets/array_representation_with_empty.png b/docs/chapter_tree/binary_tree.assets/array_representation_with_empty.png index 0420e4d6..cf949dc7 100644 Binary files a/docs/chapter_tree/binary_tree.assets/array_representation_with_empty.png and b/docs/chapter_tree/binary_tree.assets/array_representation_with_empty.png differ diff --git a/docs/chapter_tree/binary_tree.assets/array_representation_without_empty.png b/docs/chapter_tree/binary_tree.assets/array_representation_without_empty.png index e6f5849d..cb4dcce1 100644 Binary files a/docs/chapter_tree/binary_tree.assets/array_representation_without_empty.png and b/docs/chapter_tree/binary_tree.assets/array_representation_without_empty.png differ diff --git a/docs/chapter_tree/binary_tree.assets/balanced_binary_tree.png b/docs/chapter_tree/binary_tree.assets/balanced_binary_tree.png index 6202eabb..6eb95950 100644 Binary files a/docs/chapter_tree/binary_tree.assets/balanced_binary_tree.png and b/docs/chapter_tree/binary_tree.assets/balanced_binary_tree.png differ diff --git a/docs/chapter_tree/binary_tree.assets/binary_tree_add_remove.png b/docs/chapter_tree/binary_tree.assets/binary_tree_add_remove.png index a79fcc3e..006ec8a7 100644 Binary files a/docs/chapter_tree/binary_tree.assets/binary_tree_add_remove.png and b/docs/chapter_tree/binary_tree.assets/binary_tree_add_remove.png differ diff --git a/docs/chapter_tree/binary_tree.assets/binary_tree_corner_cases.png b/docs/chapter_tree/binary_tree.assets/binary_tree_corner_cases.png index d6ae7e4a..4c502f2e 100644 Binary files a/docs/chapter_tree/binary_tree.assets/binary_tree_corner_cases.png and b/docs/chapter_tree/binary_tree.assets/binary_tree_corner_cases.png differ diff --git a/docs/chapter_tree/binary_tree.assets/binary_tree_definition.png b/docs/chapter_tree/binary_tree.assets/binary_tree_definition.png index f9977740..c4c8fe56 100644 Binary files a/docs/chapter_tree/binary_tree.assets/binary_tree_definition.png and b/docs/chapter_tree/binary_tree.assets/binary_tree_definition.png differ diff --git a/docs/chapter_tree/binary_tree.assets/binary_tree_terminology.png b/docs/chapter_tree/binary_tree.assets/binary_tree_terminology.png index c71b1f8f..9ba1f106 100644 Binary files a/docs/chapter_tree/binary_tree.assets/binary_tree_terminology.png and b/docs/chapter_tree/binary_tree.assets/binary_tree_terminology.png differ diff --git a/docs/chapter_tree/binary_tree.assets/complete_binary_tree.png b/docs/chapter_tree/binary_tree.assets/complete_binary_tree.png index 2a75cb46..0994cb01 100644 Binary files a/docs/chapter_tree/binary_tree.assets/complete_binary_tree.png and b/docs/chapter_tree/binary_tree.assets/complete_binary_tree.png differ diff --git a/docs/chapter_tree/binary_tree.assets/full_binary_tree.png b/docs/chapter_tree/binary_tree.assets/full_binary_tree.png index 0ea93e40..eba38606 100644 Binary files a/docs/chapter_tree/binary_tree.assets/full_binary_tree.png and b/docs/chapter_tree/binary_tree.assets/full_binary_tree.png differ diff --git a/docs/chapter_tree/binary_tree.assets/perfect_binary_tree.png b/docs/chapter_tree/binary_tree.assets/perfect_binary_tree.png index f65ed5e9..3c4706ec 100644 Binary files a/docs/chapter_tree/binary_tree.assets/perfect_binary_tree.png and b/docs/chapter_tree/binary_tree.assets/perfect_binary_tree.png differ diff --git a/docs/chapter_tree/binary_tree.md b/docs/chapter_tree/binary_tree.md index bc95de09..0b6fc990 100644 --- a/docs/chapter_tree/binary_tree.md +++ b/docs/chapter_tree/binary_tree.md @@ -1,15 +1,15 @@ # 二叉树 -「二叉树 Binary Tree」是一种非线性数据结构,代表着祖先与后代之间的派生关系,体现着“一分为二”的分治逻辑。类似于链表,二叉树也是以结点为单位存储的,结点包含「值」和两个「指针」。 +「二叉树 Binary Tree」是一种非线性数据结构,代表着祖先与后代之间的派生关系,体现着“一分为二”的分治逻辑。类似于链表,二叉树也是以节点为单位存储的,节点包含「值」和两个「指针」。 === "Java" ```java title="" - /* 二叉树结点类 */ + /* 二叉树节点类 */ class TreeNode { - int val; // 结点值 - TreeNode left; // 左子结点指针 - TreeNode right; // 右子结点指针 + int val; // 节点值 + TreeNode left; // 左子节点指针 + TreeNode right; // 右子节点指针 TreeNode(int x) { val = x; } } ``` @@ -17,11 +17,11 @@ === "C++" ```cpp title="" - /* 二叉树结点结构体 */ + /* 二叉树节点结构体 */ struct TreeNode { - int val; // 结点值 - TreeNode *left; // 左子结点指针 - TreeNode *right; // 右子结点指针 + int val; // 节点值 + TreeNode *left; // 左子节点指针 + TreeNode *right; // 右子节点指针 TreeNode(int x) : val(x), left(nullptr), right(nullptr) {} }; ``` @@ -29,24 +29,24 @@ === "Python" ```python title="" - """ 二叉树结点类 """ + """ 二叉树节点类 """ class TreeNode: def __init__(self, val: int): - self.val: int = val # 结点值 - self.left: Optional[TreeNode] = None # 左子结点指针 - self.right: Optional[TreeNode] = None # 右子结点指针 + self.val: int = val # 节点值 + self.left: Optional[TreeNode] = None # 左子节点指针 + self.right: Optional[TreeNode] = None # 右子节点指针 ``` === "Go" ```go title="" - /* 二叉树结点结构体 */ + /* 二叉树节点结构体 */ type TreeNode struct { Val int Left *TreeNode Right *TreeNode } - /* 结点初始化方法 */ + /* 节点初始化方法 */ func NewTreeNode(v int) *TreeNode { return &TreeNode{ Left: nil, @@ -59,27 +59,27 @@ === "JavaScript" ```javascript title="" - /* 二叉树结点类 */ + /* 二叉树节点类 */ function TreeNode(val, left, right) { - this.val = (val === undefined ? 0 : val); // 结点值 - this.left = (left === undefined ? null : left); // 左子结点指针 - this.right = (right === undefined ? null : right); // 右子结点指针 + this.val = (val === undefined ? 0 : val); // 节点值 + this.left = (left === undefined ? null : left); // 左子节点指针 + this.right = (right === undefined ? null : right); // 右子节点指针 } ``` === "TypeScript" ```typescript title="" - /* 二叉树结点类 */ + /* 二叉树节点类 */ class TreeNode { val: number; left: TreeNode | null; right: TreeNode | null; constructor(val?: number, left?: TreeNode | null, right?: TreeNode | null) { - this.val = val === undefined ? 0 : val; // 结点值 - this.left = left === undefined ? null : left; // 左子结点指针 - this.right = right === undefined ? null : right; // 右子结点指针 + this.val = val === undefined ? 0 : val; // 节点值 + this.left = left === undefined ? null : left; // 左子节点指针 + this.right = right === undefined ? null : right; // 右子节点指针 } } ``` @@ -93,11 +93,11 @@ === "C#" ```csharp title="" - /* 二叉树结点类 */ + /* 二叉树节点类 */ class TreeNode { - int val; // 结点值 - TreeNode? left; // 左子结点指针 - TreeNode? right; // 右子结点指针 + int val; // 节点值 + TreeNode? left; // 左子节点指针 + TreeNode? right; // 右子节点指针 TreeNode(int x) { val = x; } } ``` @@ -105,11 +105,11 @@ === "Swift" ```swift title="" - /* 二叉树结点类 */ + /* 二叉树节点类 */ class TreeNode { - var val: Int // 结点值 - var left: TreeNode? // 左子结点指针 - var right: TreeNode? // 右子结点指针 + var val: Int // 节点值 + var left: TreeNode? // 左子节点指针 + var right: TreeNode? // 右子节点指针 init(x: Int) { val = x @@ -123,39 +123,39 @@ ``` -结点的两个指针分别指向「左子结点」和「右子结点」,并且称该结点为两个子结点的「父结点」。给定二叉树某结点,将“左子结点及其以下结点形成的树”称为该结点的「左子树」,右子树同理。 +节点的两个指针分别指向「左子节点」和「右子节点」,并且称该节点为两个子节点的「父节点」。给定二叉树某节点,将“左子节点及其以下节点形成的树”称为该节点的「左子树」,右子树同理。 -除了叶结点外,每个结点都有子结点和子树。例如,若将下图的“结点 2”看作父结点,那么其左子结点和右子结点分别为“结点 4”和“结点 5”,左子树和右子树分别为“结点 4 及其以下结点形成的树”和“结点 5 及其以下结点形成的树”。 +除了叶节点外,每个节点都有子节点和子树。例如,若将下图的“节点 2”看作父节点,那么其左子节点和右子节点分别为“节点 4”和“节点 5”,左子树和右子树分别为“节点 4 及其以下节点形成的树”和“节点 5 及其以下节点形成的树”。 -![父结点、子结点、子树](binary_tree.assets/binary_tree_definition.png) +![父节点、子节点、子树](binary_tree.assets/binary_tree_definition.png) ## 二叉树常见术语 二叉树的术语较多,建议尽量理解并记住。后续可能遗忘,可以在需要使用时回来查看确认。 -- 「根结点 Root Node」:二叉树最顶层的结点,其没有父结点; -- 「叶结点 Leaf Node」:没有子结点的结点,其两个指针都指向 $\text{null}$ ; -- 结点所处「层 Level」:从顶至底依次增加,根结点所处层为 1 ; -- 结点「度 Degree」:结点的子结点数量。二叉树中,度的范围是 0, 1, 2 ; -- 「边 Edge」:连接两个结点的边,即结点指针; -- 二叉树「高度」:二叉树中根结点到最远叶结点走过边的数量; -- 结点「深度 Depth」 :根结点到该结点走过边的数量; -- 结点「高度 Height」:最远叶结点到该结点走过边的数量; +- 「根节点 Root Node」:二叉树最顶层的节点,其没有父节点; +- 「叶节点 Leaf Node」:没有子节点的节点,其两个指针都指向 $\text{null}$ ; +- 节点所处「层 Level」:从顶至底依次增加,根节点所处层为 1 ; +- 节点「度 Degree」:节点的子节点数量。二叉树中,度的范围是 0, 1, 2 ; +- 「边 Edge」:连接两个节点的边,即节点指针; +- 二叉树「高度」:二叉树中根节点到最远叶节点走过边的数量; +- 节点「深度 Depth」 :根节点到该节点走过边的数量; +- 节点「高度 Height」:最远叶节点到该节点走过边的数量; ![二叉树的常用术语](binary_tree.assets/binary_tree_terminology.png) !!! tip "高度与深度的定义" - 值得注意,我们通常将「高度」和「深度」定义为“走过边的数量”,而有些题目或教材会将其定义为“走过结点的数量”,此时高度或深度都需要 + 1 。 + 值得注意,我们通常将「高度」和「深度」定义为“走过边的数量”,而有些题目或教材会将其定义为“走过节点的数量”,此时高度或深度都需要 + 1 。 ## 二叉树基本操作 -**初始化二叉树**。与链表类似,先初始化结点,再构建引用指向(即指针)。 +**初始化二叉树**。与链表类似,先初始化节点,再构建引用指向(即指针)。 === "Java" ```java title="binary_tree.java" - // 初始化结点 + // 初始化节点 TreeNode n1 = new TreeNode(1); TreeNode n2 = new TreeNode(2); TreeNode n3 = new TreeNode(3); @@ -172,7 +172,7 @@ ```cpp title="binary_tree.cpp" /* 初始化二叉树 */ - // 初始化结点 + // 初始化节点 TreeNode* n1 = new TreeNode(1); TreeNode* n2 = new TreeNode(2); TreeNode* n3 = new TreeNode(3); @@ -189,7 +189,7 @@ ```python title="binary_tree.py" """ 初始化二叉树 """ - # 初始化结点 + # 初始化节点 n1 = TreeNode(val=1) n2 = TreeNode(val=2) n3 = TreeNode(val=3) @@ -206,7 +206,7 @@ ```go title="binary_tree.go" /* 初始化二叉树 */ - // 初始化结点 + // 初始化节点 n1 := NewTreeNode(1) n2 := NewTreeNode(2) n3 := NewTreeNode(3) @@ -223,7 +223,7 @@ ```javascript title="binary_tree.js" /* 初始化二叉树 */ - // 初始化结点 + // 初始化节点 let n1 = new TreeNode(1), n2 = new TreeNode(2), n3 = new TreeNode(3), @@ -240,7 +240,7 @@ ```typescript title="binary_tree.ts" /* 初始化二叉树 */ - // 初始化结点 + // 初始化节点 let n1 = new TreeNode(1), n2 = new TreeNode(2), n3 = new TreeNode(3), @@ -263,7 +263,7 @@ ```csharp title="binary_tree.cs" /* 初始化二叉树 */ - // 初始化结点 + // 初始化节点 TreeNode n1 = new TreeNode(1); TreeNode n2 = new TreeNode(2); TreeNode n3 = new TreeNode(3); @@ -279,7 +279,7 @@ === "Swift" ```swift title="binary_tree.swift" - // 初始化结点 + // 初始化节点 let n1 = TreeNode(x: 1) let n2 = TreeNode(x: 2) let n3 = TreeNode(x: 3) @@ -298,78 +298,78 @@ ``` -**插入与删除结点**。与链表类似,插入与删除结点都可以通过修改指针实现。 +**插入与删除节点**。与链表类似,插入与删除节点都可以通过修改指针实现。 -![在二叉树中插入与删除结点](binary_tree.assets/binary_tree_add_remove.png) +![在二叉树中插入与删除节点](binary_tree.assets/binary_tree_add_remove.png) === "Java" ```java title="binary_tree.java" TreeNode P = new TreeNode(0); - // 在 n1 -> n2 中间插入结点 P + // 在 n1 -> n2 中间插入节点 P n1.left = P; P.left = n2; - // 删除结点 P + // 删除节点 P n1.left = n2; ``` === "C++" ```cpp title="binary_tree.cpp" - /* 插入与删除结点 */ + /* 插入与删除节点 */ TreeNode* P = new TreeNode(0); - // 在 n1 -> n2 中间插入结点 P + // 在 n1 -> n2 中间插入节点 P n1->left = P; P->left = n2; - // 删除结点 P + // 删除节点 P n1->left = n2; ``` === "Python" ```python title="binary_tree.py" - """ 插入与删除结点 """ + """ 插入与删除节点 """ p = TreeNode(0) - # 在 n1 -> n2 中间插入结点 P + # 在 n1 -> n2 中间插入节点 P n1.left = p p.left = n2 - # 删除结点 P + # 删除节点 P n1.left = n2 ``` === "Go" ```go title="binary_tree.go" - /* 插入与删除结点 */ - // 在 n1 -> n2 中间插入结点 P + /* 插入与删除节点 */ + // 在 n1 -> n2 中间插入节点 P p := NewTreeNode(0) n1.Left = p p.Left = n2 - // 删除结点 P + // 删除节点 P n1.Left = n2 ``` === "JavaScript" ```javascript title="binary_tree.js" - /* 插入与删除结点 */ + /* 插入与删除节点 */ let P = new TreeNode(0); - // 在 n1 -> n2 中间插入结点 P + // 在 n1 -> n2 中间插入节点 P n1.left = P; P.left = n2; - // 删除结点 P + // 删除节点 P n1.left = n2; ``` === "TypeScript" ```typescript title="binary_tree.ts" - /* 插入与删除结点 */ + /* 插入与删除节点 */ const P = new TreeNode(0); - // 在 n1 -> n2 中间插入结点 P + // 在 n1 -> n2 中间插入节点 P n1.left = P; P.left = n2; - // 删除结点 P + // 删除节点 P n1.left = n2; ``` @@ -382,12 +382,12 @@ === "C#" ```csharp title="binary_tree.cs" - /* 插入与删除结点 */ + /* 插入与删除节点 */ TreeNode P = new TreeNode(0); - // 在 n1 -> n2 中间插入结点 P + // 在 n1 -> n2 中间插入节点 P n1.left = P; P.left = n2; - // 删除结点 P + // 删除节点 P n1.left = n2; ``` @@ -395,10 +395,10 @@ ```swift title="binary_tree.swift" let P = TreeNode(x: 0) - // 在 n1 -> n2 中间插入结点 P + // 在 n1 -> n2 中间插入节点 P n1.left = P P.left = n2 - // 删除结点 P + // 删除节点 P n1.left = n2 ``` @@ -410,13 +410,13 @@ !!! note - 插入结点会改变二叉树的原有逻辑结构,删除结点往往意味着删除了该结点的所有子树。因此,二叉树中的插入与删除一般都是由一套操作配合完成的,这样才能实现有意义的操作。 + 插入节点会改变二叉树的原有逻辑结构,删除节点往往意味着删除了该节点的所有子树。因此,二叉树中的插入与删除一般都是由一套操作配合完成的,这样才能实现有意义的操作。 ## 常见二叉树类型 ### 完美二叉树 -「完美二叉树 Perfect Binary Tree」的所有层的结点都被完全填满。在完美二叉树中,叶结点的度为 $0$ ,其余所有结点的度都为 $2$ ;若树高度 $= h$ ,则结点总数 $= 2^{h+1} - 1$ ,呈标准的指数级关系,反映着自然界中常见的细胞分裂。 +「完美二叉树 Perfect Binary Tree」的所有层的节点都被完全填满。在完美二叉树中,叶节点的度为 $0$ ,其余所有节点的度都为 $2$ ;若树高度 $= h$ ,则节点总数 $= 2^{h+1} - 1$ ,呈标准的指数级关系,反映着自然界中常见的细胞分裂。 !!! tip @@ -426,57 +426,57 @@ ### 完全二叉树 -「完全二叉树 Complete Binary Tree」只有最底层的结点未被填满,且最底层结点尽量靠左填充。 +「完全二叉树 Complete Binary Tree」只有最底层的节点未被填满,且最底层节点尽量靠左填充。 -**完全二叉树非常适合用数组来表示**。如果按照层序遍历序列的顺序来存储,那么空结点 `null` 一定全部出现在序列的尾部,因此我们就可以不用存储这些 null 了。 +**完全二叉树非常适合用数组来表示**。如果按照层序遍历序列的顺序来存储,那么空节点 `null` 一定全部出现在序列的尾部,因此我们就可以不用存储这些 null 了。 ![完全二叉树](binary_tree.assets/complete_binary_tree.png) ### 完满二叉树 -「完满二叉树 Full Binary Tree」除了叶结点之外,其余所有结点都有两个子结点。 +「完满二叉树 Full Binary Tree」除了叶节点之外,其余所有节点都有两个子节点。 ![完满二叉树](binary_tree.assets/full_binary_tree.png) ### 平衡二叉树 -「平衡二叉树 Balanced Binary Tree」中任意结点的左子树和右子树的高度之差的绝对值 $\leq 1$ 。 +「平衡二叉树 Balanced Binary Tree」中任意节点的左子树和右子树的高度之差的绝对值 $\leq 1$ 。 ![平衡二叉树](binary_tree.assets/balanced_binary_tree.png) ## 二叉树的退化 -当二叉树的每层的结点都被填满时,达到「完美二叉树」;而当所有结点都偏向一边时,二叉树退化为「链表」。 +当二叉树的每层的节点都被填满时,达到「完美二叉树」;而当所有节点都偏向一边时,二叉树退化为「链表」。 - 完美二叉树是一个二叉树的“最佳状态”,可以完全发挥出二叉树“分治”的优势; - 链表则是另一个极端,各项操作都变为线性操作,时间复杂度退化至 $O(n)$ ; ![二叉树的最佳与最二叉树的最佳和最差结构差情况](binary_tree.assets/binary_tree_corner_cases.png) -如下表所示,在最佳和最差结构下,二叉树的叶结点数量、结点总数、高度等达到极大或极小值。 +如下表所示,在最佳和最差结构下,二叉树的叶节点数量、节点总数、高度等达到极大或极小值。
| | 完美二叉树 | 链表 | | ----------------------------- | ---------- | ---------- | -| 第 $i$ 层的结点数量 | $2^{i-1}$ | $1$ | -| 树的高度为 $h$ 时的叶结点数量 | $2^h$ | $1$ | -| 树的高度为 $h$ 时的结点总数 | $2^{h+1} - 1$ | $h + 1$ | -| 树的结点总数为 $n$ 时的高度 | $\log_2 (n+1) - 1$ | $n - 1$ | +| 第 $i$ 层的节点数量 | $2^{i-1}$ | $1$ | +| 树的高度为 $h$ 时的叶节点数量 | $2^h$ | $1$ | +| 树的高度为 $h$ 时的节点总数 | $2^{h+1} - 1$ | $h + 1$ | +| 树的节点总数为 $n$ 时的高度 | $\log_2 (n+1) - 1$ | $n - 1$ |
## 二叉树表示方式 * -我们一般使用二叉树的「链表表示」,即存储单位为结点 `TreeNode` ,结点之间通过指针(引用)相连接。本文前述示例代码展示了二叉树在链表表示下的各项基本操作。 +我们一般使用二叉树的「链表表示」,即存储单位为节点 `TreeNode` ,节点之间通过指针(引用)相连接。本文前述示例代码展示了二叉树在链表表示下的各项基本操作。 -那能否可以用「数组表示」二叉树呢?答案是肯定的。先来分析一个简单案例,给定一个「完美二叉树」,将结点按照层序遍历的顺序编号(从 0 开始),那么可以推导得出父结点索引与子结点索引之间的「映射公式」:**设结点的索引为 $i$ ,则该结点的左子结点索引为 $2i + 1$ 、右子结点索引为 $2i + 2$** 。 +那能否可以用「数组表示」二叉树呢?答案是肯定的。先来分析一个简单案例,给定一个「完美二叉树」,将节点按照层序遍历的顺序编号(从 0 开始),那么可以推导得出父节点索引与子节点索引之间的「映射公式」:**设节点的索引为 $i$ ,则该节点的左子节点索引为 $2i + 1$ 、右子节点索引为 $2i + 2$** 。 -**本质上,映射公式的作用就是链表中的指针**。对于层序遍历序列中的任意结点,我们都可以使用映射公式来访问子结点。因此,可以直接使用层序遍历序列(即数组)来表示完美二叉树。 +**本质上,映射公式的作用就是链表中的指针**。对于层序遍历序列中的任意节点,我们都可以使用映射公式来访问子节点。因此,可以直接使用层序遍历序列(即数组)来表示完美二叉树。 ![完美二叉树的数组表示](binary_tree.assets/array_representation_mapping.png) -然而,完美二叉树只是个例,二叉树中间层往往存在许多空结点(即 `null` ),而层序遍历序列并不包含这些空结点,并且我们无法单凭序列来猜测空结点的数量和分布位置,**即理论上存在许多种二叉树都符合该层序遍历序列**。显然,这种情况无法使用数组来存储二叉树。 +然而,完美二叉树只是个例,二叉树中间层往往存在许多空节点(即 `null` ),而层序遍历序列并不包含这些空节点,并且我们无法单凭序列来猜测空节点的数量和分布位置,**即理论上存在许多种二叉树都符合该层序遍历序列**。显然,这种情况无法使用数组来存储二叉树。 ![给定数组对应多种二叉树可能性](binary_tree.assets/array_representation_without_empty.png) @@ -495,7 +495,7 @@ ```cpp title="" /* 二叉树的数组表示 */ // 为了符合数据类型为 int ,使用 int 最大值标记空位 - // 该方法的使用前提是没有结点的值 = INT_MAX + // 该方法的使用前提是没有节点的值 = INT_MAX vector tree = { 1, 2, 3, 4, INT_MAX, 6, 7, 8, 9, INT_MAX, INT_MAX, 12, INT_MAX, INT_MAX, 15 }; ``` @@ -561,8 +561,8 @@ ![任意类型二叉树的数组表示](binary_tree.assets/array_representation_with_empty.png) -回顾「完全二叉树」的定义,其只有最底层有空结点,并且最底层的结点尽量靠左,因而所有空结点都一定出现在层序遍历序列的末尾。**因为我们先验地确定了空位的位置,所以在使用数组表示完全二叉树时,可以省略存储“空位”**。因此,完全二叉树非常适合使用数组来表示。 +回顾「完全二叉树」的定义,其只有最底层有空节点,并且最底层的节点尽量靠左,因而所有空节点都一定出现在层序遍历序列的末尾。**因为我们先验地确定了空位的位置,所以在使用数组表示完全二叉树时,可以省略存储“空位”**。因此,完全二叉树非常适合使用数组来表示。 ![完全二叉树的数组表示](binary_tree.assets/array_representation_complete_binary_tree.png) -数组表示有两个优点: 一是不需要存储指针,节省空间;二是可以随机访问结点。然而,当二叉树中的“空位”很多时,数组中只包含很少结点的数据,空间利用率很低。 +数组表示有两个优点: 一是不需要存储指针,节省空间;二是可以随机访问节点。然而,当二叉树中的“空位”很多时,数组中只包含很少节点的数据,空间利用率很低。 diff --git a/docs/chapter_tree/binary_tree_traversal.assets/binary_tree_bfs.png b/docs/chapter_tree/binary_tree_traversal.assets/binary_tree_bfs.png index 8c2c6197..18610330 100644 Binary files a/docs/chapter_tree/binary_tree_traversal.assets/binary_tree_bfs.png and b/docs/chapter_tree/binary_tree_traversal.assets/binary_tree_bfs.png differ diff --git a/docs/chapter_tree/binary_tree_traversal.assets/binary_tree_dfs.png b/docs/chapter_tree/binary_tree_traversal.assets/binary_tree_dfs.png index 1772ea40..e17a0296 100644 Binary files a/docs/chapter_tree/binary_tree_traversal.assets/binary_tree_dfs.png and b/docs/chapter_tree/binary_tree_traversal.assets/binary_tree_dfs.png differ diff --git a/docs/chapter_tree/binary_tree_traversal.md b/docs/chapter_tree/binary_tree_traversal.md index 95791550..c6a6a859 100755 --- a/docs/chapter_tree/binary_tree_traversal.md +++ b/docs/chapter_tree/binary_tree_traversal.md @@ -1,12 +1,12 @@ # 二叉树遍历 -从物理结构角度看,树是一种基于链表的数据结构,因此遍历方式也是通过指针(即引用)逐个遍历结点。同时,树还是一种非线性数据结构,这导致遍历树比遍历链表更加复杂,需要使用搜索算法来实现。 +从物理结构角度看,树是一种基于链表的数据结构,因此遍历方式也是通过指针(即引用)逐个遍历节点。同时,树还是一种非线性数据结构,这导致遍历树比遍历链表更加复杂,需要使用搜索算法来实现。 常见的二叉树遍历方式有层序遍历、前序遍历、中序遍历、后序遍历。 ## 层序遍历 -「层序遍历 Level-Order Traversal」从顶至底、一层一层地遍历二叉树,并在每层中按照从左到右的顺序访问结点。 +「层序遍历 Level-Order Traversal」从顶至底、一层一层地遍历二叉树,并在每层中按照从左到右的顺序访问节点。 层序遍历本质上是「广度优先搜索 Breadth-First Traversal」,其体现着一种“一圈一圈向外”的层进遍历方式。 @@ -78,23 +78,23 @@ ### 复杂度分析 -**时间复杂度**:所有结点被访问一次,使用 $O(n)$ 时间,其中 $n$ 为结点数量。 +**时间复杂度**:所有节点被访问一次,使用 $O(n)$ 时间,其中 $n$ 为节点数量。 -**空间复杂度**:当为满二叉树时达到最差情况,遍历到最底层前,队列中最多同时存在 $\frac{n + 1}{2}$ 个结点,使用 $O(n)$ 空间。 +**空间复杂度**:当为满二叉树时达到最差情况,遍历到最底层前,队列中最多同时存在 $\frac{n + 1}{2}$ 个节点,使用 $O(n)$ 空间。 ## 前序、中序、后序遍历 相对地,前、中、后序遍历皆属于「深度优先遍历 Depth-First Traversal」,其体现着一种“先走到尽头,再回头继续”的回溯遍历方式。 -如下图所示,左侧是深度优先遍历的的示意图,右上方是对应的递归实现代码。深度优先遍历就像是绕着整个二叉树的外围“走”一圈,走的过程中,在每个结点都会遇到三个位置,分别对应前序遍历、中序遍历、后序遍历。 +如下图所示,左侧是深度优先遍历的的示意图,右上方是对应的递归实现代码。深度优先遍历就像是绕着整个二叉树的外围“走”一圈,走的过程中,在每个节点都会遇到三个位置,分别对应前序遍历、中序遍历、后序遍历。 ![二叉搜索树的前、中、后序遍历](binary_tree_traversal.assets/binary_tree_dfs.png)
-| 位置 | 含义 | 此处访问结点时对应 | +| 位置 | 含义 | 此处访问节点时对应 | | ---------- | ------------------------------------ | ----------------------------- | -| 橙色圆圈处 | 刚进入此结点,即将访问该结点的左子树 | 前序遍历 Pre-Order Traversal | +| 橙色圆圈处 | 刚进入此节点,即将访问该节点的左子树 | 前序遍历 Pre-Order Traversal | | 蓝色圆圈处 | 已访问完左子树,即将访问右子树 | 中序遍历 In-Order Traversal | | 紫色圆圈处 | 已访问完左子树和右子树,即将返回 | 后序遍历 Post-Order Traversal | @@ -208,6 +208,6 @@ ### 复杂度分析 -**时间复杂度**:所有结点被访问一次,使用 $O(n)$ 时间,其中 $n$ 为结点数量。 +**时间复杂度**:所有节点被访问一次,使用 $O(n)$ 时间,其中 $n$ 为节点数量。 **空间复杂度**:当树退化为链表时达到最差情况,递归深度达到 $n$ ,系统使用 $O(n)$ 栈帧空间。 diff --git a/docs/chapter_tree/summary.md b/docs/chapter_tree/summary.md index c2a77769..9bebc972 100644 --- a/docs/chapter_tree/summary.md +++ b/docs/chapter_tree/summary.md @@ -2,12 +2,12 @@ ### 二叉树 -- 二叉树是一种非线性数据结构,代表着“一分为二”的分治逻辑。二叉树的结点包含「值」和两个「指针」,分别指向左子结点和右子结点。 -- 选定二叉树中某结点,将其左(右)子结点以下形成的树称为左(右)子树。 -- 二叉树的术语较多,包括根结点、叶结点、层、度、边、高度、深度等。 -- 二叉树的初始化、结点插入、结点删除操作与链表的操作方法类似。 +- 二叉树是一种非线性数据结构,代表着“一分为二”的分治逻辑。二叉树的节点包含「值」和两个「指针」,分别指向左子节点和右子节点。 +- 选定二叉树中某节点,将其左(右)子节点以下形成的树称为左(右)子树。 +- 二叉树的术语较多,包括根节点、叶节点、层、度、边、高度、深度等。 +- 二叉树的初始化、节点插入、节点删除操作与链表的操作方法类似。 - 常见的二叉树类型包括完美二叉树、完全二叉树、完满二叉树、平衡二叉树。完美二叉树是理想状态,链表则是退化后的最差状态。 -- 二叉树可以使用数组表示,具体做法是将结点值和空位按照层序遍历的顺序排列,并基于父结点和子结点之间的索引映射公式实现指针。 +- 二叉树可以使用数组表示,具体做法是将节点值和空位按照层序遍历的顺序排列,并基于父节点和子节点之间的索引映射公式实现指针。 ### 二叉树遍历 @@ -17,5 +17,5 @@ ### 二叉搜索树 - 二叉搜索树是一种高效的元素查找数据结构,查找、插入、删除操作的时间复杂度皆为 $O(\log n)$ 。二叉搜索树退化为链表后,各项时间复杂度劣化至 $O(n)$ ,因此如何避免退化是非常重要的课题。 -- AVL 树又称平衡二叉搜索树,其通过旋转操作,使得在不断插入与删除结点后,仍然可以保持二叉树的平衡(不退化)。 -- AVL 树的旋转操作分为右旋、左旋、先右旋后左旋、先左旋后右旋。在插入或删除结点后,AVL 树会从底至顶地执行旋转操作,使树恢复平衡。 +- AVL 树又称平衡二叉搜索树,其通过旋转操作,使得在不断插入与删除节点后,仍然可以保持二叉树的平衡(不退化)。 +- AVL 树的旋转操作分为右旋、左旋、先右旋后左旋、先左旋后右旋。在插入或删除节点后,AVL 树会从底至顶地执行旋转操作,使树恢复平衡。