refactor: Replace 结点 with 节点 (#452)

* Replace 结点 with 节点
Update the footnotes in the figures

* Update mindmap

* Reduce the size of the mindmap.png
This commit is contained in:
Yudong Jin 2023-04-09 04:32:17 +08:00 committed by GitHub
parent 3f4e32b2b0
commit 1c8b7ef559
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
395 changed files with 2056 additions and 2056 deletions

View File

@ -6,14 +6,14 @@
#include "../include/include.h" #include "../include/include.h"
/* 在链表的结点 n0 之后插入结点 P */ /* 在链表的节点 n0 之后插入节点 P */
void insert(ListNode* n0, ListNode* P) { void insert(ListNode* n0, ListNode* P) {
ListNode *n1 = n0->next; ListNode *n1 = n0->next;
P->next = n1; P->next = n1;
n0->next = P; n0->next = P;
} }
/* 删除链表的结点 n0 之后的首个结点 */ /* 删除链表的节点 n0 之后的首个节点 */
// 由于引入了 stdio.h ,此处无法使用 remove 关键词 // 由于引入了 stdio.h ,此处无法使用 remove 关键词
// 详见 https://github.com/krahets/hello-algo/pull/244#discussion_r1067863888 // 详见 https://github.com/krahets/hello-algo/pull/244#discussion_r1067863888
void removeNode(ListNode* n0) { void removeNode(ListNode* n0) {
@ -27,7 +27,7 @@ void removeNode(ListNode* n0) {
free(P); free(P);
} }
/* 访问链表中索引为 index 的点 */ /* 访问链表中索引为 index 的点 */
ListNode* access(ListNode* head, int index) { ListNode* access(ListNode* head, int index) {
while (head && head->next && index) { while (head && head->next && index) {
head = head->next; head = head->next;
@ -36,7 +36,7 @@ ListNode* access(ListNode* head, int index) {
return head; return head;
} }
/* 在链表中查找值为 target 的首个点 */ /* 在链表中查找值为 target 的首个点 */
int find(ListNode* head, int target) { int find(ListNode* head, int target) {
int index = 0; int index = 0;
while (head) { while (head) {
@ -52,7 +52,7 @@ int find(ListNode* head, int target) {
/* Driver Code */ /* Driver Code */
int main() { int main() {
/* 初始化链表 */ /* 初始化链表 */
// 初始化各个 // 初始化各个
ListNode* n0 = newListNode(1); ListNode* n0 = newListNode(1);
ListNode* n1 = newListNode(3); ListNode* n1 = newListNode(3);
ListNode* n2 = newListNode(2); ListNode* n2 = newListNode(2);
@ -66,23 +66,23 @@ int main() {
printf("初始化的链表为\r\n"); printf("初始化的链表为\r\n");
printLinkedList(n0); printLinkedList(n0);
/* 插入点 */ /* 插入点 */
insert(n0, newListNode(0)); insert(n0, newListNode(0));
printf("插入点后的链表为\r\n"); printf("插入点后的链表为\r\n");
printLinkedList(n0); printLinkedList(n0);
/* 删除点 */ /* 删除点 */
removeNode(n0); removeNode(n0);
printf("删除点后的链表为\r\n"); printf("删除点后的链表为\r\n");
printLinkedList(n0); printLinkedList(n0);
/* 访问点 */ /* 访问点 */
ListNode* node = access(n0, 3); ListNode* node = access(n0, 3);
printf("链表中索引 3 处的点的值 = %d\r\n", node->val); printf("链表中索引 3 处的点的值 = %d\r\n", node->val);
/* 查找点 */ /* 查找点 */
int index = find(n0, 2); int index = find(n0, 2);
printf("链表中值为 2 的点的索引 = %d\r\n", index); printf("链表中值为 2 的点的索引 = %d\r\n", index);
return 0; return 0;
} }

View File

@ -27,23 +27,23 @@ maxHeap *newMaxHeap(int nums[], int size) {
h->size = size; h->size = size;
memcpy(h->data, nums, size * sizeof(int)); memcpy(h->data, nums, size * sizeof(int));
for (int i = size - 1; i >= 0; i--) { for (int i = size - 1; i >= 0; i--) {
// 堆化除叶结点以外的其他所有结 // 堆化除叶节点以外的其他所有节
siftDown(h, i); siftDown(h, i);
} }
return h; return h;
} }
/* 获取左子点索引 */ /* 获取左子点索引 */
int left(maxHeap *h, int i) { int left(maxHeap *h, int i) {
return 2 * i + 1; return 2 * i + 1;
} }
/* 获取右子点索引 */ /* 获取右子点索引 */
int right(maxHeap *h, int i) { int right(maxHeap *h, int i) {
return 2 * i + 2; return 2 * i + 2;
} }
/* 获取父点索引 */ /* 获取父点索引 */
int parent(maxHeap *h, int i) { int parent(maxHeap *h, int i) {
return (i - 1) / 2; return (i - 1) / 2;
} }
@ -72,12 +72,12 @@ int peek(maxHeap *h) {
/* 元素入堆 */ /* 元素入堆 */
int push(maxHeap *h, int val) { int push(maxHeap *h, int val) {
// 默认情况下,不应该添加这么多 // 默认情况下,不应该添加这么多
if (h->size == MAX_SIZE) { if (h->size == MAX_SIZE) {
printf("heap is full!"); printf("heap is full!");
return NIL; return NIL;
} }
// 添加 // 添加
h->data[h->size] = val; h->data[h->size] = val;
h->size++; h->size++;
@ -92,9 +92,9 @@ int pop(maxHeap *h) {
printf("heap is empty!"); printf("heap is empty!");
return NIL; return NIL;
} }
// 交换根结点与最右叶结点(即交换首元素与尾元素) // 交换根节点与最右叶节点(即交换首元素与尾元素)
swap(h, 0, size(h) - 1); swap(h, 0, size(h) - 1);
// 删除 // 删除
int val = h->data[h->size - 1]; int val = h->data[h->size - 1];
h->size--; h->size--;
// 从顶至底堆化 // 从顶至底堆化
@ -105,10 +105,10 @@ int pop(maxHeap *h) {
} }
/* 从点 i 开始,从顶至底堆化 */ /* 从点 i 开始,从顶至底堆化 */
void siftDown(maxHeap *h, int i) { void siftDown(maxHeap *h, int i) {
while (true) { while (true) {
// 判断结点 i, l, r 中值最大的结点,记为 max // 判断节点 i, l, r 中值最大的节点,记为 max
int l = left(h, i); int l = left(h, i);
int r = right(h, i); int r = right(h, i);
int max = i; int max = i;
@ -118,27 +118,27 @@ void siftDown(maxHeap *h, int i) {
if (r < size(h) && h->data[r] > h->data[max]) { if (r < size(h) && h->data[r] > h->data[max]) {
max = r; max = r;
} }
// 若点 i 最大或索引 l, r 越界,则无需继续堆化,跳出 // 若点 i 最大或索引 l, r 越界,则无需继续堆化,跳出
if (max == i) { if (max == i) {
break; break;
} }
// 交换两 // 交换两
swap(h, i, max); swap(h, i, max);
// 循环向下堆化 // 循环向下堆化
i = max; i = max;
} }
} }
/* 从点 i 开始,从底至顶堆化 */ /* 从点 i 开始,从底至顶堆化 */
void siftUp(maxHeap *h, int i) { void siftUp(maxHeap *h, int i) {
while (true) { while (true) {
// 获取结点 i 的父结 // 获取节点 i 的父节
int p = parent(h, i); int p = parent(h, i);
// 当“越过根结点”或“结点无需修复”时,结束堆化 // 当“越过根节点”或“节点无需修复”时,结束堆化
if (p < 0 || h->data[i] <= h->data[p]) { if (p < 0 || h->data[i] <= h->data[p]) {
break; break;
} }
// 交换两 // 交换两
swap(h, i, p); swap(h, i, p);
// 循环向上堆化 // 循环向上堆化
i = p; i = p;

View File

@ -22,12 +22,12 @@ int linearSearchArray(int *nums, int len, int target) {
ListNode* linearSearchLinkedList(ListNode* head, int target) { ListNode* linearSearchLinkedList(ListNode* head, int target) {
// 遍历链表 // 遍历链表
while (head != NULL) { while (head != NULL) {
// 找到目标点,返回之 // 找到目标点,返回之
if (head->val == target) if (head->val == target)
return head; return head;
head = head->next; head = head->next;
} }
// 未找到目标点,返回 NULL // 未找到目标点,返回 NULL
return NULL; return NULL;
} }
@ -44,9 +44,9 @@ int main() {
ListNode* head = arrToLinkedList(nums, 10); ListNode* head = arrToLinkedList(nums, 10);
ListNode* node = linearSearchLinkedList(head, target); ListNode* node = linearSearchLinkedList(head, target);
if(node == NULL) { if(node == NULL) {
printf("目标结点值 3 的对应结点对象为 NULL\n"); printf("目标节点值 3 的对应节点对象为 NULL\n");
} else { } else {
printf("目标结点值 3 的对应结点对象为 addr: %p val: %d\n", node, node->val); printf("目标节点值 3 的对应节点对象为 addr: %p val: %d\n", node, node->val);
} }
return 0; return 0;

View File

@ -6,16 +6,16 @@
#include "../include/include.h" #include "../include/include.h"
/* 双向链表点 */ /* 双向链表点 */
struct DoublyListNode { struct DoublyListNode {
int val; // 点值 int val; // 点值
struct DoublyListNode *next; // 后继 struct DoublyListNode *next; // 后继
struct DoublyListNode *prev; // 前驱 struct DoublyListNode *prev; // 前驱
}; };
typedef struct DoublyListNode DoublyListNode; typedef struct DoublyListNode DoublyListNode;
/* 双向链表点构造方法 */ /* 双向链表点构造方法 */
DoublyListNode *newDoublyListNode(int num) { DoublyListNode *newDoublyListNode(int num) {
DoublyListNode* new = (DoublyListNode *) malloc(sizeof(DoublyListNode)); DoublyListNode* new = (DoublyListNode *) malloc(sizeof(DoublyListNode));
new->val = num; new->val = num;
@ -24,14 +24,14 @@ DoublyListNode *newDoublyListNode(int num) {
return new; return new;
} }
/* 双向链表点析构方法 */ /* 双向链表点析构方法 */
void delDoublyListNode(DoublyListNode *node) { void delDoublyListNode(DoublyListNode *node) {
free(node); free(node);
} }
/* 基于双向链表实现的双向队列 */ /* 基于双向链表实现的双向队列 */
struct LinkedListDeque { struct LinkedListDeque {
DoublyListNode *front, *rear; // 头结点 front ,尾结点 rear DoublyListNode *front, *rear; // 头节点 front ,尾节点 rear
int queSize; // 双向队列的长度 int queSize; // 双向队列的长度
}; };
@ -47,7 +47,7 @@ LinkedListDeque *newLinkedListDeque() {
/* 析构方法 */ /* 析构方法 */
void delLinkedListdeque(LinkedListDeque *deque) { void delLinkedListdeque(LinkedListDeque *deque) {
// 释放所有 // 释放所有
for (int i=0; i<deque->queSize && deque->front != NULL; i++) { for (int i=0; i<deque->queSize && deque->front != NULL; i++) {
DoublyListNode *tmp = deque->front; DoublyListNode *tmp = deque->front;
deque->front = deque->front->next; deque->front = deque->front->next;
@ -79,7 +79,7 @@ void push(LinkedListDeque *deque, int num, bool isFront) {
// 将 node 添加至链表头部 // 将 node 添加至链表头部
deque->front->prev = node; deque->front->prev = node;
node->next = deque->front; node->next = deque->front;
deque->front = node;// 更新头 deque->front = node;// 更新头
} }
// 对尾入队操作 // 对尾入队操作
else { else {
@ -120,25 +120,25 @@ int pop(LinkedListDeque *deque, bool isFront) {
int val; int val;
// 队首出队操作 // 队首出队操作
if(isFront) { if(isFront) {
val = peekFirst(deque); // 暂存头点值 val = peekFirst(deque); // 暂存头点值
DoublyListNode *fNext = deque->front->next; DoublyListNode *fNext = deque->front->next;
if (fNext) { if (fNext) {
fNext->prev = NULL; fNext->prev = NULL;
deque->front->next = NULL; deque->front->next = NULL;
delDoublyListNode(deque->front); delDoublyListNode(deque->front);
} }
deque->front = fNext; // 更新头 deque->front = fNext; // 更新头
} }
// 队尾出队操作 // 队尾出队操作
else { else {
val = peekLast(deque); // 暂存尾点值 val = peekLast(deque); // 暂存尾点值
DoublyListNode *rPrev = deque->rear->prev; DoublyListNode *rPrev = deque->rear->prev;
if (rPrev) { if (rPrev) {
rPrev->next = NULL; rPrev->next = NULL;
deque->rear->prev = NULL; deque->rear->prev = NULL;
delDoublyListNode(deque->rear); delDoublyListNode(deque->rear);
} }
deque->rear = rPrev; // 更新尾 deque->rear = rPrev; // 更新尾
} }
deque->queSize--; // 更新队列长度 deque->queSize--; // 更新队列长度
return val; return val;

View File

@ -24,7 +24,7 @@ LinkedListQueue *newLinkedListQueue() {
/* 析构方法 */ /* 析构方法 */
void delLinkedListQueue(LinkedListQueue *queue) { void delLinkedListQueue(LinkedListQueue *queue) {
// 释放所有 // 释放所有
for (int i=0; i<queue->queSize && queue->front != NULL; i++) { for (int i=0; i<queue->queSize && queue->front != NULL; i++) {
ListNode *tmp = queue->front; ListNode *tmp = queue->front;
queue->front = queue->front->next; queue->front = queue->front->next;
@ -46,14 +46,14 @@ bool empty(LinkedListQueue *queue) {
/* 入队 */ /* 入队 */
void push(LinkedListQueue *queue, int num) { void push(LinkedListQueue *queue, int num) {
// 尾点处添加 node // 尾点处添加 node
ListNode *node = newListNode(num); ListNode *node = newListNode(num);
// 如果队列为空,则令头、尾结点都指向该结 // 如果队列为空,则令头、尾节点都指向该节
if (queue->front == NULL) { if (queue->front == NULL) {
queue->front = node; queue->front = node;
queue->rear = node; queue->rear = node;
} }
// 如果队列不为空,则将该结点添加到尾结点后 // 如果队列不为空,则将该节点添加到尾节点后
else { else {
queue->rear->next = node; queue->rear->next = node;
queue->rear = node; queue->rear = node;

View File

@ -8,7 +8,7 @@
/* 基于链表实现的栈 */ /* 基于链表实现的栈 */
struct linkedListStack { struct linkedListStack {
ListNode *top; // 将头点作为栈顶 ListNode *top; // 将头点作为栈顶
int size; // 栈的长度 int size; // 栈的长度
}; };
@ -55,8 +55,8 @@ int peek(linkedListStack *s) {
void push(linkedListStack *s, int num) { void push(linkedListStack *s, int num) {
assert(s); assert(s);
ListNode *node = (ListNode *) malloc(sizeof(ListNode)); ListNode *node = (ListNode *) malloc(sizeof(ListNode));
node->next = s->top; // 更新新加点指针域 node->next = s->top; // 更新新加点指针域
node->val = num; // 更新新加点数据域 node->val = num; // 更新新加点数据域
s->top = node; // 更新栈顶 s->top = node; // 更新栈顶
s->size++; // 更新栈大小 s->size++; // 更新栈大小
} }

View File

@ -21,18 +21,18 @@ avlTree *newAVLTree() {
} }
int height(TreeNode *node) { int height(TreeNode *node) {
// 空结点高度为 -1 ,叶结点高度为 0 // 空节点高度为 -1 ,叶节点高度为 0
if (node != NULL) { if (node != NULL) {
return node->height; return node->height;
} }
return -1; return -1;
} }
/* 更新点高度 */ /* 更新点高度 */
int updateHeight(TreeNode *node) { int updateHeight(TreeNode *node) {
int lh = height(node->left); int lh = height(node->left);
int rh = height(node->right); int rh = height(node->right);
// 点高度等于最高子树高度 + 1 // 点高度等于最高子树高度 + 1
if (lh > rh) { if (lh > rh) {
node->height = lh + 1; node->height = lh + 1;
} else { } else {
@ -42,11 +42,11 @@ int updateHeight(TreeNode *node) {
/* 获取平衡因子 */ /* 获取平衡因子 */
int balanceFactor(TreeNode *node) { int balanceFactor(TreeNode *node) {
// 空点平衡因子为 0 // 空点平衡因子为 0
if (node == NULL) { if (node == NULL) {
return 0; return 0;
} }
// 点平衡因子 = 左子树高度 - 右子树高度 // 点平衡因子 = 左子树高度 - 右子树高度
return height(node->left) - height(node->right); return height(node->left) - height(node->right);
} }
@ -58,10 +58,10 @@ TreeNode *rightRotate(TreeNode *node) {
// 以 child 为原点,将 node 向右旋转 // 以 child 为原点,将 node 向右旋转
child->right = node; child->right = node;
node->left = grandChild; node->left = grandChild;
// 更新点高度 // 更新点高度
updateHeight(node); updateHeight(node);
updateHeight(child); updateHeight(child);
// 返回旋转后子树的根 // 返回旋转后子树的根
return child; return child;
} }
@ -73,16 +73,16 @@ TreeNode *leftRotate(TreeNode *node) {
// 以 child 为原点,将 node 向左旋转 // 以 child 为原点,将 node 向左旋转
child->left = node; child->left = node;
node->right = grandChild; node->right = grandChild;
// 更新点高度 // 更新点高度
updateHeight(node); updateHeight(node);
updateHeight(child); updateHeight(child);
// 返回旋转后子树的根 // 返回旋转后子树的根
return child; return child;
} }
/* 执行旋转操作,使该子树重新恢复平衡 */ /* 执行旋转操作,使该子树重新恢复平衡 */
TreeNode *rotate(TreeNode *node) { TreeNode *rotate(TreeNode *node) {
// 获取点 node 的平衡因子 // 获取点 node 的平衡因子
int bf = balanceFactor(node); int bf = balanceFactor(node);
// 左偏树 // 左偏树
if (bf > 1) { if (bf > 1) {
@ -110,54 +110,54 @@ TreeNode *rotate(TreeNode *node) {
return node; return node;
} }
/* 递归插入点(辅助方法) */ /* 递归插入点(辅助方法) */
TreeNode *insertHelper(TreeNode *node, int val) { TreeNode *insertHelper(TreeNode *node, int val) {
if (node == NULL) { if (node == NULL) {
return newTreeNode(val); return newTreeNode(val);
} }
/* 1. 查找插入位置,并插入点 */ /* 1. 查找插入位置,并插入点 */
if (val < node->val) { if (val < node->val) {
node->left = insertHelper(node->left, val); node->left = insertHelper(node->left, val);
} else if (val > node->val) { } else if (val > node->val) {
node->right = insertHelper(node->right, val); node->right = insertHelper(node->right, val);
} else { } else {
// 重复点不插入,直接返回 // 重复点不插入,直接返回
return node; return node;
} }
// 更新点高度 // 更新点高度
updateHeight(node); updateHeight(node);
/* 2. 执行旋转操作,使该子树重新恢复平衡 */ /* 2. 执行旋转操作,使该子树重新恢复平衡 */
node = rotate(node); node = rotate(node);
// 返回子树的根 // 返回子树的根
return node; return node;
} }
/* 插入点 */ /* 插入点 */
TreeNode *insert(avlTree *tree, int val) { TreeNode *insert(avlTree *tree, int val) {
tree->root = insertHelper(tree->root, val); tree->root = insertHelper(tree->root, val);
return tree->root; return tree->root;
} }
/* 获取中序遍历中的下一个结点(仅适用于 root 有左子结点的情况) */ /* 获取中序遍历中的下一个节点(仅适用于 root 有左子节点的情况) */
TreeNode *getInOrderNext(TreeNode *node) { TreeNode *getInOrderNext(TreeNode *node) {
if (node == NULL) { if (node == NULL) {
return node; return node;
} }
// 循环访问左子结点,直到叶结点时为最小结点,跳出 // 循环访问左子节点,直到叶节点时为最小节点,跳出
while (node->left != NULL) { while (node->left != NULL) {
node = node->left; node = node->left;
} }
return node; return node;
} }
/* 递归删除点(辅助方法) */ /* 递归删除点(辅助方法) */
TreeNode *removeHelper(TreeNode *node, int val) { TreeNode *removeHelper(TreeNode *node, int val) {
TreeNode *child, *grandChild, *temp; TreeNode *child, *grandChild, *temp;
if (node == NULL) { if (node == NULL) {
return NULL; return NULL;
} }
/* 1. 查找点,并删除之 */ /* 1. 查找点,并删除之 */
if (val < node->val) { if (val < node->val) {
node->left = removeHelper(node->left, val); node->left = removeHelper(node->left, val);
} else if (val > node->val) { } else if (val > node->val) {
@ -168,64 +168,64 @@ TreeNode *removeHelper(TreeNode *node, int val) {
if (node->right != NULL) { if (node->right != NULL) {
child = node->right; child = node->right;
} }
// 子点数量 = 0 ,直接删除 node 并返回 // 子点数量 = 0 ,直接删除 node 并返回
if (child == NULL) { if (child == NULL) {
return NULL; return NULL;
} else { } else {
// 子点数量 = 1 ,直接删除 node // 子点数量 = 1 ,直接删除 node
node = child; node = child;
} }
} else { } else {
// 子结点数量 = 2 ,则将中序遍历的下个结点删除,并用该结点替换当前结 // 子节点数量 = 2 ,则将中序遍历的下个节点删除,并用该节点替换当前节
temp = getInOrderNext(node->right); temp = getInOrderNext(node->right);
node->right = removeHelper(node->right, temp->val); node->right = removeHelper(node->right, temp->val);
node->val = temp->val; node->val = temp->val;
} }
} }
// 更新点高度 // 更新点高度
updateHeight(node); updateHeight(node);
/* 2. 执行旋转操作,使该子树重新恢复平衡 */ /* 2. 执行旋转操作,使该子树重新恢复平衡 */
node = rotate(node); node = rotate(node);
// 返回子树的根 // 返回子树的根
return node; return node;
} }
/* 删除点 */ /* 删除点 */
// 由于引入了 stdio.h ,此处无法使用 remove 关键词 // 由于引入了 stdio.h ,此处无法使用 remove 关键词
TreeNode *removeNode(avlTree *tree, int val) { TreeNode *removeNode(avlTree *tree, int val) {
TreeNode *root = removeHelper(tree->root, val); TreeNode *root = removeHelper(tree->root, val);
return root; return root;
} }
/* 查找点 */ /* 查找点 */
TreeNode *search(avlTree *tree, int val) { TreeNode *search(avlTree *tree, int val) {
TreeNode *cur = tree->root; TreeNode *cur = tree->root;
// 循环查找,越过叶点后跳出 // 循环查找,越过叶点后跳出
while (cur != NULL) { while (cur != NULL) {
if (cur->val < val) { if (cur->val < val) {
// 目标点在 cur 的右子树中 // 目标点在 cur 的右子树中
cur = cur->right; cur = cur->right;
} else if (cur->val > val) { } else if (cur->val > val) {
// 目标点在 cur 的左子树中 // 目标点在 cur 的左子树中
cur = cur->left; cur = cur->left;
} else { } else {
// 找到目标点,跳出循环 // 找到目标点,跳出循环
break; break;
} }
} }
// 找到目标点,跳出循环 // 找到目标点,跳出循环
return cur; return cur;
} }
void testInsert(avlTree *tree, int val) { void testInsert(avlTree *tree, int val) {
insert(tree, val); insert(tree, val);
printf("\n插入点 %d 后AVL 树为 \n", val); printf("\n插入点 %d 后AVL 树为 \n", val);
printTree(tree->root); printTree(tree->root);
} }
void testRemove(avlTree *tree, int val) { void testRemove(avlTree *tree, int val) {
removeNode(tree, val); removeNode(tree, val);
printf("\n删除点 %d 后AVL 树为 \n", val); printf("\n删除点 %d 后AVL 树为 \n", val);
printTree(tree->root); printTree(tree->root);
} }
@ -233,8 +233,8 @@ void testRemove(avlTree *tree, int val) {
int main() { int main() {
/* 初始化空 AVL 树 */ /* 初始化空 AVL 树 */
avlTree *tree = (avlTree *) newAVLTree(); avlTree *tree = (avlTree *) newAVLTree();
/* 插入点 */ /* 插入点 */
// 请关注插入点后AVL 树是如何保持平衡的 // 请关注插入点后AVL 树是如何保持平衡的
testInsert(tree, 1); testInsert(tree, 1);
testInsert(tree, 2); testInsert(tree, 2);
testInsert(tree, 3); testInsert(tree, 3);
@ -246,16 +246,16 @@ int main() {
testInsert(tree, 10); testInsert(tree, 10);
testInsert(tree, 6); testInsert(tree, 6);
/* 插入重复点 */ /* 插入重复点 */
testInsert(tree, 7); testInsert(tree, 7);
/* 删除点 */ /* 删除点 */
// 请关注删除点后AVL 树是如何保持平衡的 // 请关注删除点后AVL 树是如何保持平衡的
testRemove(tree, 8); // 删除度为 0 的 testRemove(tree, 8); // 删除度为 0 的
testRemove(tree, 5); // 删除度为 1 的 testRemove(tree, 5); // 删除度为 1 的
testRemove(tree, 4); // 删除度为 2 的 testRemove(tree, 4); // 删除度为 2 的
/* 查询点 */ /* 查询点 */
TreeNode *node = search(tree, 7); TreeNode *node = search(tree, 7);
printf("\n查找到的结点对象结点值 = %d \n", node->val); printf("\n查找到的节点对象节点值 = %d \n", node->val);
} }

View File

@ -23,7 +23,7 @@ TreeNode *buildTree(int nums[], int i, int j) {
if (i > j) { if (i > j) {
return NULL; return NULL;
} }
// 将数组中间结点作为根结 // 将数组中间节点作为根节
int mid = (i + j) / 2; int mid = (i + j) / 2;
TreeNode *root = newTreeNode(nums[mid]); TreeNode *root = newTreeNode(nums[mid]);
// 递归建立左子树和右子树 // 递归建立左子树和右子树
@ -43,39 +43,39 @@ binarySearchTree *newBinarySearchTree(int nums[], int size) {
return bst; return bst;
} }
/* 获取二叉树根点 */ /* 获取二叉树根点 */
TreeNode *getRoot(binarySearchTree *bst) { TreeNode *getRoot(binarySearchTree *bst) {
return bst->root; return bst->root;
} }
/* 查找点 */ /* 查找点 */
TreeNode *search(binarySearchTree *bst, int num) { TreeNode *search(binarySearchTree *bst, int num) {
TreeNode *cur = bst->root; TreeNode *cur = bst->root;
// 循环查找,越过叶点后跳出 // 循环查找,越过叶点后跳出
while (cur != NULL) { while (cur != NULL) {
if (cur->val < num) { if (cur->val < num) {
// 目标点在 cur 的右子树中 // 目标点在 cur 的右子树中
cur = cur->right; cur = cur->right;
} else if (cur->val > num) { } else if (cur->val > num) {
// 目标点在 cur 的左子树中 // 目标点在 cur 的左子树中
cur = cur->left; cur = cur->left;
} else { } else {
// 找到目标点,跳出循环 // 找到目标点,跳出循环
break; break;
} }
} }
// 返回目标 // 返回目标
return cur; return cur;
} }
/* 插入点 */ /* 插入点 */
TreeNode *insert(binarySearchTree *bst, int num) { TreeNode *insert(binarySearchTree *bst, int num) {
// 若树为空,直接提前返回 // 若树为空,直接提前返回
if (bst->root == NULL) return NULL; if (bst->root == NULL) return NULL;
TreeNode *cur = bst->root, *pre = NULL; TreeNode *cur = bst->root, *pre = NULL;
// 循环查找,越过叶点后跳出 // 循环查找,越过叶点后跳出
while (cur != NULL) { while (cur != NULL) {
// 找到重复点,直接返回 // 找到重复点,直接返回
if (cur->val == num) { if (cur->val == num) {
return NULL; return NULL;
} }
@ -88,7 +88,7 @@ TreeNode *insert(binarySearchTree *bst, int num) {
cur = cur->left; cur = cur->left;
} }
} }
// 插入点 val // 插入点 val
TreeNode *node = newTreeNode(num); TreeNode *node = newTreeNode(num);
if (pre->val < num) { if (pre->val < num) {
pre->right = node; pre->right = node;
@ -98,56 +98,56 @@ TreeNode *insert(binarySearchTree *bst, int num) {
return node; return node;
} }
/* 获取中序遍历中的下一个结点(仅适用于 root 有左子结点的情况) */ /* 获取中序遍历中的下一个节点(仅适用于 root 有左子节点的情况) */
TreeNode *getInOrderNext(TreeNode *root) { TreeNode *getInOrderNext(TreeNode *root) {
if (root == NULL) return root; if (root == NULL) return root;
// 循环访问左子结点,直到叶结点时为最小结点,跳出 // 循环访问左子节点,直到叶节点时为最小节点,跳出
while (root->left != NULL) { while (root->left != NULL) {
root = root->left; root = root->left;
} }
return root; return root;
} }
/* 删除点 */ /* 删除点 */
// 由于引入了 stdio.h ,此处无法使用 remove 关键词 // 由于引入了 stdio.h ,此处无法使用 remove 关键词
TreeNode *removeNode(binarySearchTree *bst, int num) { TreeNode *removeNode(binarySearchTree *bst, int num) {
// 若树为空,直接提前返回 // 若树为空,直接提前返回
if (bst->root == NULL) return NULL; if (bst->root == NULL) return NULL;
TreeNode *cur = bst->root, *pre = NULL; TreeNode *cur = bst->root, *pre = NULL;
// 循环查找,越过叶点后跳出 // 循环查找,越过叶点后跳出
while (cur != NULL) { while (cur != NULL) {
// 找到待删除点,跳出循环 // 找到待删除点,跳出循环
if (cur->val == num) break; if (cur->val == num) break;
pre = cur; pre = cur;
if (cur->val < num) { if (cur->val < num) {
// 待删除点在 root 的右子树中 // 待删除点在 root 的右子树中
cur = cur->right; cur = cur->right;
} else { } else {
// 待删除点在 root 的左子树中 // 待删除点在 root 的左子树中
cur = cur->left; cur = cur->left;
} }
} }
// 若无待删除点,则直接返回 // 若无待删除点,则直接返回
if (cur == NULL) { if (cur == NULL) {
return NULL; return NULL;
} }
// 判断待删除结点是否存在子结 // 判断待删除节点是否存在子节
if (cur->left == NULL || cur->right == NULL) { if (cur->left == NULL || cur->right == NULL) {
/* 子点数量 = 0 or 1 */ /* 子点数量 = 0 or 1 */
// 当子结点数量 = 0 / 1 时, child = nullptr / 该子结 // 当子节点数量 = 0 / 1 时, child = nullptr / 该子节
TreeNode *child = cur->left != NULL ? cur->left : cur->right; TreeNode *child = cur->left != NULL ? cur->left : cur->right;
// 删除点 cur // 删除点 cur
if (pre->left == cur) { if (pre->left == cur) {
pre->left = child; pre->left = child;
} else { } else {
pre->right = child; pre->right = child;
} }
} else { } else {
/* 子点数量 = 2 */ /* 子点数量 = 2 */
// 获取中序遍历中 cur 的下一个 // 获取中序遍历中 cur 的下一个
TreeNode *nex = getInOrderNext(cur->right); TreeNode *nex = getInOrderNext(cur->right);
int tmp = nex->val; int tmp = nex->val;
// 递归删除点 nex // 递归删除点 nex
removeNode(bst, nex->val); removeNode(bst, nex->val);
// 将 nex 的值复制给 cur // 将 nex 的值复制给 cur
cur->val = tmp; cur->val = tmp;
@ -163,26 +163,26 @@ int main() {
printf("初始化的二叉树为\n"); printf("初始化的二叉树为\n");
printTree(getRoot(bst)); printTree(getRoot(bst));
/* 查找点 */ /* 查找点 */
TreeNode *node = search(bst, 7); TreeNode *node = search(bst, 7);
printf("查找到的结点对象的结点值 = %d\n", node->val); printf("查找到的节点对象的节点值 = %d\n", node->val);
/* 插入点 */ /* 插入点 */
insert(bst, 16); insert(bst, 16);
printf("插入点 16 后,二叉树为\n"); printf("插入点 16 后,二叉树为\n");
printTree(getRoot(bst)); printTree(getRoot(bst));
/* 删除点 */ /* 删除点 */
removeNode(bst, 1); removeNode(bst, 1);
printf("删除点 1 后,二叉树为\n"); printf("删除点 1 后,二叉树为\n");
printTree(getRoot(bst)); printTree(getRoot(bst));
removeNode(bst, 2); removeNode(bst, 2);
printf("删除点 2 后,二叉树为\n"); printf("删除点 2 后,二叉树为\n");
printTree(getRoot(bst)); printTree(getRoot(bst));
removeNode(bst, 4); removeNode(bst, 4);
printf("删除点 4 后,二叉树为\n"); printf("删除点 4 后,二叉树为\n");
printTree(getRoot(bst)); printTree(getRoot(bst));
// 释放内存 // 释放内存

View File

@ -9,7 +9,7 @@
/* Driver Code */ /* Driver Code */
int main() { int main() {
/* 初始化二叉树 */ /* 初始化二叉树 */
// 初始化 // 初始化
TreeNode* n1 = newTreeNode(1); TreeNode* n1 = newTreeNode(1);
TreeNode* n2 = newTreeNode(2); TreeNode* n2 = newTreeNode(2);
TreeNode* n3 = newTreeNode(3); TreeNode* n3 = newTreeNode(3);
@ -23,19 +23,19 @@ int main() {
printf("初始化二叉树\n"); printf("初始化二叉树\n");
printTree(n1); printTree(n1);
/* 插入与删除点 */ /* 插入与删除点 */
TreeNode* P = newTreeNode(0); TreeNode* P = newTreeNode(0);
// 在 n1 -> n2 中间插入点 P // 在 n1 -> n2 中间插入点 P
n1->left = P; n1->left = P;
P->left = n2; P->left = n2;
printf("插入点 P 后\n"); printf("插入点 P 后\n");
printTree(n1); printTree(n1);
// 删除点 P // 删除点 P
n1->left = n2; n1->left = n2;
// 释放内存 // 释放内存
free(P); free(P);
printf("删除点 P 后\n"); printf("删除点 P 后\n");
printTree(n1); printTree(n1);
return 0; return 0;

View File

@ -18,7 +18,7 @@ int *levelOrder(TreeNode *root, int *size) {
queue = (TreeNode **) malloc(sizeof(TreeNode) * MAX_NODE_SIZE); queue = (TreeNode **) malloc(sizeof(TreeNode) * MAX_NODE_SIZE);
// 队列指针 // 队列指针
front = 0, rear = 0; front = 0, rear = 0;
// 加入根 // 加入根
queue[rear++] = root; queue[rear++] = root;
// 初始化一个列表,用于保存遍历序列 // 初始化一个列表,用于保存遍历序列
/* 辅助数组 */ /* 辅助数组 */
@ -28,14 +28,14 @@ int *levelOrder(TreeNode *root, int *size) {
while (front < rear) { while (front < rear) {
// 队列出队 // 队列出队
node = queue[front++]; node = queue[front++];
// 保存点值 // 保存点值
arr[index++] = node->val; arr[index++] = node->val;
if (node->left != NULL) { if (node->left != NULL) {
// 左子点入队 // 左子点入队
queue[rear++] = node->left; queue[rear++] = node->left;
} }
if (node->right != NULL) { if (node->right != NULL) {
// 右子点入队 // 右子点入队
queue[rear++] = node->right; queue[rear++] = node->right;
} }
} }
@ -59,7 +59,7 @@ int main() {
/* 层序遍历 */ /* 层序遍历 */
// 需要传入数组的长度 // 需要传入数组的长度
int *arr = levelOrder(root, &size); int *arr = levelOrder(root, &size);
printf("层序遍历的点打印序列 = "); printf("层序遍历的点打印序列 = ");
printArray(arr, size); printArray(arr, size);
return 0; return 0;

View File

@ -12,7 +12,7 @@ int *arr;
/* 前序遍历 */ /* 前序遍历 */
void preOrder(TreeNode *root, int *size) { void preOrder(TreeNode *root, int *size) {
if (root == NULL) return; if (root == NULL) return;
// 访问优先级:根点 -> 左子树 -> 右子树 // 访问优先级:根点 -> 左子树 -> 右子树
arr[(*size)++] = root->val; arr[(*size)++] = root->val;
preOrder(root->left, size); preOrder(root->left, size);
preOrder(root->right, size); preOrder(root->right, size);
@ -21,7 +21,7 @@ void preOrder(TreeNode *root, int *size) {
/* 中序遍历 */ /* 中序遍历 */
void inOrder(TreeNode *root, int *size) { void inOrder(TreeNode *root, int *size) {
if (root == NULL) return; if (root == NULL) return;
// 访问优先级:左子树 -> 根点 -> 右子树 // 访问优先级:左子树 -> 根点 -> 右子树
inOrder(root->left, size); inOrder(root->left, size);
arr[(*size)++] = root->val; arr[(*size)++] = root->val;
inOrder(root->right, size); inOrder(root->right, size);
@ -30,7 +30,7 @@ void inOrder(TreeNode *root, int *size) {
/* 后序遍历 */ /* 后序遍历 */
void postOrder(TreeNode *root, int *size) { void postOrder(TreeNode *root, int *size) {
if (root == NULL) return; if (root == NULL) return;
// 访问优先级:左子树 -> 右子树 -> 根 // 访问优先级:左子树 -> 右子树 -> 根
postOrder(root->left, size); postOrder(root->left, size);
postOrder(root->right, size); postOrder(root->right, size);
arr[(*size)++] = root->val; arr[(*size)++] = root->val;
@ -52,19 +52,19 @@ int main() {
arr = (int *) malloc(sizeof(int) * MAX_NODE_SIZE); arr = (int *) malloc(sizeof(int) * MAX_NODE_SIZE);
size = 0; size = 0;
preOrder(root, &size); preOrder(root, &size);
printf("前序遍历的点打印序列 = "); printf("前序遍历的点打印序列 = ");
printArray(arr, size); printArray(arr, size);
/* 中序遍历 */ /* 中序遍历 */
size = 0; size = 0;
inOrder(root, &size); inOrder(root, &size);
printf("中序遍历的点打印序列 = "); printf("中序遍历的点打印序列 = ");
printArray(arr, size); printArray(arr, size);
/* 后序遍历 */ /* 后序遍历 */
size = 0; size = 0;
postOrder(root, &size); postOrder(root, &size);
printf("后序遍历的点打印序列 = "); printf("后序遍历的点打印序列 = ");
printArray(arr, size); printArray(arr, size);
return 0; return 0;

View File

@ -10,16 +10,16 @@
extern "C" { extern "C" {
#endif #endif
/* 链表点结构体 */ /* 链表点结构体 */
struct ListNode { struct ListNode {
int val; // 点值 int val; // 点值
struct ListNode *next; // 指向下一点的指针(引用) struct ListNode *next; // 指向下一点的指针(引用)
}; };
// typedef 作用是为一种数据类型定义一个新名字 // typedef 作用是为一种数据类型定义一个新名字
typedef struct ListNode ListNode; typedef struct ListNode ListNode;
/* 构造函数,初始化一个新点 */ /* 构造函数,初始化一个新点 */
ListNode *newListNode(int val) { ListNode *newListNode(int val) {
ListNode *node, *next; ListNode *node, *next;
node = (ListNode *) malloc(sizeof(ListNode)); node = (ListNode *) malloc(sizeof(ListNode));

View File

@ -52,18 +52,18 @@ TreeNode *arrToTree(const int *arr, size_t size) {
TreeNode *root, *node; TreeNode *root, *node;
TreeNode **queue; TreeNode **queue;
/* 根点 */ /* 根点 */
root = newTreeNode(arr[0]); root = newTreeNode(arr[0]);
/* 辅助队列 */ /* 辅助队列 */
queue = (TreeNode **) malloc(sizeof(TreeNode) * MAX_NODE_SIZE); queue = (TreeNode **) malloc(sizeof(TreeNode) * MAX_NODE_SIZE);
// 队列指针 // 队列指针
front = 0, rear = 0; front = 0, rear = 0;
// 将根点放入队尾 // 将根点放入队尾
queue[rear++] = root; queue[rear++] = root;
// 记录遍历数组的索引 // 记录遍历数组的索引
index = 0; index = 0;
while (front < rear) { while (front < rear) {
// 取队列中的头结点,并让头结点出队 // 取队列中的头节点,并让头节点出队
node = queue[front++]; node = queue[front++];
index++; index++;
if (index < size) { if (index < size) {
@ -103,14 +103,14 @@ int *treeToArr(TreeNode *root) {
queue = (TreeNode **) malloc(sizeof(TreeNode) * MAX_NODE_SIZE); queue = (TreeNode **) malloc(sizeof(TreeNode) * MAX_NODE_SIZE);
// 队列指针 // 队列指针
front = 0, rear = 0; front = 0, rear = 0;
// 将根点放入队尾 // 将根点放入队尾
queue[rear++] = root; queue[rear++] = root;
/* 辅助数组 */ /* 辅助数组 */
arr = (int *) malloc(sizeof(int) * MAX_NODE_SIZE); arr = (int *) malloc(sizeof(int) * MAX_NODE_SIZE);
// 数组指针 // 数组指针
index = 0; index = 0;
while (front < rear) { while (front < rear) {
// 取队列中的头结点,并让头结点出队 // 取队列中的头节点,并让头节点出队
node = queue[front++]; node = queue[front++];
if (node != NULL) { if (node != NULL) {
arr[index] = node->val; arr[index] = node->val;

View File

@ -6,14 +6,14 @@
#include "../include/include.hpp" #include "../include/include.hpp"
/* 在链表的结点 n0 之后插入结点 P */ /* 在链表的节点 n0 之后插入节点 P */
void insert(ListNode* n0, ListNode* P) { void insert(ListNode* n0, ListNode* P) {
ListNode* n1 = n0->next; ListNode* n1 = n0->next;
P->next = n1; P->next = n1;
n0->next = P; n0->next = P;
} }
/* 删除链表的结点 n0 之后的首个结点 */ /* 删除链表的节点 n0 之后的首个节点 */
void remove(ListNode* n0) { void remove(ListNode* n0) {
if (n0->next == nullptr) if (n0->next == nullptr)
return; return;
@ -25,7 +25,7 @@ void remove(ListNode* n0) {
delete P; delete P;
} }
/* 访问链表中索引为 index 的点 */ /* 访问链表中索引为 index 的点 */
ListNode* access(ListNode* head, int index) { ListNode* access(ListNode* head, int index) {
for (int i = 0; i < index; i++) { for (int i = 0; i < index; i++) {
if (head == nullptr) if (head == nullptr)
@ -35,7 +35,7 @@ ListNode* access(ListNode* head, int index) {
return head; return head;
} }
/* 在链表中查找值为 target 的首个点 */ /* 在链表中查找值为 target 的首个点 */
int find(ListNode* head, int target) { int find(ListNode* head, int target) {
int index = 0; int index = 0;
while (head != nullptr) { while (head != nullptr) {
@ -51,7 +51,7 @@ int find(ListNode* head, int target) {
/* Driver Code */ /* Driver Code */
int main() { int main() {
/* 初始化链表 */ /* 初始化链表 */
// 初始化各个 // 初始化各个
ListNode* n0 = new ListNode(1); ListNode* n0 = new ListNode(1);
ListNode* n1 = new ListNode(3); ListNode* n1 = new ListNode(3);
ListNode* n2 = new ListNode(2); ListNode* n2 = new ListNode(2);
@ -65,23 +65,23 @@ int main() {
cout << "初始化的链表为" << endl; cout << "初始化的链表为" << endl;
PrintUtil::printLinkedList(n0); PrintUtil::printLinkedList(n0);
/* 插入点 */ /* 插入点 */
insert(n0, new ListNode(0)); insert(n0, new ListNode(0));
cout << "插入点后的链表为" << endl; cout << "插入点后的链表为" << endl;
PrintUtil::printLinkedList(n0); PrintUtil::printLinkedList(n0);
/* 删除点 */ /* 删除点 */
remove(n0); remove(n0);
cout << "删除点后的链表为" << endl; cout << "删除点后的链表为" << endl;
PrintUtil::printLinkedList(n0); PrintUtil::printLinkedList(n0);
/* 访问点 */ /* 访问点 */
ListNode* node = access(n0, 3); ListNode* node = access(n0, 3);
cout << "链表中索引 3 处的点的值 = " << node->val << endl; cout << "链表中索引 3 处的点的值 = " << node->val << endl;
/* 查找点 */ /* 查找点 */
int index = find(n0, 2); int index = find(n0, 2);
cout << "链表中值为 2 的点的索引 = " << index << endl; cout << "链表中值为 2 的点的索引 = " << index << endl;
// 释放内存 // 释放内存
freeMemoryLinkedList(n0); freeMemoryLinkedList(n0);

View File

@ -12,7 +12,7 @@ public:
// 邻接表key: 顶点value该顶点的所有邻接顶点 // 邻接表key: 顶点value该顶点的所有邻接顶点
unordered_map<Vertex*, vector<Vertex*>> adjList; unordered_map<Vertex*, vector<Vertex*>> adjList;
/* 在 vector 中删除指定点 */ /* 在 vector 中删除指定点 */
void remove(vector<Vertex*> &vec, Vertex *vet) { void remove(vector<Vertex*> &vec, Vertex *vet) {
for (int i = 0; i < vec.size(); i++) { for (int i = 0; i < vec.size(); i++) {
if (vec[i] == vet) { if (vec[i] == vet) {

View File

@ -12,47 +12,47 @@ private:
// 使用动态数组,这样无需考虑扩容问题 // 使用动态数组,这样无需考虑扩容问题
vector<int> maxHeap; vector<int> maxHeap;
/* 获取左子点索引 */ /* 获取左子点索引 */
int left(int i) { int left(int i) {
return 2 * i + 1; return 2 * i + 1;
} }
/* 获取右子点索引 */ /* 获取右子点索引 */
int right(int i) { int right(int i) {
return 2 * i + 2; return 2 * i + 2;
} }
/* 获取父点索引 */ /* 获取父点索引 */
int parent(int i) { int parent(int i) {
return (i - 1) / 2; // 向下取整 return (i - 1) / 2; // 向下取整
} }
/* 从点 i 开始,从底至顶堆化 */ /* 从点 i 开始,从底至顶堆化 */
void siftUp(int i) { void siftUp(int i) {
while (true) { while (true) {
// 获取结点 i 的父结 // 获取节点 i 的父节
int p = parent(i); int p = parent(i);
// 当“越过根结点”或“结点无需修复”时,结束堆化 // 当“越过根节点”或“节点无需修复”时,结束堆化
if (p < 0 || maxHeap[i] <= maxHeap[p]) if (p < 0 || maxHeap[i] <= maxHeap[p])
break; break;
// 交换两 // 交换两
swap(maxHeap[i], maxHeap[p]); swap(maxHeap[i], maxHeap[p]);
// 循环向上堆化 // 循环向上堆化
i = p; i = p;
} }
} }
/* 从点 i 开始,从顶至底堆化 */ /* 从点 i 开始,从顶至底堆化 */
void siftDown(int i) { void siftDown(int i) {
while (true) { while (true) {
// 判断结点 i, l, r 中值最大的结点,记为 ma // 判断节点 i, l, r 中值最大的节点,记为 ma
int l = left(i), r = right(i), ma = i; int l = left(i), r = right(i), ma = i;
// 若点 i 最大或索引 l, r 越界,则无需继续堆化,跳出 // 若点 i 最大或索引 l, r 越界,则无需继续堆化,跳出
if (l < size() && maxHeap[l] > maxHeap[ma]) if (l < size() && maxHeap[l] > maxHeap[ma])
ma = l; ma = l;
if (r < size() && maxHeap[r] > maxHeap[ma]) if (r < size() && maxHeap[r] > maxHeap[ma])
ma = r; ma = r;
// 若点 i 最大或索引 l, r 越界,则无需继续堆化,跳出 // 若点 i 最大或索引 l, r 越界,则无需继续堆化,跳出
if (ma == i) if (ma == i)
break; break;
swap(maxHeap[i], maxHeap[ma]); swap(maxHeap[i], maxHeap[ma]);
@ -66,7 +66,7 @@ public:
MaxHeap(vector<int> nums) { MaxHeap(vector<int> nums) {
// 将列表元素原封不动添加进堆 // 将列表元素原封不动添加进堆
maxHeap = nums; maxHeap = nums;
// 堆化除叶结点以外的其他所有结 // 堆化除叶节点以外的其他所有节
for (int i = parent(size() - 1); i >= 0; i--) { for (int i = parent(size() - 1); i >= 0; i--) {
siftDown(i); siftDown(i);
} }
@ -89,7 +89,7 @@ public:
/* 元素入堆 */ /* 元素入堆 */
void push(int val) { void push(int val) {
// 添加 // 添加
maxHeap.push_back(val); maxHeap.push_back(val);
// 从底至顶堆化 // 从底至顶堆化
siftUp(size() - 1); siftUp(size() - 1);
@ -101,9 +101,9 @@ public:
if (empty()) { if (empty()) {
throw out_of_range("堆为空"); throw out_of_range("堆为空");
} }
// 交换根结点与最右叶结点(即交换首元素与尾元素) // 交换根节点与最右叶节点(即交换首元素与尾元素)
swap(maxHeap[0], maxHeap[size() - 1]); swap(maxHeap[0], maxHeap[size() - 1]);
// 删除 // 删除
maxHeap.pop_back(); maxHeap.pop_back();
// 从顶至底堆化 // 从顶至底堆化
siftDown(0); siftDown(0);

View File

@ -17,7 +17,7 @@ int hashingSearchArray(unordered_map<int, int> map, int target) {
/* 哈希查找(链表) */ /* 哈希查找(链表) */
ListNode* hashingSearchLinkedList(unordered_map<int, ListNode*> map, int target) { ListNode* hashingSearchLinkedList(unordered_map<int, ListNode*> map, int target) {
// 哈希表的 key: 目标结点值value: 结点对象 // 哈希表的 key: 目标节点值value: 节点对象
// 若哈希表中无此 key ,返回 nullptr // 若哈希表中无此 key ,返回 nullptr
if (map.find(target) == map.end()) if (map.find(target) == map.end())
return nullptr; return nullptr;
@ -44,11 +44,11 @@ int main() {
// 初始化哈希表 // 初始化哈希表
unordered_map<int, ListNode*> map1; unordered_map<int, ListNode*> map1;
while (head != nullptr) { while (head != nullptr) {
map1[head->val] = head; // key: 结点值value: 结 map1[head->val] = head; // key: 节点值value: 节
head = head->next; head = head->next;
} }
ListNode* node = hashingSearchLinkedList(map1, target); ListNode* node = hashingSearchLinkedList(map1, target);
cout << "目标结点值 3 的对应结点对象为 " << node << endl; cout << "目标节点值 3 的对应节点对象为 " << node << endl;
return 0; return 0;
} }

View File

@ -22,12 +22,12 @@ int linearSearchArray(vector<int>& nums, int target) {
ListNode* linearSearchLinkedList(ListNode* head, int target) { ListNode* linearSearchLinkedList(ListNode* head, int target) {
// 遍历链表 // 遍历链表
while (head != nullptr) { while (head != nullptr) {
// 找到目标点,返回之 // 找到目标点,返回之
if (head->val == target) if (head->val == target)
return head; return head;
head = head->next; head = head->next;
} }
// 未找到目标点,返回 nullptr // 未找到目标点,返回 nullptr
return nullptr; return nullptr;
} }
@ -44,7 +44,7 @@ int main() {
/* 在链表中执行线性查找 */ /* 在链表中执行线性查找 */
ListNode* head = vecToLinkedList(nums); ListNode* head = vecToLinkedList(nums);
ListNode* node = linearSearchLinkedList(head, target); ListNode* node = linearSearchLinkedList(head, target);
cout << "目标结点值 3 的对应结点对象为 " << node << endl; cout << "目标节点值 3 的对应节点对象为 " << node << endl;
return 0; return 0;
} }

View File

@ -7,18 +7,18 @@
#include "../include/include.hpp" #include "../include/include.hpp"
/* 双向链表点 */ /* 双向链表点 */
struct DoublyListNode { struct DoublyListNode {
int val; // 点值 int val; // 点值
DoublyListNode *next; // 后继点指针 DoublyListNode *next; // 后继点指针
DoublyListNode *prev; // 前驱点指针 DoublyListNode *prev; // 前驱点指针
DoublyListNode(int val) : val(val), prev(nullptr), next(nullptr) {} DoublyListNode(int val) : val(val), prev(nullptr), next(nullptr) {}
}; };
/* 基于双向链表实现的双向队列 */ /* 基于双向链表实现的双向队列 */
class LinkedListDeque { class LinkedListDeque {
private: private:
DoublyListNode *front, *rear; // 头结点 front ,尾结点 rear DoublyListNode *front, *rear; // 头节点 front ,尾节点 rear
int queSize = 0; // 双向队列的长度 int queSize = 0; // 双向队列的长度
public: public:
@ -27,7 +27,7 @@ public:
/* 析构方法 */ /* 析构方法 */
~LinkedListDeque() { ~LinkedListDeque() {
// 遍历链表删除点,释放内存 // 遍历链表删除点,释放内存
DoublyListNode *pre, *cur = front; DoublyListNode *pre, *cur = front;
while (cur != nullptr) { while (cur != nullptr) {
pre = cur; pre = cur;
@ -57,13 +57,13 @@ public:
// 将 node 添加至链表头部 // 将 node 添加至链表头部
front->prev = node; front->prev = node;
node->next = front; node->next = front;
front = node; // 更新头 front = node; // 更新头
// 队尾入队操作 // 队尾入队操作
} else { } else {
// 将 node 添加至链表尾部 // 将 node 添加至链表尾部
rear->next = node; rear->next = node;
node->prev = rear; node->prev = rear;
rear = node; // 更新尾 rear = node; // 更新尾
} }
queSize++; // 更新队列长度 queSize++; // 更新队列长度
} }
@ -86,26 +86,26 @@ public:
int val; int val;
// 队首出队操作 // 队首出队操作
if (isFront) { if (isFront) {
val = front->val; // 暂存头点值 val = front->val; // 暂存头点值
// 删除头 // 删除头
DoublyListNode *fNext = front->next; DoublyListNode *fNext = front->next;
if (fNext != nullptr) { if (fNext != nullptr) {
fNext->prev = nullptr; fNext->prev = nullptr;
front->next = nullptr; front->next = nullptr;
delete front; delete front;
} }
front = fNext; // 更新头 front = fNext; // 更新头
// 队尾出队操作 // 队尾出队操作
} else { } else {
val = rear->val; // 暂存尾点值 val = rear->val; // 暂存尾点值
// 删除尾 // 删除尾
DoublyListNode *rPrev = rear->prev; DoublyListNode *rPrev = rear->prev;
if (rPrev != nullptr) { if (rPrev != nullptr) {
rPrev->next = nullptr; rPrev->next = nullptr;
rear->prev = nullptr; rear->prev = nullptr;
delete rear; delete rear;
} }
rear = rPrev; // 更新尾 rear = rPrev; // 更新尾
} }
queSize--; // 更新队列长度 queSize--; // 更新队列长度
return val; return val;

View File

@ -9,7 +9,7 @@
/* 基于链表实现的队列 */ /* 基于链表实现的队列 */
class LinkedListQueue { class LinkedListQueue {
private: private:
ListNode *front, *rear; // 头结点 front ,尾结点 rear ListNode *front, *rear; // 头节点 front ,尾节点 rear
int queSize; int queSize;
public: public:
@ -20,7 +20,7 @@ public:
} }
~LinkedListQueue() { ~LinkedListQueue() {
// 遍历链表删除点,释放内存 // 遍历链表删除点,释放内存
freeMemoryLinkedList(front); freeMemoryLinkedList(front);
} }
@ -36,14 +36,14 @@ public:
/* 入队 */ /* 入队 */
void push(int num) { void push(int num) {
// 尾点后添加 num // 尾点后添加 num
ListNode* node = new ListNode(num); ListNode* node = new ListNode(num);
// 如果队列为空,则令头、尾结点都指向该结 // 如果队列为空,则令头、尾节点都指向该节
if (front == nullptr) { if (front == nullptr) {
front = node; front = node;
rear = node; rear = node;
} }
// 如果队列不为空,则将该结点添加到尾结点后 // 如果队列不为空,则将该节点添加到尾节点后
else { else {
rear->next = node; rear->next = node;
rear = node; rear = node;
@ -54,7 +54,7 @@ public:
/* 出队 */ /* 出队 */
void pop() { void pop() {
int num = peek(); int num = peek();
// 删除头 // 删除头
ListNode *tmp = front; ListNode *tmp = front;
front = front->next; front = front->next;
// 释放内存 // 释放内存

View File

@ -9,7 +9,7 @@
/* 基于链表实现的栈 */ /* 基于链表实现的栈 */
class LinkedListStack { class LinkedListStack {
private: private:
ListNode* stackTop; // 将头点作为栈顶 ListNode* stackTop; // 将头点作为栈顶
int stkSize; // 栈的长度 int stkSize; // 栈的长度
public: public:
@ -19,7 +19,7 @@ public:
} }
~LinkedListStack() { ~LinkedListStack() {
// 遍历链表删除点,释放内存 // 遍历链表删除点,释放内存
freeMemoryLinkedList(stackTop); freeMemoryLinkedList(stackTop);
} }

View File

@ -9,11 +9,11 @@
/* AVL 树 */ /* AVL 树 */
class AVLTree { class AVLTree {
public: public:
TreeNode* root; // 根 TreeNode* root; // 根
private: private:
/* 更新点高度 */ /* 更新点高度 */
void updateHeight(TreeNode* node) { void updateHeight(TreeNode* node) {
// 点高度等于最高子树高度 + 1 // 点高度等于最高子树高度 + 1
node->height = max(height(node->left), height(node->right)) + 1; node->height = max(height(node->left), height(node->right)) + 1;
} }
@ -24,10 +24,10 @@ private:
// 以 child 为原点,将 node 向右旋转 // 以 child 为原点,将 node 向右旋转
child->right = node; child->right = node;
node->left = grandChild; node->left = grandChild;
// 更新点高度 // 更新点高度
updateHeight(node); updateHeight(node);
updateHeight(child); updateHeight(child);
// 返回旋转后子树的根 // 返回旋转后子树的根
return child; return child;
} }
@ -38,16 +38,16 @@ private:
// 以 child 为原点,将 node 向左旋转 // 以 child 为原点,将 node 向左旋转
child->left = node; child->left = node;
node->right = grandChild; node->right = grandChild;
// 更新点高度 // 更新点高度
updateHeight(node); updateHeight(node);
updateHeight(child); updateHeight(child);
// 返回旋转后子树的根 // 返回旋转后子树的根
return child; return child;
} }
/* 执行旋转操作,使该子树重新恢复平衡 */ /* 执行旋转操作,使该子树重新恢复平衡 */
TreeNode* rotate(TreeNode* node) { TreeNode* rotate(TreeNode* node) {
// 获取点 node 的平衡因子 // 获取点 node 的平衡因子
int _balanceFactor = balanceFactor(node); int _balanceFactor = balanceFactor(node);
// 左偏树 // 左偏树
if (_balanceFactor > 1) { if (_balanceFactor > 1) {
@ -75,40 +75,40 @@ private:
return node; return node;
} }
/* 递归插入点(辅助方法) */ /* 递归插入点(辅助方法) */
TreeNode* insertHelper(TreeNode* node, int val) { TreeNode* insertHelper(TreeNode* node, int val) {
if (node == nullptr) if (node == nullptr)
return new TreeNode(val); return new TreeNode(val);
/* 1. 查找插入位置,并插入点 */ /* 1. 查找插入位置,并插入点 */
if (val < node->val) if (val < node->val)
node->left = insertHelper(node->left, val); node->left = insertHelper(node->left, val);
else if (val > node->val) else if (val > node->val)
node->right = insertHelper(node->right, val); node->right = insertHelper(node->right, val);
else else
return node; // 重复点不插入,直接返回 return node; // 重复点不插入,直接返回
updateHeight(node); // 更新点高度 updateHeight(node); // 更新点高度
/* 2. 执行旋转操作,使该子树重新恢复平衡 */ /* 2. 执行旋转操作,使该子树重新恢复平衡 */
node = rotate(node); node = rotate(node);
// 返回子树的根 // 返回子树的根
return node; return node;
} }
/* 获取中序遍历中的下一个结点(仅适用于 root 有左子结点的情况) */ /* 获取中序遍历中的下一个节点(仅适用于 root 有左子节点的情况) */
TreeNode* getInOrderNext(TreeNode* node) { TreeNode* getInOrderNext(TreeNode* node) {
if (node == nullptr) if (node == nullptr)
return node; return node;
// 循环访问左子结点,直到叶结点时为最小结点,跳出 // 循环访问左子节点,直到叶节点时为最小节点,跳出
while (node->left != nullptr) { while (node->left != nullptr) {
node = node->left; node = node->left;
} }
return node; return node;
} }
/* 递归删除点(辅助方法) */ /* 递归删除点(辅助方法) */
TreeNode* removeHelper(TreeNode* node, int val) { TreeNode* removeHelper(TreeNode* node, int val) {
if (node == nullptr) if (node == nullptr)
return nullptr; return nullptr;
/* 1. 查找点,并删除之 */ /* 1. 查找点,并删除之 */
if (val < node->val) if (val < node->val)
node->left = removeHelper(node->left, val); node->left = removeHelper(node->left, val);
else if (val > node->val) else if (val > node->val)
@ -116,74 +116,74 @@ private:
else { else {
if (node->left == nullptr || node->right == nullptr) { if (node->left == nullptr || node->right == nullptr) {
TreeNode* child = node->left != nullptr ? node->left : node->right; TreeNode* child = node->left != nullptr ? node->left : node->right;
// 子点数量 = 0 ,直接删除 node 并返回 // 子点数量 = 0 ,直接删除 node 并返回
if (child == nullptr) { if (child == nullptr) {
delete node; delete node;
return nullptr; return nullptr;
} }
// 子点数量 = 1 ,直接删除 node // 子点数量 = 1 ,直接删除 node
else { else {
delete node; delete node;
node = child; node = child;
} }
} else { } else {
// 子结点数量 = 2 ,则将中序遍历的下个结点删除,并用该结点替换当前结 // 子节点数量 = 2 ,则将中序遍历的下个节点删除,并用该节点替换当前节
TreeNode* temp = getInOrderNext(node->right); TreeNode* temp = getInOrderNext(node->right);
int tempVal = temp->val; int tempVal = temp->val;
node->right = removeHelper(node->right, temp->val); node->right = removeHelper(node->right, temp->val);
node->val = tempVal; node->val = tempVal;
} }
} }
updateHeight(node); // 更新点高度 updateHeight(node); // 更新点高度
/* 2. 执行旋转操作,使该子树重新恢复平衡 */ /* 2. 执行旋转操作,使该子树重新恢复平衡 */
node = rotate(node); node = rotate(node);
// 返回子树的根 // 返回子树的根
return node; return node;
} }
public: public:
/* 获取点高度 */ /* 获取点高度 */
int height(TreeNode* node) { int height(TreeNode* node) {
// 空结点高度为 -1 ,叶结点高度为 0 // 空节点高度为 -1 ,叶节点高度为 0
return node == nullptr ? -1 : node->height; return node == nullptr ? -1 : node->height;
} }
/* 获取平衡因子 */ /* 获取平衡因子 */
int balanceFactor(TreeNode* node) { int balanceFactor(TreeNode* node) {
// 空点平衡因子为 0 // 空点平衡因子为 0
if (node == nullptr) return 0; if (node == nullptr) return 0;
// 点平衡因子 = 左子树高度 - 右子树高度 // 点平衡因子 = 左子树高度 - 右子树高度
return height(node->left) - height(node->right); return height(node->left) - height(node->right);
} }
/* 插入点 */ /* 插入点 */
TreeNode* insert(int val) { TreeNode* insert(int val) {
root = insertHelper(root, val); root = insertHelper(root, val);
return root; return root;
} }
/* 删除点 */ /* 删除点 */
TreeNode* remove(int val) { TreeNode* remove(int val) {
root = removeHelper(root, val); root = removeHelper(root, val);
return root; return root;
} }
/* 查找点 */ /* 查找点 */
TreeNode* search(int val) { TreeNode* search(int val) {
TreeNode* cur = root; TreeNode* cur = root;
// 循环查找,越过叶点后跳出 // 循环查找,越过叶点后跳出
while (cur != nullptr) { while (cur != nullptr) {
// 目标点在 cur 的右子树中 // 目标点在 cur 的右子树中
if (cur->val < val) if (cur->val < val)
cur = cur->right; cur = cur->right;
// 目标点在 cur 的左子树中 // 目标点在 cur 的左子树中
else if (cur->val > val) else if (cur->val > val)
cur = cur->left; cur = cur->left;
// 找到目标点,跳出循环 // 找到目标点,跳出循环
else else
break; break;
} }
// 返回目标 // 返回目标
return cur; return cur;
} }
@ -198,21 +198,21 @@ public:
void testInsert(AVLTree& tree, int val) { void testInsert(AVLTree& tree, int val) {
tree.insert(val); tree.insert(val);
cout << "\n插入" << val << "AVL 树为" << endl; cout << "\n插入" << val << "AVL 树为" << endl;
PrintUtil::printTree(tree.root); PrintUtil::printTree(tree.root);
} }
void testRemove(AVLTree& tree, int val) { void testRemove(AVLTree& tree, int val) {
tree.remove(val); tree.remove(val);
cout << "\n删除" << val << "AVL 树为" << endl; cout << "\n删除" << val << "AVL 树为" << endl;
PrintUtil::printTree(tree.root); PrintUtil::printTree(tree.root);
} }
int main() { int main() {
/* 初始化空 AVL 树 */ /* 初始化空 AVL 树 */
AVLTree avlTree; AVLTree avlTree;
/* 插入点 */ /* 插入点 */
// 请关注插入点后AVL 树是如何保持平衡的 // 请关注插入点后AVL 树是如何保持平衡的
testInsert(avlTree, 1); testInsert(avlTree, 1);
testInsert(avlTree, 2); testInsert(avlTree, 2);
testInsert(avlTree, 3); testInsert(avlTree, 3);
@ -224,16 +224,16 @@ int main() {
testInsert(avlTree, 10); testInsert(avlTree, 10);
testInsert(avlTree, 6); testInsert(avlTree, 6);
/* 插入重复点 */ /* 插入重复点 */
testInsert(avlTree, 7); testInsert(avlTree, 7);
/* 删除点 */ /* 删除点 */
// 请关注删除点后AVL 树是如何保持平衡的 // 请关注删除点后AVL 树是如何保持平衡的
testRemove(avlTree, 8); // 删除度为 0 的 testRemove(avlTree, 8); // 删除度为 0 的
testRemove(avlTree, 5); // 删除度为 1 的 testRemove(avlTree, 5); // 删除度为 1 的
testRemove(avlTree, 4); // 删除度为 2 的 testRemove(avlTree, 4); // 删除度为 2 的
/* 查询点 */ /* 查询点 */
TreeNode* node = avlTree.search(7); TreeNode* node = avlTree.search(7);
cout << "\n查找到的点对象为 " << node << "点值 = " << node->val << endl; cout << "\n查找到的点对象为 " << node << "点值 = " << node->val << endl;
} }

View File

@ -21,7 +21,7 @@ public:
freeMemoryTree(root); freeMemoryTree(root);
} }
/* 获取二叉树根点 */ /* 获取二叉树根点 */
TreeNode* getRoot() { TreeNode* getRoot() {
return root; return root;
} }
@ -29,7 +29,7 @@ public:
/* 构建二叉搜索树 */ /* 构建二叉搜索树 */
TreeNode* buildTree(vector<int> nums, int i, int j) { TreeNode* buildTree(vector<int> nums, int i, int j) {
if (i > j) return nullptr; if (i > j) return nullptr;
// 将数组中间结点作为根结 // 将数组中间节点作为根节
int mid = (i + j) / 2; int mid = (i + j) / 2;
TreeNode* root = new TreeNode(nums[mid]); TreeNode* root = new TreeNode(nums[mid]);
// 递归建立左子树和右子树 // 递归建立左子树和右子树
@ -38,30 +38,30 @@ public:
return root; return root;
} }
/* 查找点 */ /* 查找点 */
TreeNode* search(int num) { TreeNode* search(int num) {
TreeNode* cur = root; TreeNode* cur = root;
// 循环查找,越过叶点后跳出 // 循环查找,越过叶点后跳出
while (cur != nullptr) { while (cur != nullptr) {
// 目标点在 cur 的右子树中 // 目标点在 cur 的右子树中
if (cur->val < num) cur = cur->right; if (cur->val < num) cur = cur->right;
// 目标点在 cur 的左子树中 // 目标点在 cur 的左子树中
else if (cur->val > num) cur = cur->left; else if (cur->val > num) cur = cur->left;
// 找到目标点,跳出循环 // 找到目标点,跳出循环
else break; else break;
} }
// 返回目标 // 返回目标
return cur; return cur;
} }
/* 插入点 */ /* 插入点 */
TreeNode* insert(int num) { TreeNode* insert(int num) {
// 若树为空,直接提前返回 // 若树为空,直接提前返回
if (root == nullptr) return nullptr; if (root == nullptr) return nullptr;
TreeNode *cur = root, *pre = nullptr; TreeNode *cur = root, *pre = nullptr;
// 循环查找,越过叶点后跳出 // 循环查找,越过叶点后跳出
while (cur != nullptr) { while (cur != nullptr) {
// 找到重复点,直接返回 // 找到重复点,直接返回
if (cur->val == num) return nullptr; if (cur->val == num) return nullptr;
pre = cur; pre = cur;
// 插入位置在 cur 的右子树中 // 插入位置在 cur 的右子树中
@ -69,46 +69,46 @@ public:
// 插入位置在 cur 的左子树中 // 插入位置在 cur 的左子树中
else cur = cur->left; else cur = cur->left;
} }
// 插入点 val // 插入点 val
TreeNode* node = new TreeNode(num); TreeNode* node = new TreeNode(num);
if (pre->val < num) pre->right = node; if (pre->val < num) pre->right = node;
else pre->left = node; else pre->left = node;
return node; return node;
} }
/* 删除点 */ /* 删除点 */
TreeNode* remove(int num) { TreeNode* remove(int num) {
// 若树为空,直接提前返回 // 若树为空,直接提前返回
if (root == nullptr) return nullptr; if (root == nullptr) return nullptr;
TreeNode *cur = root, *pre = nullptr; TreeNode *cur = root, *pre = nullptr;
// 循环查找,越过叶点后跳出 // 循环查找,越过叶点后跳出
while (cur != nullptr) { while (cur != nullptr) {
// 找到待删除点,跳出循环 // 找到待删除点,跳出循环
if (cur->val == num) break; if (cur->val == num) break;
pre = cur; pre = cur;
// 待删除点在 cur 的右子树中 // 待删除点在 cur 的右子树中
if (cur->val < num) cur = cur->right; if (cur->val < num) cur = cur->right;
// 待删除点在 cur 的左子树中 // 待删除点在 cur 的左子树中
else cur = cur->left; else cur = cur->left;
} }
// 若无待删除点,则直接返回 // 若无待删除点,则直接返回
if (cur == nullptr) return nullptr; if (cur == nullptr) return nullptr;
// 子点数量 = 0 or 1 // 子点数量 = 0 or 1
if (cur->left == nullptr || cur->right == nullptr) { if (cur->left == nullptr || cur->right == nullptr) {
// 当子结点数量 = 0 / 1 时, child = nullptr / 该子结 // 当子节点数量 = 0 / 1 时, child = nullptr / 该子节
TreeNode* child = cur->left != nullptr ? cur->left : cur->right; TreeNode* child = cur->left != nullptr ? cur->left : cur->right;
// 删除点 cur // 删除点 cur
if (pre->left == cur) pre->left = child; if (pre->left == cur) pre->left = child;
else pre->right = child; else pre->right = child;
// 释放内存 // 释放内存
delete cur; delete cur;
} }
// 子点数量 = 2 // 子点数量 = 2
else { else {
// 获取中序遍历中 cur 的下一个 // 获取中序遍历中 cur 的下一个
TreeNode* nex = getInOrderNext(cur->right); TreeNode* nex = getInOrderNext(cur->right);
int tmp = nex->val; int tmp = nex->val;
// 递归删除点 nex // 递归删除点 nex
remove(nex->val); remove(nex->val);
// 将 nex 的值复制给 cur // 将 nex 的值复制给 cur
cur->val = tmp; cur->val = tmp;
@ -116,10 +116,10 @@ public:
return cur; return cur;
} }
/* 获取中序遍历中的下一个结点(仅适用于 root 有左子结点的情况) */ /* 获取中序遍历中的下一个节点(仅适用于 root 有左子节点的情况) */
TreeNode* getInOrderNext(TreeNode* root) { TreeNode* getInOrderNext(TreeNode* root) {
if (root == nullptr) return root; if (root == nullptr) return root;
// 循环访问左子结点,直到叶结点时为最小结点,跳出 // 循环访问左子节点,直到叶节点时为最小节点,跳出
while (root->left != nullptr) { while (root->left != nullptr) {
root = root->left; root = root->left;
} }
@ -136,24 +136,24 @@ int main() {
cout << endl << "初始化的二叉树为\n" << endl; cout << endl << "初始化的二叉树为\n" << endl;
PrintUtil::printTree(bst->getRoot()); PrintUtil::printTree(bst->getRoot());
/* 查找点 */ /* 查找点 */
TreeNode* node = bst->search(7); TreeNode* node = bst->search(7);
cout << endl << "查找到的点对象为 " << node << "点值 = " << node->val << endl; cout << endl << "查找到的点对象为 " << node << "点值 = " << node->val << endl;
/* 插入点 */ /* 插入点 */
node = bst->insert(16); node = bst->insert(16);
cout << endl << "插入点 16 后,二叉树为\n" << endl; cout << endl << "插入点 16 后,二叉树为\n" << endl;
PrintUtil::printTree(bst->getRoot()); PrintUtil::printTree(bst->getRoot());
/* 删除点 */ /* 删除点 */
bst->remove(1); bst->remove(1);
cout << endl << "删除点 1 后,二叉树为\n" << endl; cout << endl << "删除点 1 后,二叉树为\n" << endl;
PrintUtil::printTree(bst->getRoot()); PrintUtil::printTree(bst->getRoot());
bst->remove(2); bst->remove(2);
cout << endl << "删除点 2 后,二叉树为\n" << endl; cout << endl << "删除点 2 后,二叉树为\n" << endl;
PrintUtil::printTree(bst->getRoot()); PrintUtil::printTree(bst->getRoot());
bst->remove(4); bst->remove(4);
cout << endl << "删除点 4 后,二叉树为\n" << endl; cout << endl << "删除点 4 后,二叉树为\n" << endl;
PrintUtil::printTree(bst->getRoot()); PrintUtil::printTree(bst->getRoot());
// 释放内存 // 释放内存

View File

@ -10,7 +10,7 @@
/* Driver Code */ /* Driver Code */
int main() { int main() {
/* 初始化二叉树 */ /* 初始化二叉树 */
// 初始化 // 初始化
TreeNode* n1 = new TreeNode(1); TreeNode* n1 = new TreeNode(1);
TreeNode* n2 = new TreeNode(2); TreeNode* n2 = new TreeNode(2);
TreeNode* n3 = new TreeNode(3); TreeNode* n3 = new TreeNode(3);
@ -24,17 +24,17 @@ int main() {
cout << endl << "初始化二叉树\n" << endl; cout << endl << "初始化二叉树\n" << endl;
PrintUtil::printTree(n1); PrintUtil::printTree(n1);
/* 插入与删除点 */ /* 插入与删除点 */
TreeNode* P = new TreeNode(0); TreeNode* P = new TreeNode(0);
// 在 n1 -> n2 中间插入点 P // 在 n1 -> n2 中间插入点 P
n1->left = P; n1->left = P;
P->left = n2; P->left = n2;
cout << endl << "插入点 P 后\n" << endl; cout << endl << "插入点 P 后\n" << endl;
PrintUtil::printTree(n1); PrintUtil::printTree(n1);
// 删除点 P // 删除点 P
n1->left = n2; n1->left = n2;
delete P; // 释放内存 delete P; // 释放内存
cout << endl << "删除点 P 后\n" << endl; cout << endl << "删除点 P 后\n" << endl;
PrintUtil::printTree(n1); PrintUtil::printTree(n1);
// 释放内存 // 释放内存

View File

@ -8,7 +8,7 @@
/* 层序遍历 */ /* 层序遍历 */
vector<int> levelOrder(TreeNode* root) { vector<int> levelOrder(TreeNode* root) {
// 初始化队列,加入根 // 初始化队列,加入根
queue<TreeNode*> queue; queue<TreeNode*> queue;
queue.push(root); queue.push(root);
// 初始化一个列表,用于保存遍历序列 // 初始化一个列表,用于保存遍历序列
@ -16,11 +16,11 @@ vector<int> levelOrder(TreeNode* root) {
while (!queue.empty()) { while (!queue.empty()) {
TreeNode* node = queue.front(); TreeNode* node = queue.front();
queue.pop(); // 队列出队 queue.pop(); // 队列出队
vec.push_back(node->val); // 保存点值 vec.push_back(node->val); // 保存点值
if (node->left != nullptr) if (node->left != nullptr)
queue.push(node->left); // 左子点入队 queue.push(node->left); // 左子点入队
if (node->right != nullptr) if (node->right != nullptr)
queue.push(node->right); // 右子点入队 queue.push(node->right); // 右子点入队
} }
return vec; return vec;
} }
@ -36,7 +36,7 @@ int main() {
/* 层序遍历 */ /* 层序遍历 */
vector<int> vec = levelOrder(root); vector<int> vec = levelOrder(root);
cout << endl << "层序遍历的点打印序列 = "; cout << endl << "层序遍历的点打印序列 = ";
PrintUtil::printVector(vec); PrintUtil::printVector(vec);
return 0; return 0;

View File

@ -12,7 +12,7 @@ vector<int> vec;
/* 前序遍历 */ /* 前序遍历 */
void preOrder(TreeNode* root) { void preOrder(TreeNode* root) {
if (root == nullptr) return; if (root == nullptr) return;
// 访问优先级:根点 -> 左子树 -> 右子树 // 访问优先级:根点 -> 左子树 -> 右子树
vec.push_back(root->val); vec.push_back(root->val);
preOrder(root->left); preOrder(root->left);
preOrder(root->right); preOrder(root->right);
@ -21,7 +21,7 @@ void preOrder(TreeNode* root) {
/* 中序遍历 */ /* 中序遍历 */
void inOrder(TreeNode* root) { void inOrder(TreeNode* root) {
if (root == nullptr) return; if (root == nullptr) return;
// 访问优先级:左子树 -> 根点 -> 右子树 // 访问优先级:左子树 -> 根点 -> 右子树
inOrder(root->left); inOrder(root->left);
vec.push_back(root->val); vec.push_back(root->val);
inOrder(root->right); inOrder(root->right);
@ -30,7 +30,7 @@ void inOrder(TreeNode* root) {
/* 后序遍历 */ /* 后序遍历 */
void postOrder(TreeNode* root) { void postOrder(TreeNode* root) {
if (root == nullptr) return; if (root == nullptr) return;
// 访问优先级:左子树 -> 右子树 -> 根 // 访问优先级:左子树 -> 右子树 -> 根
postOrder(root->left); postOrder(root->left);
postOrder(root->right); postOrder(root->right);
vec.push_back(root->val); vec.push_back(root->val);
@ -48,19 +48,19 @@ int main() {
/* 前序遍历 */ /* 前序遍历 */
vec.clear(); vec.clear();
preOrder(root); preOrder(root);
cout << endl << "前序遍历的点打印序列 = "; cout << endl << "前序遍历的点打印序列 = ";
PrintUtil::printVector(vec); PrintUtil::printVector(vec);
/* 中序遍历 */ /* 中序遍历 */
vec.clear(); vec.clear();
inOrder(root); inOrder(root);
cout << endl << "中序遍历的点打印序列 = "; cout << endl << "中序遍历的点打印序列 = ";
PrintUtil::printVector(vec); PrintUtil::printVector(vec);
/* 后序遍历 */ /* 后序遍历 */
vec.clear(); vec.clear();
postOrder(root); postOrder(root);
cout << endl << "后序遍历的点打印序列 = "; cout << endl << "后序遍历的点打印序列 = ";
PrintUtil::printVector(vec); PrintUtil::printVector(vec);
return 0; return 0;

View File

@ -9,7 +9,7 @@ namespace hello_algo.chapter_array_and_linkedlist;
public class linked_list public class linked_list
{ {
/* 在链表的结点 n0 之后插入结点 P */ /* 在链表的节点 n0 之后插入节点 P */
public static void insert(ListNode n0, ListNode P) public static void insert(ListNode n0, ListNode P)
{ {
ListNode? n1 = n0.next; ListNode? n1 = n0.next;
@ -17,7 +17,7 @@ public class linked_list
n0.next = P; n0.next = P;
} }
/* 删除链表的结点 n0 之后的首个结点 */ /* 删除链表的节点 n0 之后的首个节点 */
public static void remove(ListNode n0) public static void remove(ListNode n0)
{ {
if (n0.next == null) if (n0.next == null)
@ -28,7 +28,7 @@ public class linked_list
n0.next = n1; n0.next = n1;
} }
/* 访问链表中索引为 index 的点 */ /* 访问链表中索引为 index 的点 */
public static ListNode? access(ListNode head, int index) public static ListNode? access(ListNode head, int index)
{ {
for (int i = 0; i < index; i++) for (int i = 0; i < index; i++)
@ -40,7 +40,7 @@ public class linked_list
return head; return head;
} }
/* 在链表中查找值为 target 的首个点 */ /* 在链表中查找值为 target 的首个点 */
public static int find(ListNode head, int target) public static int find(ListNode head, int target)
{ {
int index = 0; int index = 0;
@ -59,7 +59,7 @@ public class linked_list
public void Test() public void Test()
{ {
// 初始化链表 // 初始化链表
// 初始化各个 // 初始化各个
ListNode n0 = new ListNode(1); ListNode n0 = new ListNode(1);
ListNode n1 = new ListNode(3); ListNode n1 = new ListNode(3);
ListNode n2 = new ListNode(2); ListNode n2 = new ListNode(2);
@ -72,20 +72,20 @@ public class linked_list
n3.next = n4; n3.next = n4;
Console.WriteLine($"初始化的链表为{n0}"); Console.WriteLine($"初始化的链表为{n0}");
// 插入 // 插入
insert(n0, new ListNode(0)); insert(n0, new ListNode(0));
Console.WriteLine($"插入点后的链表为{n0}"); Console.WriteLine($"插入点后的链表为{n0}");
// 删除 // 删除
remove(n0); remove(n0);
Console.WriteLine($"删除点后的链表为{n0}"); Console.WriteLine($"删除点后的链表为{n0}");
// 访问 // 访问
ListNode? node = access(n0, 3); ListNode? node = access(n0, 3);
Console.WriteLine($"链表中索引 3 处的点的值 = {node?.val}"); Console.WriteLine($"链表中索引 3 处的点的值 = {node?.val}");
// 查找 // 查找
int index = find(n0, 2); int index = find(n0, 2);
Console.WriteLine($"链表中值为 2 的点的索引 = {index}"); Console.WriteLine($"链表中值为 2 的点的索引 = {index}");
} }
} }

View File

@ -26,7 +26,7 @@ class MaxHeap
{ {
// 将列表元素原封不动添加进堆 // 将列表元素原封不动添加进堆
maxHeap = new List<int>(nums); maxHeap = new List<int>(nums);
// 堆化除叶结点以外的其他所有结 // 堆化除叶节点以外的其他所有节
var size = parent(this.size() - 1); var size = parent(this.size() - 1);
for (int i = size; i >= 0; i--) for (int i = size; i >= 0; i--)
{ {
@ -34,19 +34,19 @@ class MaxHeap
} }
} }
/* 获取左子点索引 */ /* 获取左子点索引 */
int left(int i) int left(int i)
{ {
return 2 * i + 1; return 2 * i + 1;
} }
/* 获取右子点索引 */ /* 获取右子点索引 */
int right(int i) int right(int i)
{ {
return 2 * i + 2; return 2 * i + 2;
} }
/* 获取父点索引 */ /* 获取父点索引 */
int parent(int i) int parent(int i)
{ {
return (i - 1) / 2; // 向下整除 return (i - 1) / 2; // 向下整除
@ -61,7 +61,7 @@ class MaxHeap
/* 元素入堆 */ /* 元素入堆 */
public void push(int val) public void push(int val)
{ {
// 添加 // 添加
maxHeap.Add(val); maxHeap.Add(val);
// 从底至顶堆化 // 从底至顶堆化
siftUp(size() - 1); siftUp(size() - 1);
@ -79,17 +79,17 @@ class MaxHeap
return size() == 0; return size() == 0;
} }
/* 从点 i 开始,从底至顶堆化 */ /* 从点 i 开始,从底至顶堆化 */
void siftUp(int i) void siftUp(int i)
{ {
while (true) while (true)
{ {
// 获取结点 i 的父结 // 获取节点 i 的父节
int p = parent(i); int p = parent(i);
// 越过根结点点无需修复则结束堆化 // 越过根节点点无需修复则结束堆化
if (p < 0 || maxHeap[i] <= maxHeap[p]) if (p < 0 || maxHeap[i] <= maxHeap[p])
break; break;
// 交换两 // 交换两
swap(i, p); swap(i, p);
// 循环向上堆化 // 循环向上堆化
i = p; i = p;
@ -102,9 +102,9 @@ class MaxHeap
// 判空处理 // 判空处理
if (isEmpty()) if (isEmpty())
throw new IndexOutOfRangeException(); throw new IndexOutOfRangeException();
// 交换根结点与最右叶结即交换首元素与尾元素 // 交换根节点与最右叶节即交换首元素与尾元素
swap(0, size() - 1); swap(0, size() - 1);
// 删除 // 删除
int val = maxHeap.Last(); int val = maxHeap.Last();
maxHeap.RemoveAt(size() - 1); maxHeap.RemoveAt(size() - 1);
// 从顶至底堆化 // 从顶至底堆化
@ -113,20 +113,20 @@ class MaxHeap
return val; return val;
} }
/* 从点 i 开始,从顶至底堆化 */ /* 从点 i 开始,从顶至底堆化 */
void siftDown(int i) void siftDown(int i)
{ {
while (true) while (true)
{ {
// 判断 i, l, r 中值最大的记为 ma // 判断 i, l, r 中值最大的记为 ma
int l = left(i), r = right(i), ma = i; int l = left(i), r = right(i), ma = i;
if (l < size() && maxHeap[l] > maxHeap[ma]) if (l < size() && maxHeap[l] > maxHeap[ma])
ma = l; ma = l;
if (r < size() && maxHeap[r] > maxHeap[ma]) if (r < size() && maxHeap[r] > maxHeap[ma])
ma = r; ma = r;
// 结点 i 最大越过叶结则结束堆化 // 节点 i 最大越过叶节则结束堆化
if (ma == i) break; if (ma == i) break;
// 交换两 // 交换两
swap(i, ma); swap(i, ma);
// 循环向下堆化 // 循环向下堆化
i = ma; i = ma;

View File

@ -23,7 +23,7 @@ public class hashing_search
static ListNode? hashingSearchLinkedList(Dictionary<int, ListNode> map, int target) static ListNode? hashingSearchLinkedList(Dictionary<int, ListNode> map, int target)
{ {
// 哈希表的 key: 目标结点值value: 点对象 // 哈希表的 key: 目标节点值value: 点对象
// 若哈希表中无此 key 返回 null // 若哈希表中无此 key 返回 null
return map.GetValueOrDefault(target); return map.GetValueOrDefault(target);
} }
@ -50,10 +50,10 @@ public class hashing_search
Dictionary<int, ListNode> map1 = new(); Dictionary<int, ListNode> map1 = new();
while (head != null) while (head != null)
{ {
map1[head.val] = head; // key: 结点值value: map1[head.val] = head; // key: 节点值value:
head = head.next; head = head.next;
} }
ListNode? node = hashingSearchLinkedList(map1, target); ListNode? node = hashingSearchLinkedList(map1, target);
Console.WriteLine("目标结点值 3 的对应结点对象为 " + node); Console.WriteLine("目标节点值 3 的对应节点对象为 " + node);
} }
} }

View File

@ -31,12 +31,12 @@ public class linear_search
// 遍历链表 // 遍历链表
while (head != null) while (head != null)
{ {
// 找到目标返回之 // 找到目标返回之
if (head.val == target) if (head.val == target)
return head; return head;
head = head.next; head = head.next;
} }
// 未找到目标返回 null // 未找到目标返回 null
return null; return null;
} }
@ -53,6 +53,6 @@ public class linear_search
/* 在链表中执行线性查找 */ /* 在链表中执行线性查找 */
ListNode head = ListNode.ArrToLinkedList(nums); ListNode head = ListNode.ArrToLinkedList(nums);
ListNode? node = linearSearchLinkedList(head, target); ListNode? node = linearSearchLinkedList(head, target);
Console.WriteLine("目标结点值 3 的对应结点对象为 " + node); Console.WriteLine("目标节点值 3 的对应节点对象为 " + node);
} }
} }

View File

@ -8,12 +8,12 @@ using NUnit.Framework;
namespace hello_algo.chapter_stack_and_queue namespace hello_algo.chapter_stack_and_queue
{ {
/* 双向链表点 */ /* 双向链表点 */
public class ListNode public class ListNode
{ {
public int val; // 点值 public int val; // 点值
public ListNode? next; // 后继点引用指针 public ListNode? next; // 后继点引用指针
public ListNode? prev; // 前驱点引用指针 public ListNode? prev; // 前驱点引用指针
public ListNode(int val) public ListNode(int val)
{ {
@ -26,7 +26,7 @@ namespace hello_algo.chapter_stack_and_queue
/* 基于双向链表实现的双向队列 */ /* 基于双向链表实现的双向队列 */
public class LinkedListDeque public class LinkedListDeque
{ {
private ListNode? front, rear; // 结点 front, 尾结 rear private ListNode? front, rear; // 节点 front, 尾节 rear
private int queSize = 0; // 双向队列的长度 private int queSize = 0; // 双向队列的长度
public LinkedListDeque() public LinkedListDeque()
@ -63,7 +63,7 @@ namespace hello_algo.chapter_stack_and_queue
// node 添加至链表头部 // node 添加至链表头部
front.prev = node; front.prev = node;
node.next = front; node.next = front;
front = node; // 更新头 front = node; // 更新头
} }
// 队尾入队操作 // 队尾入队操作
else else
@ -71,7 +71,7 @@ namespace hello_algo.chapter_stack_and_queue
// node 添加至链表尾部 // node 添加至链表尾部
rear.next = node; rear.next = node;
node.prev = rear; node.prev = rear;
rear = node; // 更新尾 rear = node; // 更新尾
} }
queSize++; // 更新队列长度 queSize++; // 更新队列长度
@ -102,8 +102,8 @@ namespace hello_algo.chapter_stack_and_queue
// 队首出队操作 // 队首出队操作
if (isFront) if (isFront)
{ {
val = front.val; // 暂存头点值 val = front.val; // 暂存头点值
// 删除头 // 删除头
ListNode fNext = front.next; ListNode fNext = front.next;
if (fNext != null) if (fNext != null)
{ {
@ -111,13 +111,13 @@ namespace hello_algo.chapter_stack_and_queue
front.next = null; front.next = null;
} }
front = fNext; // 更新头 front = fNext; // 更新头
} }
// 队尾出队操作 // 队尾出队操作
else else
{ {
val = rear.val; // 暂存尾点值 val = rear.val; // 暂存尾点值
// 删除尾 // 删除尾
ListNode rPrev = rear.prev; ListNode rPrev = rear.prev;
if (rPrev != null) if (rPrev != null)
{ {
@ -125,7 +125,7 @@ namespace hello_algo.chapter_stack_and_queue
rear.prev = null; rear.prev = null;
} }
rear = rPrev; // 更新尾 rear = rPrev; // 更新尾
} }
queSize--; // 更新队列长度 queSize--; // 更新队列长度

View File

@ -12,7 +12,7 @@ namespace hello_algo.chapter_stack_and_queue;
/* 基于链表实现的队列 */ /* 基于链表实现的队列 */
class LinkedListQueue class LinkedListQueue
{ {
private ListNode? front, rear; // 结点 front 尾结 rear private ListNode? front, rear; // 节点 front 尾节 rear
private int queSize = 0; private int queSize = 0;
public LinkedListQueue() public LinkedListQueue()
@ -36,14 +36,14 @@ class LinkedListQueue
/* 入队 */ /* 入队 */
public void push(int num) public void push(int num)
{ {
// 点后添加 num // 点后添加 num
ListNode node = new ListNode(num); ListNode node = new ListNode(num);
// 如果队列为空则令头结点都指向该结 // 如果队列为空则令头节点都指向该节
if (front == null) if (front == null)
{ {
front = node; front = node;
rear = node; rear = node;
// 如果队列不为空则将该结点添加到尾结点后 // 如果队列不为空则将该节点添加到尾节点后
} }
else if (rear != null) else if (rear != null)
{ {
@ -57,7 +57,7 @@ class LinkedListQueue
public int pop() public int pop()
{ {
int num = peek(); int num = peek();
// 删除头 // 删除头
front = front?.next; front = front?.next;
queSize--; queSize--;
return num; return num;

View File

@ -12,7 +12,7 @@ namespace hello_algo.chapter_stack_and_queue;
/* 基于链表实现的栈 */ /* 基于链表实现的栈 */
class LinkedListStack class LinkedListStack
{ {
private ListNode? stackPeek; // 将头点作为栈顶 private ListNode? stackPeek; // 将头点作为栈顶
private int stkSize = 0; // 栈的长度 private int stkSize = 0; // 栈的长度
public LinkedListStack() public LinkedListStack()

View File

@ -12,28 +12,28 @@ namespace hello_algo.chapter_tree;
/* AVL 树 */ /* AVL 树 */
class AVLTree class AVLTree
{ {
public TreeNode? root; // public TreeNode? root; //
/* 获取点高度 */ /* 获取点高度 */
public int height(TreeNode? node) public int height(TreeNode? node)
{ {
// 结点高度为 -1 叶结点高度为 0 // 节点高度为 -1 叶节点高度为 0
return node == null ? -1 : node.height; return node == null ? -1 : node.height;
} }
/* 更新点高度 */ /* 更新点高度 */
private void updateHeight(TreeNode node) private void updateHeight(TreeNode node)
{ {
// 点高度等于最高子树高度 + 1 // 点高度等于最高子树高度 + 1
node.height = Math.Max(height(node.left), height(node.right)) + 1; node.height = Math.Max(height(node.left), height(node.right)) + 1;
} }
/* 获取平衡因子 */ /* 获取平衡因子 */
public int balanceFactor(TreeNode? node) public int balanceFactor(TreeNode? node)
{ {
// 点平衡因子为 0 // 点平衡因子为 0
if (node == null) return 0; if (node == null) return 0;
// 点平衡因子 = 左子树高度 - 右子树高度 // 点平衡因子 = 左子树高度 - 右子树高度
return height(node.left) - height(node.right); return height(node.left) - height(node.right);
} }
@ -45,10 +45,10 @@ class AVLTree
// child 为原点 node 向右旋转 // child 为原点 node 向右旋转
child.right = node; child.right = node;
node.left = grandChild; node.left = grandChild;
// 更新点高度 // 更新点高度
updateHeight(node); updateHeight(node);
updateHeight(child); updateHeight(child);
// 返回旋转后子树的根 // 返回旋转后子树的根
return child; return child;
} }
@ -60,17 +60,17 @@ class AVLTree
// child 为原点 node 向左旋转 // child 为原点 node 向左旋转
child.left = node; child.left = node;
node.right = grandChild; node.right = grandChild;
// 更新点高度 // 更新点高度
updateHeight(node); updateHeight(node);
updateHeight(child); updateHeight(child);
// 返回旋转后子树的根 // 返回旋转后子树的根
return child; return child;
} }
/* 执行旋转操作,使该子树重新恢复平衡 */ /* 执行旋转操作,使该子树重新恢复平衡 */
TreeNode? rotate(TreeNode? node) TreeNode? rotate(TreeNode? node)
{ {
// 获取 node 的平衡因子 // 获取 node 的平衡因子
int balanceFactorInt = balanceFactor(node); int balanceFactorInt = balanceFactor(node);
// 左偏树 // 左偏树
if (balanceFactorInt > 1) if (balanceFactorInt > 1)
@ -106,43 +106,43 @@ class AVLTree
return node; return node;
} }
/* 插入点 */ /* 插入点 */
public TreeNode? insert(int val) public TreeNode? insert(int val)
{ {
root = insertHelper(root, val); root = insertHelper(root, val);
return root; return root;
} }
/* 递归插入点(辅助方法) */ /* 递归插入点(辅助方法) */
private TreeNode? insertHelper(TreeNode? node, int val) private TreeNode? insertHelper(TreeNode? node, int val)
{ {
if (node == null) return new TreeNode(val); if (node == null) return new TreeNode(val);
/* 1. 查找插入位置,并插入点 */ /* 1. 查找插入位置,并插入点 */
if (val < node.val) if (val < node.val)
node.left = insertHelper(node.left, val); node.left = insertHelper(node.left, val);
else if (val > node.val) else if (val > node.val)
node.right = insertHelper(node.right, val); node.right = insertHelper(node.right, val);
else else
return node; // 重复点不插入直接返回 return node; // 重复点不插入直接返回
updateHeight(node); // 更新点高度 updateHeight(node); // 更新点高度
/* 2. 执行旋转操作,使该子树重新恢复平衡 */ /* 2. 执行旋转操作,使该子树重新恢复平衡 */
node = rotate(node); node = rotate(node);
// 返回子树的根 // 返回子树的根
return node; return node;
} }
/* 删除点 */ /* 删除点 */
public TreeNode? remove(int val) public TreeNode? remove(int val)
{ {
root = removeHelper(root, val); root = removeHelper(root, val);
return root; return root;
} }
/* 递归删除点(辅助方法) */ /* 递归删除点(辅助方法) */
private TreeNode? removeHelper(TreeNode? node, int val) private TreeNode? removeHelper(TreeNode? node, int val)
{ {
if (node == null) return null; if (node == null) return null;
/* 1. 查找点,并删除之 */ /* 1. 查找点,并删除之 */
if (val < node.val) if (val < node.val)
node.left = removeHelper(node.left, val); node.left = removeHelper(node.left, val);
else if (val > node.val) else if (val > node.val)
@ -152,33 +152,33 @@ class AVLTree
if (node.left == null || node.right == null) if (node.left == null || node.right == null)
{ {
TreeNode? child = node.left != null ? node.left : node.right; TreeNode? child = node.left != null ? node.left : node.right;
// 点数量 = 0 直接删除 node 并返回 // 点数量 = 0 直接删除 node 并返回
if (child == null) if (child == null)
return null; return null;
// 点数量 = 1 直接删除 node // 点数量 = 1 直接删除 node
else else
node = child; node = child;
} }
else else
{ {
// 点数量 = 2 则将中序遍历的下个结点删除并用该结点替换当前结 // 点数量 = 2 则将中序遍历的下个节点删除并用该节点替换当前节
TreeNode? temp = getInOrderNext(node.right); TreeNode? temp = getInOrderNext(node.right);
node.right = removeHelper(node.right, temp.val); node.right = removeHelper(node.right, temp.val);
node.val = temp.val; node.val = temp.val;
} }
} }
updateHeight(node); // 更新点高度 updateHeight(node); // 更新点高度
/* 2. 执行旋转操作,使该子树重新恢复平衡 */ /* 2. 执行旋转操作,使该子树重新恢复平衡 */
node = rotate(node); node = rotate(node);
// 返回子树的根 // 返回子树的根
return node; return node;
} }
/* 获取中序遍历中的下一个结点(仅适用于 root 有左子结点的情况) */ /* 获取中序遍历中的下一个节点(仅适用于 root 有左子节点的情况) */
private TreeNode? getInOrderNext(TreeNode? node) private TreeNode? getInOrderNext(TreeNode? node)
{ {
if (node == null) return node; if (node == null) return node;
// 循环访问左子结点直到叶结点时为最小结跳出 // 循环访问左子节点直到叶节点时为最小节跳出
while (node.left != null) while (node.left != null)
{ {
node = node.left; node = node.left;
@ -186,24 +186,24 @@ class AVLTree
return node; return node;
} }
/* 查找点 */ /* 查找点 */
public TreeNode? search(int val) public TreeNode? search(int val)
{ {
TreeNode? cur = root; TreeNode? cur = root;
// 循环查找越过叶点后跳出 // 循环查找越过叶点后跳出
while (cur != null) while (cur != null)
{ {
// 目标点在 cur 的右子树中 // 目标点在 cur 的右子树中
if (cur.val < val) if (cur.val < val)
cur = cur.right; cur = cur.right;
// 目标点在 cur 的左子树中 // 目标点在 cur 的左子树中
else if (cur.val > val) else if (cur.val > val)
cur = cur.left; cur = cur.left;
// 找到目标跳出循环 // 找到目标跳出循环
else else
break; break;
} }
// 返回目标 // 返回目标
return cur; return cur;
} }
} }
@ -213,14 +213,14 @@ public class avl_tree
static void testInsert(AVLTree tree, int val) static void testInsert(AVLTree tree, int val)
{ {
tree.insert(val); tree.insert(val);
Console.WriteLine("\n插入" + val + "AVL 树为"); Console.WriteLine("\n插入" + val + "AVL 树为");
PrintUtil.PrintTree(tree.root); PrintUtil.PrintTree(tree.root);
} }
static void testRemove(AVLTree tree, int val) static void testRemove(AVLTree tree, int val)
{ {
tree.remove(val); tree.remove(val);
Console.WriteLine("\n删除" + val + "AVL 树为"); Console.WriteLine("\n删除" + val + "AVL 树为");
PrintUtil.PrintTree(tree.root); PrintUtil.PrintTree(tree.root);
} }
@ -230,8 +230,8 @@ public class avl_tree
/* 初始化空 AVL 树 */ /* 初始化空 AVL 树 */
AVLTree avlTree = new AVLTree(); AVLTree avlTree = new AVLTree();
/* 插入点 */ /* 插入点 */
// 请关注插入点后AVL 树是如何保持平衡的 // 请关注插入点后AVL 树是如何保持平衡的
testInsert(avlTree, 1); testInsert(avlTree, 1);
testInsert(avlTree, 2); testInsert(avlTree, 2);
testInsert(avlTree, 3); testInsert(avlTree, 3);
@ -243,17 +243,17 @@ public class avl_tree
testInsert(avlTree, 10); testInsert(avlTree, 10);
testInsert(avlTree, 6); testInsert(avlTree, 6);
/* 插入重复点 */ /* 插入重复点 */
testInsert(avlTree, 7); testInsert(avlTree, 7);
/* 删除点 */ /* 删除点 */
// 请关注删除点后AVL 树是如何保持平衡的 // 请关注删除点后AVL 树是如何保持平衡的
testRemove(avlTree, 8); // 删除度为 0 testRemove(avlTree, 8); // 删除度为 0
testRemove(avlTree, 5); // 删除度为 1 testRemove(avlTree, 5); // 删除度为 1
testRemove(avlTree, 4); // 删除度为 2 testRemove(avlTree, 4); // 删除度为 2
/* 查询点 */ /* 查询点 */
TreeNode? node = avlTree.search(7); TreeNode? node = avlTree.search(7);
Console.WriteLine("\n查找到的点对象为 " + node + "点值 = " + node?.val); Console.WriteLine("\n查找到的点对象为 " + node + "点值 = " + node?.val);
} }
} }

View File

@ -19,7 +19,7 @@ class BinarySearchTree
root = buildTree(nums, 0, nums.Length - 1); // 构建二叉搜索树 root = buildTree(nums, 0, nums.Length - 1); // 构建二叉搜索树
} }
/* 获取二叉树根点 */ /* 获取二叉树根点 */
public TreeNode? getRoot() public TreeNode? getRoot()
{ {
return root; return root;
@ -29,7 +29,7 @@ class BinarySearchTree
public TreeNode? buildTree(int[] nums, int i, int j) public TreeNode? buildTree(int[] nums, int i, int j)
{ {
if (i > j) return null; if (i > j) return null;
// 将数组中间结点作为根结 // 将数组中间节点作为根节
int mid = (i + j) / 2; int mid = (i + j) / 2;
TreeNode root = new TreeNode(nums[mid]); TreeNode root = new TreeNode(nums[mid]);
// 递归建立左子树和右子树 // 递归建立左子树和右子树
@ -38,34 +38,34 @@ class BinarySearchTree
return root; return root;
} }
/* 查找点 */ /* 查找点 */
public TreeNode? search(int num) public TreeNode? search(int num)
{ {
TreeNode? cur = root; TreeNode? cur = root;
// 循环查找越过叶点后跳出 // 循环查找越过叶点后跳出
while (cur != null) while (cur != null)
{ {
// 目标点在 cur 的右子树中 // 目标点在 cur 的右子树中
if (cur.val < num) cur = cur.right; if (cur.val < num) cur = cur.right;
// 目标点在 cur 的左子树中 // 目标点在 cur 的左子树中
else if (cur.val > num) cur = cur.left; else if (cur.val > num) cur = cur.left;
// 找到目标跳出循环 // 找到目标跳出循环
else break; else break;
} }
// 返回目标 // 返回目标
return cur; return cur;
} }
/* 插入点 */ /* 插入点 */
public TreeNode? insert(int num) public TreeNode? insert(int num)
{ {
// 若树为空直接提前返回 // 若树为空直接提前返回
if (root == null) return null; if (root == null) return null;
TreeNode? cur = root, pre = null; TreeNode? cur = root, pre = null;
// 循环查找越过叶点后跳出 // 循环查找越过叶点后跳出
while (cur != null) while (cur != null)
{ {
// 找到重复直接返回 // 找到重复直接返回
if (cur.val == num) return null; if (cur.val == num) return null;
pre = cur; pre = cur;
// 插入位置在 cur 的右子树中 // 插入位置在 cur 的右子树中
@ -74,7 +74,7 @@ class BinarySearchTree
else cur = cur.left; else cur = cur.left;
} }
// 插入 val // 插入 val
TreeNode node = new TreeNode(num); TreeNode node = new TreeNode(num);
if (pre != null) if (pre != null)
{ {
@ -85,31 +85,31 @@ class BinarySearchTree
} }
/* 删除点 */ /* 删除点 */
public TreeNode? remove(int num) public TreeNode? remove(int num)
{ {
// 若树为空直接提前返回 // 若树为空直接提前返回
if (root == null) return null; if (root == null) return null;
TreeNode? cur = root, pre = null; TreeNode? cur = root, pre = null;
// 循环查找越过叶点后跳出 // 循环查找越过叶点后跳出
while (cur != null) while (cur != null)
{ {
// 找到待删除跳出循环 // 找到待删除跳出循环
if (cur.val == num) break; if (cur.val == num) break;
pre = cur; pre = cur;
// 待删除点在 cur 的右子树中 // 待删除点在 cur 的右子树中
if (cur.val < num) cur = cur.right; if (cur.val < num) cur = cur.right;
// 待删除点在 cur 的左子树中 // 待删除点在 cur 的左子树中
else cur = cur.left; else cur = cur.left;
} }
// 若无待删除则直接返回 // 若无待删除则直接返回
if (cur == null || pre == null) return null; if (cur == null || pre == null) return null;
// 点数量 = 0 or 1 // 点数量 = 0 or 1
if (cur.left == null || cur.right == null) if (cur.left == null || cur.right == null)
{ {
// 当子点数量 = 0 / 1 child = null / 该子 // 当子点数量 = 0 / 1 child = null / 该子
TreeNode? child = cur.left != null ? cur.left : cur.right; TreeNode? child = cur.left != null ? cur.left : cur.right;
// 删除 cur // 删除 cur
if (pre.left == cur) if (pre.left == cur)
{ {
pre.left = child; pre.left = child;
@ -119,15 +119,15 @@ class BinarySearchTree
pre.right = child; pre.right = child;
} }
} }
// 点数量 = 2 // 点数量 = 2
else else
{ {
// 获取中序遍历中 cur 的下一个 // 获取中序遍历中 cur 的下一个
TreeNode? nex = getInOrderNext(cur.right); TreeNode? nex = getInOrderNext(cur.right);
if (nex != null) if (nex != null)
{ {
int tmp = nex.val; int tmp = nex.val;
// 递归删除 nex // 递归删除 nex
remove(nex.val); remove(nex.val);
// nex 的值复制给 cur // nex 的值复制给 cur
cur.val = tmp; cur.val = tmp;
@ -136,11 +136,11 @@ class BinarySearchTree
return cur; return cur;
} }
/* 获取中序遍历中的下一个结点(仅适用于 root 有左子结点的情况) */ /* 获取中序遍历中的下一个节点(仅适用于 root 有左子节点的情况) */
private TreeNode? getInOrderNext(TreeNode? root) private TreeNode? getInOrderNext(TreeNode? root)
{ {
if (root == null) return root; if (root == null) return root;
// 循环访问左子结点直到叶结点时为最小结跳出 // 循环访问左子节点直到叶节点时为最小节跳出
while (root.left != null) while (root.left != null)
{ {
root = root.left; root = root.left;
@ -160,24 +160,24 @@ public class binary_search_tree
Console.WriteLine("\n初始化的二叉树为\n"); Console.WriteLine("\n初始化的二叉树为\n");
PrintUtil.PrintTree(bst.getRoot()); PrintUtil.PrintTree(bst.getRoot());
/* 查找点 */ /* 查找点 */
TreeNode? node = bst.search(7); TreeNode? node = bst.search(7);
Console.WriteLine("\n查找到的点对象为 " + node + "点值 = " + node.val); Console.WriteLine("\n查找到的点对象为 " + node + "点值 = " + node.val);
/* 插入点 */ /* 插入点 */
node = bst.insert(16); node = bst.insert(16);
Console.WriteLine("\n插入点 16 后,二叉树为\n"); Console.WriteLine("\n插入点 16 后,二叉树为\n");
PrintUtil.PrintTree(bst.getRoot()); PrintUtil.PrintTree(bst.getRoot());
/* 删除点 */ /* 删除点 */
bst.remove(1); bst.remove(1);
Console.WriteLine("\n删除点 1 后,二叉树为\n"); Console.WriteLine("\n删除点 1 后,二叉树为\n");
PrintUtil.PrintTree(bst.getRoot()); PrintUtil.PrintTree(bst.getRoot());
bst.remove(2); bst.remove(2);
Console.WriteLine("\n删除点 2 后,二叉树为\n"); Console.WriteLine("\n删除点 2 后,二叉树为\n");
PrintUtil.PrintTree(bst.getRoot()); PrintUtil.PrintTree(bst.getRoot());
bst.remove(4); bst.remove(4);
Console.WriteLine("\n删除点 4 后,二叉树为\n"); Console.WriteLine("\n删除点 4 后,二叉树为\n");
PrintUtil.PrintTree(bst.getRoot()); PrintUtil.PrintTree(bst.getRoot());
} }
} }

View File

@ -15,7 +15,7 @@ public class binary_tree
public void Test() public void Test()
{ {
/* 初始化二叉树 */ /* 初始化二叉树 */
// 初始化 // 初始化
TreeNode n1 = new TreeNode(1); TreeNode n1 = new TreeNode(1);
TreeNode n2 = new TreeNode(2); TreeNode n2 = new TreeNode(2);
TreeNode n3 = new TreeNode(3); TreeNode n3 = new TreeNode(3);
@ -29,16 +29,16 @@ public class binary_tree
Console.WriteLine("\n初始化二叉树\n"); Console.WriteLine("\n初始化二叉树\n");
PrintUtil.PrintTree(n1); PrintUtil.PrintTree(n1);
/* 插入与删除点 */ /* 插入与删除点 */
TreeNode P = new TreeNode(0); TreeNode P = new TreeNode(0);
// n1 -> n2 中间插入 P // n1 -> n2 中间插入 P
n1.left = P; n1.left = P;
P.left = n2; P.left = n2;
Console.WriteLine("\n插入点 P 后\n"); Console.WriteLine("\n插入点 P 后\n");
PrintUtil.PrintTree(n1); PrintUtil.PrintTree(n1);
// 删除 P // 删除 P
n1.left = n2; n1.left = n2;
Console.WriteLine("\n删除点 P 后\n"); Console.WriteLine("\n删除点 P 后\n");
PrintUtil.PrintTree(n1); PrintUtil.PrintTree(n1);
} }
} }

View File

@ -15,7 +15,7 @@ public class binary_tree_bfs
/* 层序遍历 */ /* 层序遍历 */
public List<int> levelOrder(TreeNode root) public List<int> levelOrder(TreeNode root)
{ {
// 初始化队列加入根 // 初始化队列加入根
Queue<TreeNode> queue = new(); Queue<TreeNode> queue = new();
queue.Enqueue(root); queue.Enqueue(root);
// 初始化一个列表用于保存遍历序列 // 初始化一个列表用于保存遍历序列
@ -23,11 +23,11 @@ public class binary_tree_bfs
while (queue.Count != 0) while (queue.Count != 0)
{ {
TreeNode node = queue.Dequeue(); // 队列出队 TreeNode node = queue.Dequeue(); // 队列出队
list.Add(node.val); // 保存点值 list.Add(node.val); // 保存点值
if (node.left != null) if (node.left != null)
queue.Enqueue(node.left); // 左子点入队 queue.Enqueue(node.left); // 左子点入队
if (node.right != null) if (node.right != null)
queue.Enqueue(node.right); // 右子点入队 queue.Enqueue(node.right); // 右子点入队
} }
return list; return list;
} }
@ -42,6 +42,6 @@ public class binary_tree_bfs
PrintUtil.PrintTree(root); PrintUtil.PrintTree(root);
List<int> list = levelOrder(root); List<int> list = levelOrder(root);
Console.WriteLine("\n层序遍历的点打印序列 = " + string.Join(",", list.ToArray())); Console.WriteLine("\n层序遍历的点打印序列 = " + string.Join(",", list.ToArray()));
} }
} }

View File

@ -17,7 +17,7 @@ public class binary_tree_dfs
void preOrder(TreeNode? root) void preOrder(TreeNode? root)
{ {
if (root == null) return; if (root == null) return;
// 访问优先级 -> 左子树 -> 右子树 // 访问优先级 -> 左子树 -> 右子树
list.Add(root.val); list.Add(root.val);
preOrder(root.left); preOrder(root.left);
preOrder(root.right); preOrder(root.right);
@ -27,7 +27,7 @@ public class binary_tree_dfs
void inOrder(TreeNode? root) void inOrder(TreeNode? root)
{ {
if (root == null) return; if (root == null) return;
// 访问优先级左子树 -> -> 右子树 // 访问优先级左子树 -> -> 右子树
inOrder(root.left); inOrder(root.left);
list.Add(root.val); list.Add(root.val);
inOrder(root.right); inOrder(root.right);
@ -37,7 +37,7 @@ public class binary_tree_dfs
void postOrder(TreeNode? root) void postOrder(TreeNode? root)
{ {
if (root == null) return; if (root == null) return;
// 访问优先级左子树 -> 右子树 -> // 访问优先级左子树 -> 右子树 ->
postOrder(root.left); postOrder(root.left);
postOrder(root.right); postOrder(root.right);
list.Add(root.val); list.Add(root.val);
@ -54,14 +54,14 @@ public class binary_tree_dfs
list.Clear(); list.Clear();
preOrder(root); preOrder(root);
Console.WriteLine("\n前序遍历的点打印序列 = " + string.Join(",", list.ToArray())); Console.WriteLine("\n前序遍历的点打印序列 = " + string.Join(",", list.ToArray()));
list.Clear(); list.Clear();
inOrder(root); inOrder(root);
Console.WriteLine("\n中序遍历的点打印序列 = " + string.Join(",", list.ToArray())); Console.WriteLine("\n中序遍历的点打印序列 = " + string.Join(",", list.ToArray()));
list.Clear(); list.Clear();
postOrder(root); postOrder(root);
Console.WriteLine("\n后序遍历的点打印序列 = " + string.Join(",", list.ToArray())); Console.WriteLine("\n后序遍历的点打印序列 = " + string.Join(",", list.ToArray()));
} }
} }

View File

@ -8,10 +8,10 @@ namespace hello_algo.include;
public class TreeNode public class TreeNode
{ {
public int val; // 点值 public int val; // 点值
public int height; // 点高度 public int height; // 点高度
public TreeNode? left; // 左子点引用 public TreeNode? left; // 左子点引用
public TreeNode? right; // 右子点引用 public TreeNode? right; // 右子点引用
public TreeNode(int x) public TreeNode(int x)
{ {

View File

@ -9,14 +9,14 @@ import '../utils/print_util.dart';
class LinkedList { class LinkedList {
/* 在链表的结点 n0 之后插入结点 P */ /* 在链表的节点 n0 之后插入节点 P */
void insert(ListNode n0, ListNode P) { void insert(ListNode n0, ListNode P) {
ListNode? n1 = n0.next; ListNode? n1 = n0.next;
P.next = n1; P.next = n1;
n0.next = P; n0.next = P;
} }
/* 删除链表的结点 n0 之后的首个结点 */ /* 删除链表的节点 n0 之后的首个节点 */
void remove(ListNode n0) { void remove(ListNode n0) {
if (n0.next == null) return; if (n0.next == null) return;
ListNode P = n0.next!; ListNode P = n0.next!;
@ -24,7 +24,7 @@ class LinkedList {
n0.next = n1; n0.next = n1;
} }
/* 访问链表中索引为 index 的点 */ /* 访问链表中索引为 index 的点 */
ListNode? access(ListNode? head, int index) { ListNode? access(ListNode? head, int index) {
for (var i = 0; i < index; i++) { for (var i = 0; i < index; i++) {
if (head == null) return null; if (head == null) return null;
@ -33,7 +33,7 @@ class LinkedList {
return head; return head;
} }
/* 在链表中查找值为 target 的首个点 */ /* 在链表中查找值为 target 的首个点 */
int find(ListNode? head, int target) { int find(ListNode? head, int target) {
int index = 0; int index = 0;
while (head != null) { while (head != null) {
@ -50,7 +50,7 @@ class LinkedList {
/* Driver Code */ /* Driver Code */
int main() { int main() {
// //
// //
ListNode n0 = ListNode(1); ListNode n0 = ListNode(1);
ListNode n1 = ListNode(3); ListNode n1 = ListNode(3);
ListNode n2 = ListNode(2); ListNode n2 = ListNode(2);
@ -65,21 +65,21 @@ int main() {
print('初始化的链表为'); print('初始化的链表为');
printLinkedList(n0); printLinkedList(n0);
/* 插入点 */ /* 插入点 */
LinkedList().insert(n0, ListNode(0)); LinkedList().insert(n0, ListNode(0));
printLinkedList(n0); printLinkedList(n0);
/* 删除点 */ /* 删除点 */
LinkedList().remove(n0); LinkedList().remove(n0);
printLinkedList(n0); printLinkedList(n0);
/* 访问点 */ /* 访问点 */
ListNode? node = LinkedList().access(n0, 3); ListNode? node = LinkedList().access(n0, 3);
print('链表中索引 3 处的点的值 = ${node!.val}'); print('链表中索引 3 处的点的值 = ${node!.val}');
/* 查找点 */ /* 查找点 */
int index = LinkedList().find(n0, 2); int index = LinkedList().find(n0, 2);
print('链表中值为 2 的点的索引 = $index'); print('链表中值为 2 的点的索引 = $index');
return 0; return 0;
} }

View File

@ -4,19 +4,19 @@
* Author: liuyuxin (gvenusleo@gmail.com) * Author: liuyuxin (gvenusleo@gmail.com)
*/ */
/* 双向链表点 */ /* 双向链表点 */
class ListNode { class ListNode {
int val; // int val; //
ListNode? next; // ListNode? next; //
ListNode? prev; // ListNode? prev; //
ListNode(this.val, {this.next, this.prev}); ListNode(this.val, {this.next, this.prev});
} }
/* 基于双向链表实现的双向对列 */ /* 基于双向链表实现的双向对列 */
class LinkedListDeque { class LinkedListDeque {
late ListNode? _front; // _front late ListNode? _front; // _front
late ListNode? _rear; // _rear late ListNode? _rear; // _rear
int _queSize = 0; // int _queSize = 0; //
LinkedListDeque() { LinkedListDeque() {
@ -45,13 +45,13 @@ class LinkedListDeque {
// node // node
_front!.prev = node; _front!.prev = node;
node.next = _front; node.next = _front;
_front = node; // _front = node; //
} else { } else {
// //
// node // node
_rear!.next = node; _rear!.next = node;
node.prev = _rear; node.prev = _rear;
_rear = node; // _rear = node; //
} }
_queSize++; // _queSize++; //
} }
@ -75,24 +75,24 @@ class LinkedListDeque {
final int val; final int val;
if (isFront) { if (isFront) {
// //
val = _front!.val; // val = _front!.val; //
// //
ListNode? fNext = _front!.next; ListNode? fNext = _front!.next;
if (fNext != null) { if (fNext != null) {
fNext.prev = null; fNext.prev = null;
_front!.next = null; _front!.next = null;
} }
_front = fNext; // _front = fNext; //
} else { } else {
// //
val = _rear!.val; // val = _rear!.val; //
// //
ListNode? rPrev = _rear!.prev; ListNode? rPrev = _rear!.prev;
if (rPrev != null) { if (rPrev != null) {
rPrev.next = null; rPrev.next = null;
_rear!.prev = null; _rear!.prev = null;
} }
_rear = rPrev; // _rear = rPrev; //
} }
_queSize--; // _queSize--; //
return val; return val;

View File

@ -8,8 +8,8 @@ import '../utils/list_node.dart';
/* 基于链表实现的队列 */ /* 基于链表实现的队列 */
class LinkedListQueue { class LinkedListQueue {
ListNode? _front; // _front ListNode? _front; // _front
ListNode? _rear; // _rear ListNode? _rear; // _rear
int _queSize = 0; // int _queSize = 0; //
LinkedListQueue() { LinkedListQueue() {
@ -29,14 +29,14 @@ class LinkedListQueue {
/* 入队 */ /* 入队 */
void push(int num) { void push(int num) {
// num // num
final node = ListNode(num); final node = ListNode(num);
// //
if (_front == null) { if (_front == null) {
_front = node; _front = node;
_rear = node; _rear = node;
} else { } else {
// //
_rear!.next = node; _rear!.next = node;
_rear = node; _rear = node;
} }
@ -46,7 +46,7 @@ class LinkedListQueue {
/* 出队 */ /* 出队 */
int pop() { int pop() {
final int num = peek(); final int num = peek();
// //
_front = _front!.next; _front = _front!.next;
_queSize--; _queSize--;
return num; return num;

View File

@ -8,7 +8,7 @@ import '../utils/list_node.dart';
/* 基于链表类实现的栈 */ /* 基于链表类实现的栈 */
class LinkedListStack { class LinkedListStack {
ListNode? _stackPeek; // ListNode? _stackPeek; //
int _stkSize = 0; // int _stkSize = 0; //
LinkedListStack() { LinkedListStack() {

View File

@ -16,22 +16,22 @@ class AVLTree {
root = null; root = null;
} }
/* 获取点高度 */ /* 获取点高度 */
int height(TreeNode? node) { int height(TreeNode? node) {
return node == null ? -1 : node.height; return node == null ? -1 : node.height;
} }
/* 更新点高度 */ /* 更新点高度 */
void updateHeight(TreeNode? node) { void updateHeight(TreeNode? node) {
// + 1 // + 1
node!.height = max(height(node.left), height(node.right)) + 1; node!.height = max(height(node.left), height(node.right)) + 1;
} }
/* 获取平衡因子 */ /* 获取平衡因子 */
int balanceFactor(TreeNode? node) { int balanceFactor(TreeNode? node) {
// 0 // 0
if (node == null) return 0; if (node == null) return 0;
// = - // = -
return height(node.left) - height(node.right); return height(node.left) - height(node.right);
} }
@ -42,10 +42,10 @@ class AVLTree {
// child node // child node
child.right = node; child.right = node;
node.left = grandChild; node.left = grandChild;
// //
updateHeight(node); updateHeight(node);
updateHeight(child); updateHeight(child);
// //
return child; return child;
} }
@ -56,16 +56,16 @@ class AVLTree {
// child node // child node
child.left = node; child.left = node;
node.right = grandChild; node.right = grandChild;
// //
updateHeight(node); updateHeight(node);
updateHeight(child); updateHeight(child);
// //
return child; return child;
} }
/* 执行旋转操作,使该子树重新恢复平衡 */ /* 执行旋转操作,使该子树重新恢复平衡 */
TreeNode? rotate(TreeNode? node) { TreeNode? rotate(TreeNode? node) {
// node // node
int factor = balanceFactor(node); int factor = balanceFactor(node);
// //
if (factor > 1) { if (factor > 1) {
@ -93,39 +93,39 @@ class AVLTree {
return node; return node;
} }
/* 插入点 */ /* 插入点 */
TreeNode? insert(int val) { TreeNode? insert(int val) {
root = insertHelper(root, val); root = insertHelper(root, val);
return root; return root;
} }
/* 递归插入点(辅助方法) */ /* 递归插入点(辅助方法) */
TreeNode? insertHelper(TreeNode? node, int val) { TreeNode? insertHelper(TreeNode? node, int val) {
if (node == null) return TreeNode(val); if (node == null) return TreeNode(val);
/* 1. 查找插入位置,并插入点 */ /* 1. 查找插入位置,并插入点 */
if (val < node.val) if (val < node.val)
node.left = insertHelper(node.left, val); node.left = insertHelper(node.left, val);
else if (val > node.val) else if (val > node.val)
node.right = insertHelper(node.right, val); node.right = insertHelper(node.right, val);
else else
return node; // return node; //
updateHeight(node); // updateHeight(node); //
/* 2. 执行旋转操作,使该子树重新恢复平衡 */ /* 2. 执行旋转操作,使该子树重新恢复平衡 */
node = rotate(node); node = rotate(node);
// //
return node; return node;
} }
/* 删除点 */ /* 删除点 */
TreeNode? remove(int val) { TreeNode? remove(int val) {
root = removeHelper(root, val); root = removeHelper(root, val);
return root; return root;
} }
/* 递归删除点(辅助方法) */ /* 递归删除点(辅助方法) */
TreeNode? removeHelper(TreeNode? node, int val) { TreeNode? removeHelper(TreeNode? node, int val) {
if (node == null) return null; if (node == null) return null;
/* 1. 查找点,并删除之 */ /* 1. 查找点,并删除之 */
if (val < node.val) if (val < node.val)
node.left = removeHelper(node.left, val); node.left = removeHelper(node.left, val);
else if (val > node.val) else if (val > node.val)
@ -133,48 +133,48 @@ class AVLTree {
else { else {
if (node.left == null || node.right == null) { if (node.left == null || node.right == null) {
TreeNode? child = node.left ?? node.right; TreeNode? child = node.left ?? node.right;
// = 0 node // = 0 node
if (child == null) if (child == null)
return null; return null;
// = 1 node // = 1 node
else else
node = child; node = child;
} else { } else {
// = 2 // = 2
TreeNode? temp = getInOrderNext(node.right); TreeNode? temp = getInOrderNext(node.right);
node.right = removeHelper(node.right, temp!.val); node.right = removeHelper(node.right, temp!.val);
node.val = temp.val; node.val = temp.val;
} }
} }
updateHeight(node); // updateHeight(node); //
/* 2. 执行旋转操作,使该子树重新恢复平衡 */ /* 2. 执行旋转操作,使该子树重新恢复平衡 */
node = rotate(node); node = rotate(node);
// //
return node; return node;
} }
/* 获取中序遍历中的下一个结点(仅适用于 root 有左子结点的情况) */ /* 获取中序遍历中的下一个节点(仅适用于 root 有左子节点的情况) */
TreeNode? getInOrderNext(TreeNode? node) { TreeNode? getInOrderNext(TreeNode? node) {
if (node == null) return node; if (node == null) return node;
// 访 // 访
while (node!.left != null) { while (node!.left != null) {
node = node.left; node = node.left;
} }
return node; return node;
} }
/* 查找点 */ /* 查找点 */
TreeNode? search(int val) { TreeNode? search(int val) {
TreeNode? cur = root; TreeNode? cur = root;
// //
while (cur != null) { while (cur != null) {
// cur // cur
if (val < cur.val) if (val < cur.val)
cur = cur.left; cur = cur.left;
// cur // cur
else if (val > cur.val) else if (val > cur.val)
cur = cur.right; cur = cur.right;
// //
else else
break; break;
} }
@ -184,13 +184,13 @@ class AVLTree {
void testInsert(AVLTree tree, int val) { void testInsert(AVLTree tree, int val) {
tree.insert(val); tree.insert(val);
print("\n插入$valAVL 树为"); print("\n插入$valAVL 树为");
printTree(tree.root); printTree(tree.root);
} }
void testRemove(AVLTree tree, int val) { void testRemove(AVLTree tree, int val) {
tree.remove(val); tree.remove(val);
print("\n删除$valAVL 树为"); print("\n删除$valAVL 树为");
printTree(tree.root); printTree(tree.root);
} }
@ -198,8 +198,8 @@ void testRemove(AVLTree tree, int val) {
void main() { void main() {
/* 初始化空 AVL 树 */ /* 初始化空 AVL 树 */
AVLTree avlTree = AVLTree(); AVLTree avlTree = AVLTree();
/* 插入点 */ /* 插入点 */
// AVL // AVL
testInsert(avlTree, 1); testInsert(avlTree, 1);
testInsert(avlTree, 2); testInsert(avlTree, 2);
testInsert(avlTree, 3); testInsert(avlTree, 3);
@ -211,16 +211,16 @@ void main() {
testInsert(avlTree, 10); testInsert(avlTree, 10);
testInsert(avlTree, 6); testInsert(avlTree, 6);
/* 插入重复点 */ /* 插入重复点 */
testInsert(avlTree, 7); testInsert(avlTree, 7);
/* 删除点 */ /* 删除点 */
// AVL // AVL
testRemove(avlTree, 8); // 0 testRemove(avlTree, 8); // 0
testRemove(avlTree, 5); // 1 testRemove(avlTree, 5); // 1
testRemove(avlTree, 4); // 2 testRemove(avlTree, 4); // 2
/* 查询点 */ /* 查询点 */
TreeNode? node = avlTree.search(7); TreeNode? node = avlTree.search(7);
print("\n查找到的结点对象为 $node,结点值 = ${node!.val}"); print("\n查找到的节点对象为 $node,节点值 = ${node!.val}");
} }

View File

@ -15,7 +15,7 @@ void binarySearchTree(List<int> nums) {
root = buildTree(nums, 0, nums.length - 1); // root = buildTree(nums, 0, nums.length - 1); //
} }
/* 获取二叉树的根点 */ /* 获取二叉树的根点 */
TreeNode? getRoot() { TreeNode? getRoot() {
return root; return root;
} }
@ -25,7 +25,7 @@ TreeNode? buildTree(List<int> nums, int i, int j) {
if (i > j) { if (i > j) {
return null; return null;
} }
// //
int mid = (i + j) ~/ 2; int mid = (i + j) ~/ 2;
TreeNode? root = TreeNode(nums[mid]); TreeNode? root = TreeNode(nums[mid]);
root.left = buildTree(nums, i, mid - 1); root.left = buildTree(nums, i, mid - 1);
@ -33,34 +33,34 @@ TreeNode? buildTree(List<int> nums, int i, int j) {
return root; return root;
} }
/* 查找点 */ /* 查找点 */
TreeNode? search(int num) { TreeNode? search(int num) {
TreeNode? cur = root; TreeNode? cur = root;
// //
while (cur != null) { while (cur != null) {
// cur // cur
if (cur.val < num) if (cur.val < num)
cur = cur.right; cur = cur.right;
// cur // cur
else if (cur.val > num) else if (cur.val > num)
cur = cur.left; cur = cur.left;
// //
else else
break; break;
} }
// //
return cur; return cur;
} }
/* 插入点 */ /* 插入点 */
TreeNode? insert(int num) { TreeNode? insert(int num) {
// //
if (root == null) return null; if (root == null) return null;
TreeNode? cur = root; TreeNode? cur = root;
TreeNode? pre = null; TreeNode? pre = null;
// //
while (cur != null) { while (cur != null) {
// //
if (cur.val == num) return null; if (cur.val == num) return null;
pre = cur; pre = cur;
// cur // cur
@ -70,7 +70,7 @@ TreeNode? insert(int num) {
else else
cur = cur.left; cur = cur.left;
} }
// val // val
TreeNode? node = TreeNode(num); TreeNode? node = TreeNode(num);
if (pre!.val < num) if (pre!.val < num)
pre.right = node; pre.right = node;
@ -79,42 +79,42 @@ TreeNode? insert(int num) {
return node; return node;
} }
/* 删除点 */ /* 删除点 */
TreeNode? remove(int num) { TreeNode? remove(int num) {
// //
if (root == null) return null; if (root == null) return null;
TreeNode? cur = root; TreeNode? cur = root;
TreeNode? pre = null; TreeNode? pre = null;
// //
while (cur != null) { while (cur != null) {
// //
if (cur.val == num) break; if (cur.val == num) break;
pre = cur; pre = cur;
// cur // cur
if (cur.val < num) if (cur.val < num)
cur = cur.right; cur = cur.right;
// cur // cur
else else
cur = cur.left; cur = cur.left;
} }
// //
if (cur == null) return null; if (cur == null) return null;
// = 0 or 1 // = 0 or 1
if (cur.left == null || cur.right == null) { if (cur.left == null || cur.right == null) {
// = 0 / 1 child = null / // = 0 / 1 child = null /
TreeNode? child = cur.left ?? cur.right; TreeNode? child = cur.left ?? cur.right;
// cur // cur
if (pre!.left == cur) if (pre!.left == cur)
pre.left = child; pre.left = child;
else else
pre.right = child; pre.right = child;
} else { } else {
// = 2 // = 2
// cur // cur
TreeNode? nex = getInOrderNext(cur.right); TreeNode? nex = getInOrderNext(cur.right);
int tem = nex!.val; int tem = nex!.val;
// nex // nex
remove(nex.val); remove(nex.val);
// nex cur // nex cur
cur.val = tem; cur.val = tem;
@ -122,10 +122,10 @@ TreeNode? remove(int num) {
return cur; return cur;
} }
/* 获取中序遍历中的下一个结点(仅适用于 root 有左子结点的情况) */ /* 获取中序遍历中的下一个节点(仅适用于 root 有左子节点的情况) */
TreeNode? getInOrderNext(TreeNode? root) { TreeNode? getInOrderNext(TreeNode? root) {
if (root == null) return null; if (root == null) return null;
// 访 // 访
while (root!.left != null) { while (root!.left != null) {
root = root.left; root = root.left;
} }
@ -140,23 +140,23 @@ void main() {
print("\n初始化的二叉树为\n"); print("\n初始化的二叉树为\n");
printTree(getRoot()); printTree(getRoot());
/* 查找点 */ /* 查找点 */
TreeNode? node = search(7); TreeNode? node = search(7);
print("\n查找到的结点对象为 $node,结点值 = ${node?.val}"); print("\n查找到的节点对象为 $node,节点值 = ${node?.val}");
/* 插入点 */ /* 插入点 */
node = insert(16); node = insert(16);
print("\n插入点 16 后,二叉树为\n"); print("\n插入点 16 后,二叉树为\n");
printTree(getRoot()); printTree(getRoot());
/* 删除点 */ /* 删除点 */
remove(1); remove(1);
print("\n删除点 1 后,二叉树为\n"); print("\n删除点 1 后,二叉树为\n");
printTree(getRoot()); printTree(getRoot());
remove(2); remove(2);
print("\n删除点 2 后,二叉树为\n"); print("\n删除点 2 后,二叉树为\n");
printTree(getRoot()); printTree(getRoot());
remove(4); remove(4);
print("\n删除点 4 后,二叉树为\n"); print("\n删除点 4 后,二叉树为\n");
printTree(getRoot()); printTree(getRoot());
} }

View File

@ -9,7 +9,7 @@ import '../utils/tree_node.dart';
void main() { void main() {
/* 初始化二叉树 */ /* 初始化二叉树 */
// //
TreeNode n1 = TreeNode(1); TreeNode n1 = TreeNode(1);
TreeNode n2 = TreeNode(2); TreeNode n2 = TreeNode(2);
TreeNode n3 = TreeNode(3); TreeNode n3 = TreeNode(3);
@ -23,15 +23,15 @@ void main() {
print("\n初始化二叉树\n"); print("\n初始化二叉树\n");
printTree(n1); printTree(n1);
/* 插入与删除点 */ /* 插入与删除点 */
TreeNode p = TreeNode(0); TreeNode p = TreeNode(0);
// n1 -> n2 p // n1 -> n2 p
n1.left = p; n1.left = p;
p.left = n2; p.left = n2;
print("\n插入点 P 后\n"); print("\n插入点 P 后\n");
printTree(n1); printTree(n1);
// P // P
n1.left = n2; n1.left = n2;
print("\n删除点 P 后\n"); print("\n删除点 P 后\n");
printTree(n1); printTree(n1);
} }

View File

@ -10,16 +10,16 @@ import '../utils/tree_node.dart';
/* 层序遍历 */ /* 层序遍历 */
List<int> levelOrder(TreeNode? root) { List<int> levelOrder(TreeNode? root) {
// //
Queue<TreeNode?> queue = Queue(); Queue<TreeNode?> queue = Queue();
queue.add(root); queue.add(root);
// //
List<int> res = []; List<int> res = [];
while (queue.isNotEmpty) { while (queue.isNotEmpty) {
TreeNode? node = queue.removeFirst(); // TreeNode? node = queue.removeFirst(); //
res.add(node!.val); // res.add(node!.val); //
if (node.left != null) queue.add(node.left); // if (node.left != null) queue.add(node.left); //
if (node.right != null) queue.add(node.right); // if (node.right != null) queue.add(node.right); //
} }
return res; return res;
} }
@ -34,5 +34,5 @@ void main() {
// //
List<int> res = levelOrder(root); List<int> res = levelOrder(root);
print("\n层序遍历的点打印序列 = $res"); print("\n层序遍历的点打印序列 = $res");
} }

View File

@ -13,7 +13,7 @@ List<int> list = [];
/* 前序遍历 */ /* 前序遍历 */
void preOrder(TreeNode? node) { void preOrder(TreeNode? node) {
if (node == null) return; if (node == null) return;
// 访 -> -> // 访 -> ->
list.add(node.val); list.add(node.val);
preOrder(node.left); preOrder(node.left);
preOrder(node.right); preOrder(node.right);
@ -22,7 +22,7 @@ void preOrder(TreeNode? node) {
/* 中序遍历 */ /* 中序遍历 */
void inOrder(TreeNode? node) { void inOrder(TreeNode? node) {
if (node == null) return; if (node == null) return;
// 访 -> -> // 访 -> ->
inOrder(node.left); inOrder(node.left);
list.add(node.val); list.add(node.val);
inOrder(node.right); inOrder(node.right);
@ -31,7 +31,7 @@ void inOrder(TreeNode? node) {
/* 后序遍历 */ /* 后序遍历 */
void postOrder(TreeNode? node) { void postOrder(TreeNode? node) {
if (node == null) return; if (node == null) return;
// 访 -> -> // 访 -> ->
postOrder(node.left); postOrder(node.left);
postOrder(node.right); postOrder(node.right);
list.add(node.val); list.add(node.val);
@ -48,15 +48,15 @@ void main() {
/* 前序遍历 */ /* 前序遍历 */
list.clear(); list.clear();
preOrder(root); preOrder(root);
print("\n前序遍历的点打印序列 = $list"); print("\n前序遍历的点打印序列 = $list");
/* 中序遍历 */ /* 中序遍历 */
list.clear(); list.clear();
inOrder(root); inOrder(root);
print("\n中序遍历的点打印序列 = $list"); print("\n中序遍历的点打印序列 = $list");
/* 后序遍历 */ /* 后序遍历 */
list.clear(); list.clear();
postOrder(root); postOrder(root);
print("\n后序遍历的点打印序列 = $list"); print("\n后序遍历的点打印序列 = $list");
} }

View File

@ -7,10 +7,10 @@
import 'dart:collection'; import 'dart:collection';
class TreeNode { class TreeNode {
int val; // int val; //
int height; // int height; //
TreeNode? left; // TreeNode? left; //
TreeNode? right; // TreeNode? right; //
TreeNode(this.val, [this.height = 0, this.left, this.right]); TreeNode(this.val, [this.height = 0, this.left, this.right]);
} }

View File

@ -8,14 +8,14 @@ import (
. "github.com/krahets/hello-algo/pkg" . "github.com/krahets/hello-algo/pkg"
) )
/* 在链表的结点 n0 之后插入结点 P */ /* 在链表的节点 n0 之后插入节点 P */
func insertNode(n0 *ListNode, P *ListNode) { func insertNode(n0 *ListNode, P *ListNode) {
n1 := n0.Next n1 := n0.Next
P.Next = n1 P.Next = n1
n0.Next = P n0.Next = P
} }
/* 删除链表的结点 n0 之后的首个结点 */ /* 删除链表的节点 n0 之后的首个节点 */
func removeNode(n0 *ListNode) { func removeNode(n0 *ListNode) {
if n0.Next == nil { if n0.Next == nil {
return return
@ -26,7 +26,7 @@ func removeNode(n0 *ListNode) {
n0.Next = n1 n0.Next = n1
} }
/* 访问链表中索引为 index 的点 */ /* 访问链表中索引为 index 的点 */
func access(head *ListNode, index int) *ListNode { func access(head *ListNode, index int) *ListNode {
for i := 0; i < index; i++ { for i := 0; i < index; i++ {
if head == nil { if head == nil {
@ -37,7 +37,7 @@ func access(head *ListNode, index int) *ListNode {
return head return head
} }
/* 在链表中查找值为 target 的首个点 */ /* 在链表中查找值为 target 的首个点 */
func findNode(head *ListNode, target int) int { func findNode(head *ListNode, target int) int {
index := 0 index := 0
for head != nil { for head != nil {

View File

@ -13,7 +13,7 @@ import (
func TestLinkedList(t *testing.T) { func TestLinkedList(t *testing.T) {
/* 初始化链表 1 -> 3 -> 2 -> 5 -> 4 */ /* 初始化链表 1 -> 3 -> 2 -> 5 -> 4 */
// 初始化各个 // 初始化各个
n0 := NewListNode(1) n0 := NewListNode(1)
n1 := NewListNode(3) n1 := NewListNode(3)
n2 := NewListNode(2) n2 := NewListNode(2)
@ -28,21 +28,21 @@ func TestLinkedList(t *testing.T) {
fmt.Println("初始化的链表为") fmt.Println("初始化的链表为")
PrintLinkedList(n0) PrintLinkedList(n0)
/* 插入点 */ /* 插入点 */
insertNode(n0, NewListNode(0)) insertNode(n0, NewListNode(0))
fmt.Println("插入点后的链表为") fmt.Println("插入点后的链表为")
PrintLinkedList(n0) PrintLinkedList(n0)
/* 删除点 */ /* 删除点 */
removeNode(n0) removeNode(n0)
fmt.Println("删除点后的链表为") fmt.Println("删除点后的链表为")
PrintLinkedList(n0) PrintLinkedList(n0)
/* 访问点 */ /* 访问点 */
node := access(n0, 3) node := access(n0, 3)
fmt.Println("链表中索引 3 处的点的值 =", node) fmt.Println("链表中索引 3 处的点的值 =", node)
/* 查找点 */ /* 查找点 */
index := findNode(n0, 2) index := findNode(n0, 2)
fmt.Println("链表中值为 2 的点的索引 =", index) fmt.Println("链表中值为 2 的点的索引 =", index)
} }

View File

@ -27,23 +27,23 @@ func newMaxHeap(nums []any) *maxHeap {
// 将列表元素原封不动添加进堆 // 将列表元素原封不动添加进堆
h := &maxHeap{data: nums} h := &maxHeap{data: nums}
for i := len(h.data) - 1; i >= 0; i-- { for i := len(h.data) - 1; i >= 0; i-- {
// 堆化除叶结点以外的其他所有结 // 堆化除叶节点以外的其他所有节
h.siftDown(i) h.siftDown(i)
} }
return h return h
} }
/* 获取左子点索引 */ /* 获取左子点索引 */
func (h *maxHeap) left(i int) int { func (h *maxHeap) left(i int) int {
return 2*i + 1 return 2*i + 1
} }
/* 获取右子点索引 */ /* 获取右子点索引 */
func (h *maxHeap) right(i int) int { func (h *maxHeap) right(i int) int {
return 2*i + 2 return 2*i + 2
} }
/* 获取父点索引 */ /* 获取父点索引 */
func (h *maxHeap) parent(i int) int { func (h *maxHeap) parent(i int) int {
// 向下整除 // 向下整除
return (i - 1) / 2 return (i - 1) / 2
@ -71,22 +71,22 @@ func (h *maxHeap) peek() any {
/* 元素入堆 */ /* 元素入堆 */
func (h *maxHeap) push(val any) { func (h *maxHeap) push(val any) {
// 添加 // 添加
h.data = append(h.data, val) h.data = append(h.data, val)
// 从底至顶堆化 // 从底至顶堆化
h.siftUp(len(h.data) - 1) h.siftUp(len(h.data) - 1)
} }
/* 从点 i 开始,从底至顶堆化 */ /* 从点 i 开始,从底至顶堆化 */
func (h *maxHeap) siftUp(i int) { func (h *maxHeap) siftUp(i int) {
for true { for true {
// 获取结点 i 的父结 // 获取节点 i 的父节
p := h.parent(i) p := h.parent(i)
// 当“越过根结点”或“结点无需修复”时,结束堆化 // 当“越过根节点”或“节点无需修复”时,结束堆化
if p < 0 || h.data[i].(int) <= h.data[p].(int) { if p < 0 || h.data[i].(int) <= h.data[p].(int) {
break break
} }
// 交换两 // 交换两
h.swap(i, p) h.swap(i, p)
// 循环向上堆化 // 循环向上堆化
i = p i = p
@ -100,9 +100,9 @@ func (h *maxHeap) pop() any {
fmt.Println("error") fmt.Println("error")
return nil return nil
} }
// 交换根结点与最右叶结点(即交换首元素与尾元素) // 交换根节点与最右叶节点(即交换首元素与尾元素)
h.swap(0, h.size()-1) h.swap(0, h.size()-1)
// 删除 // 删除
val := h.data[len(h.data)-1] val := h.data[len(h.data)-1]
h.data = 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 return val
} }
/* 从点 i 开始,从顶至底堆化 */ /* 从点 i 开始,从顶至底堆化 */
func (h *maxHeap) siftDown(i int) { func (h *maxHeap) siftDown(i int) {
for true { for true {
// 判断结点 i, l, r 中值最大的结点,记为 max // 判断节点 i, l, r 中值最大的节点,记为 max
l, r, max := h.left(i), h.right(i), i l, r, max := h.left(i), h.right(i), i
if l < h.size() && h.data[l].(int) > h.data[max].(int) { if l < h.size() && h.data[l].(int) > h.data[max].(int) {
max = l max = l
@ -123,11 +123,11 @@ func (h *maxHeap) siftDown(i int) {
if r < h.size() && h.data[r].(int) > h.data[max].(int) { if r < h.size() && h.data[r].(int) > h.data[max].(int) {
max = r max = r
} }
// 若点 i 最大或索引 l, r 越界,则无需继续堆化,跳出 // 若点 i 最大或索引 l, r 越界,则无需继续堆化,跳出
if max == i { if max == i {
break break
} }
// 交换两 // 交换两
h.swap(i, max) h.swap(i, max)
// 循环向下堆化 // 循环向下堆化
i = max i = max

View File

@ -19,7 +19,7 @@ func hashingSearchArray(m map[int]int, target int) int {
/* 哈希查找(链表) */ /* 哈希查找(链表) */
func hashingSearchLinkedList(m map[int]*ListNode, target int) *ListNode { func hashingSearchLinkedList(m map[int]*ListNode, target int) *ListNode {
// 哈希表的 key: 目标结点值value: 结点对象 // 哈希表的 key: 目标节点值value: 节点对象
// 若哈希表中无此 key ,返回 nil // 若哈希表中无此 key ,返回 nil
if node, ok := m[target]; ok { if node, ok := m[target]; ok {
return node return node

View File

@ -32,5 +32,5 @@ func TestHashingSearch(t *testing.T) {
head = head.Next head = head.Next
} }
node := hashingSearchLinkedList(m1, target) node := hashingSearchLinkedList(m1, target)
fmt.Println("目标结点值 3 的对应结点对象为 ", node) fmt.Println("目标节点值 3 的对应节点对象为 ", node)
} }

View File

@ -25,7 +25,7 @@ func linearSearchArray(nums []int, target int) int {
func linearSearchLinkedList(node *ListNode, target int) *ListNode { func linearSearchLinkedList(node *ListNode, target int) *ListNode {
// 遍历链表 // 遍历链表
for node != nil { for node != nil {
// 找到目标点,返回之 // 找到目标点,返回之
if node.Val == target { if node.Val == target {
return node return node
} }

View File

@ -22,5 +22,5 @@ func TestLinearSearch(t *testing.T) {
// 在链表中执行线性查找 // 在链表中执行线性查找
head := ArrayToLinkedList(nums) head := ArrayToLinkedList(nums)
node := linearSearchLinkedList(head, target) node := linearSearchLinkedList(head, target)
fmt.Println("目标结点值 3 的对应结点对象为", node) fmt.Println("目标节点值 3 的对应节点对象为", node)
} }

View File

@ -8,7 +8,7 @@ import . "github.com/krahets/hello-algo/pkg"
/* AVL 树 */ /* AVL 树 */
type aVLTree struct { type aVLTree struct {
// 根 // 根
root *TreeNode root *TreeNode
} }
@ -16,20 +16,20 @@ func newAVLTree() *aVLTree {
return &aVLTree{root: nil} return &aVLTree{root: nil}
} }
/* 获取点高度 */ /* 获取点高度 */
func (t *aVLTree) height(node *TreeNode) int { func (t *aVLTree) height(node *TreeNode) int {
// 空结点高度为 -1 ,叶结点高度为 0 // 空节点高度为 -1 ,叶节点高度为 0
if node != nil { if node != nil {
return node.Height return node.Height
} }
return -1 return -1
} }
/* 更新点高度 */ /* 更新点高度 */
func (t *aVLTree) updateHeight(node *TreeNode) { func (t *aVLTree) updateHeight(node *TreeNode) {
lh := t.height(node.Left) lh := t.height(node.Left)
rh := t.height(node.Right) rh := t.height(node.Right)
// 点高度等于最高子树高度 + 1 // 点高度等于最高子树高度 + 1
if lh > rh { if lh > rh {
node.Height = lh + 1 node.Height = lh + 1
} else { } else {
@ -39,11 +39,11 @@ func (t *aVLTree) updateHeight(node *TreeNode) {
/* 获取平衡因子 */ /* 获取平衡因子 */
func (t *aVLTree) balanceFactor(node *TreeNode) int { func (t *aVLTree) balanceFactor(node *TreeNode) int {
// 空点平衡因子为 0 // 空点平衡因子为 0
if node == nil { if node == nil {
return 0 return 0
} }
// 点平衡因子 = 左子树高度 - 右子树高度 // 点平衡因子 = 左子树高度 - 右子树高度
return t.height(node.Left) - t.height(node.Right) return t.height(node.Left) - t.height(node.Right)
} }
@ -54,10 +54,10 @@ func (t *aVLTree) rightRotate(node *TreeNode) *TreeNode {
// 以 child 为原点,将 node 向右旋转 // 以 child 为原点,将 node 向右旋转
child.Right = node child.Right = node
node.Left = grandChild node.Left = grandChild
// 更新点高度 // 更新点高度
t.updateHeight(node) t.updateHeight(node)
t.updateHeight(child) t.updateHeight(child)
// 返回旋转后子树的根 // 返回旋转后子树的根
return child return child
} }
@ -68,16 +68,16 @@ func (t *aVLTree) leftRotate(node *TreeNode) *TreeNode {
// 以 child 为原点,将 node 向左旋转 // 以 child 为原点,将 node 向左旋转
child.Left = node child.Left = node
node.Right = grandChild node.Right = grandChild
// 更新点高度 // 更新点高度
t.updateHeight(node) t.updateHeight(node)
t.updateHeight(child) t.updateHeight(child)
// 返回旋转后子树的根 // 返回旋转后子树的根
return child return child
} }
/* 执行旋转操作,使该子树重新恢复平衡 */ /* 执行旋转操作,使该子树重新恢复平衡 */
func (t *aVLTree) rotate(node *TreeNode) *TreeNode { func (t *aVLTree) rotate(node *TreeNode) *TreeNode {
// 获取点 node 的平衡因子 // 获取点 node 的平衡因子
// Go 推荐短变量,这里 bf 指代 t.balanceFactor // Go 推荐短变量,这里 bf 指代 t.balanceFactor
bf := t.balanceFactor(node) bf := t.balanceFactor(node)
// 左偏树 // 左偏树
@ -106,46 +106,46 @@ func (t *aVLTree) rotate(node *TreeNode) *TreeNode {
return node return node
} }
/* 插入点 */ /* 插入点 */
func (t *aVLTree) insert(val int) *TreeNode { func (t *aVLTree) insert(val int) *TreeNode {
t.root = t.insertHelper(t.root, val) t.root = t.insertHelper(t.root, val)
return t.root return t.root
} }
/* 递归插入点(辅助方法) */ /* 递归插入点(辅助方法) */
func (t *aVLTree) insertHelper(node *TreeNode, val int) *TreeNode { func (t *aVLTree) insertHelper(node *TreeNode, val int) *TreeNode {
if node == nil { if node == nil {
return NewTreeNode(val) return NewTreeNode(val)
} }
/* 1. 查找插入位置,并插入点 */ /* 1. 查找插入位置,并插入点 */
if val < node.Val { if val < node.Val {
node.Left = t.insertHelper(node.Left, val) node.Left = t.insertHelper(node.Left, val)
} else if val > node.Val { } else if val > node.Val {
node.Right = t.insertHelper(node.Right, val) node.Right = t.insertHelper(node.Right, val)
} else { } else {
// 重复点不插入,直接返回 // 重复点不插入,直接返回
return node return node
} }
// 更新点高度 // 更新点高度
t.updateHeight(node) t.updateHeight(node)
/* 2. 执行旋转操作,使该子树重新恢复平衡 */ /* 2. 执行旋转操作,使该子树重新恢复平衡 */
node = t.rotate(node) node = t.rotate(node)
// 返回子树的根 // 返回子树的根
return node return node
} }
/* 删除点 */ /* 删除点 */
func (t *aVLTree) remove(val int) *TreeNode { func (t *aVLTree) remove(val int) *TreeNode {
root := t.removeHelper(t.root, val) root := t.removeHelper(t.root, val)
return root return root
} }
/* 递归删除点(辅助方法) */ /* 递归删除点(辅助方法) */
func (t *aVLTree) removeHelper(node *TreeNode, val int) *TreeNode { func (t *aVLTree) removeHelper(node *TreeNode, val int) *TreeNode {
if node == nil { if node == nil {
return nil return nil
} }
/* 1. 查找点,并删除之 */ /* 1. 查找点,并删除之 */
if val < node.Val { if val < node.Val {
node.Left = t.removeHelper(node.Left, val) node.Left = t.removeHelper(node.Left, val)
} else if val > node.Val { } else if val > node.Val {
@ -156,56 +156,56 @@ func (t *aVLTree) removeHelper(node *TreeNode, val int) *TreeNode {
if node.Right != nil { if node.Right != nil {
child = node.Right child = node.Right
} }
// 子点数量 = 0 ,直接删除 node 并返回 // 子点数量 = 0 ,直接删除 node 并返回
if child == nil { if child == nil {
return nil return nil
} else { } else {
// 子点数量 = 1 ,直接删除 node // 子点数量 = 1 ,直接删除 node
node = child node = child
} }
} else { } else {
// 子结点数量 = 2 ,则将中序遍历的下个结点删除,并用该结点替换当前结 // 子节点数量 = 2 ,则将中序遍历的下个节点删除,并用该节点替换当前节
temp := t.getInOrderNext(node.Right) temp := t.getInOrderNext(node.Right)
node.Right = t.removeHelper(node.Right, temp.Val) node.Right = t.removeHelper(node.Right, temp.Val)
node.Val = temp.Val node.Val = temp.Val
} }
} }
// 更新点高度 // 更新点高度
t.updateHeight(node) t.updateHeight(node)
/* 2. 执行旋转操作,使该子树重新恢复平衡 */ /* 2. 执行旋转操作,使该子树重新恢复平衡 */
node = t.rotate(node) node = t.rotate(node)
// 返回子树的根 // 返回子树的根
return node return node
} }
/* 获取中序遍历中的下一个结点(仅适用于 root 有左子结点的情况) */ /* 获取中序遍历中的下一个节点(仅适用于 root 有左子节点的情况) */
func (t *aVLTree) getInOrderNext(node *TreeNode) *TreeNode { func (t *aVLTree) getInOrderNext(node *TreeNode) *TreeNode {
if node == nil { if node == nil {
return node return node
} }
// 循环访问左子结点,直到叶结点时为最小结点,跳出 // 循环访问左子节点,直到叶节点时为最小节点,跳出
for node.Left != nil { for node.Left != nil {
node = node.Left node = node.Left
} }
return node return node
} }
/* 查找点 */ /* 查找点 */
func (t *aVLTree) search(val int) *TreeNode { func (t *aVLTree) search(val int) *TreeNode {
cur := t.root cur := t.root
// 循环查找,越过叶点后跳出 // 循环查找,越过叶点后跳出
for cur != nil { for cur != nil {
if cur.Val < val { if cur.Val < val {
// 目标点在 cur 的右子树中 // 目标点在 cur 的右子树中
cur = cur.Right cur = cur.Right
} else if cur.Val > val { } else if cur.Val > val {
// 目标点在 cur 的左子树中 // 目标点在 cur 的左子树中
cur = cur.Left cur = cur.Left
} else { } else {
// 找到目标点,跳出循环 // 找到目标点,跳出循环
break break
} }
} }
// 返回目标 // 返回目标
return cur return cur
} }

View File

@ -14,8 +14,8 @@ import (
func TestAVLTree(t *testing.T) { func TestAVLTree(t *testing.T) {
/* 初始化空 AVL 树 */ /* 初始化空 AVL 树 */
tree := newAVLTree() tree := newAVLTree()
/* 插入点 */ /* 插入点 */
// 请关注插入点后AVL 树是如何保持平衡的 // 请关注插入点后AVL 树是如何保持平衡的
testInsert(tree, 1) testInsert(tree, 1)
testInsert(tree, 2) testInsert(tree, 2)
testInsert(tree, 3) testInsert(tree, 3)
@ -27,28 +27,28 @@ func TestAVLTree(t *testing.T) {
testInsert(tree, 10) testInsert(tree, 10)
testInsert(tree, 6) testInsert(tree, 6)
/* 插入重复点 */ /* 插入重复点 */
testInsert(tree, 7) testInsert(tree, 7)
/* 删除点 */ /* 删除点 */
// 请关注删除点后AVL 树是如何保持平衡的 // 请关注删除点后AVL 树是如何保持平衡的
testRemove(tree, 8) // 删除度为 0 的 testRemove(tree, 8) // 删除度为 0 的
testRemove(tree, 5) // 删除度为 1 的 testRemove(tree, 5) // 删除度为 1 的
testRemove(tree, 4) // 删除度为 2 的 testRemove(tree, 4) // 删除度为 2 的
/* 查询点 */ /* 查询点 */
node := tree.search(7) 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) { func testInsert(tree *aVLTree, val int) {
tree.insert(val) tree.insert(val)
fmt.Printf("\n插入点 %d 后AVL 树为 \n", val) fmt.Printf("\n插入点 %d 后AVL 树为 \n", val)
PrintTree(tree.root) PrintTree(tree.root)
} }
func testRemove(tree *aVLTree, val int) { func testRemove(tree *aVLTree, val int) {
tree.remove(val) tree.remove(val)
fmt.Printf("\n删除点 %d 后AVL 树为 \n", val) fmt.Printf("\n删除点 %d 后AVL 树为 \n", val)
PrintTree(tree.root) PrintTree(tree.root)
} }

View File

@ -28,7 +28,7 @@ func (bst *binarySearchTree) buildTree(nums []int, left, right int) *TreeNode {
if left > right { if left > right {
return nil return nil
} }
// 将数组中间结点作为根结 // 将数组中间节点作为根节
middle := left + (right-left)>>1 middle := left + (right-left)>>1
root := NewTreeNode(nums[middle]) root := NewTreeNode(nums[middle])
// 递归构建左子树和右子树 // 递归构建左子树和右子树
@ -37,53 +37,53 @@ func (bst *binarySearchTree) buildTree(nums []int, left, right int) *TreeNode {
return root return root
} }
/* 获取根点 */ /* 获取根点 */
func (bst *binarySearchTree) getRoot() *TreeNode { func (bst *binarySearchTree) getRoot() *TreeNode {
return bst.root return bst.root
} }
/* 获取中序遍历的下一个结点(仅适用于 root 有左子结点的情况) */ /* 获取中序遍历的下一个节点(仅适用于 root 有左子节点的情况) */
func (bst *binarySearchTree) getInOrderNext(node *TreeNode) *TreeNode { func (bst *binarySearchTree) getInOrderNext(node *TreeNode) *TreeNode {
if node == nil { if node == nil {
return node return node
} }
// 循环访问左子结点,直到叶结点时为最小结点,跳出 // 循环访问左子节点,直到叶节点时为最小节点,跳出
for node.Left != nil { for node.Left != nil {
node = node.Left node = node.Left
} }
return node return node
} }
/* 查找点 */ /* 查找点 */
func (bst *binarySearchTree) search(num int) *TreeNode { func (bst *binarySearchTree) search(num int) *TreeNode {
node := bst.root node := bst.root
// 循环查找,越过叶点后跳出 // 循环查找,越过叶点后跳出
for node != nil { for node != nil {
if node.Val < num { if node.Val < num {
// 目标点在 cur 的右子树中 // 目标点在 cur 的右子树中
node = node.Right node = node.Right
} else if node.Val > num { } else if node.Val > num {
// 目标点在 cur 的左子树中 // 目标点在 cur 的左子树中
node = node.Left node = node.Left
} else { } else {
// 找到目标点,跳出循环 // 找到目标点,跳出循环
break break
} }
} }
// 返回目标 // 返回目标
return node return node
} }
/* 插入点 */ /* 插入点 */
func (bst *binarySearchTree) insert(num int) *TreeNode { func (bst *binarySearchTree) insert(num int) *TreeNode {
cur := bst.root cur := bst.root
// 若树为空,直接提前返回 // 若树为空,直接提前返回
if cur == nil { if cur == nil {
return nil return nil
} }
// 待插入结点之前的结点位置 // 待插入节点之前的节点位置
var pre *TreeNode = nil var pre *TreeNode = nil
// 循环查找,越过叶点后跳出 // 循环查找,越过叶点后跳出
for cur != nil { for cur != nil {
if cur.Val == num { if cur.Val == num {
return nil return nil
@ -95,7 +95,7 @@ func (bst *binarySearchTree) insert(num int) *TreeNode {
cur = cur.Left cur = cur.Left
} }
} }
// 插入 // 插入
node := NewTreeNode(num) node := NewTreeNode(num)
if pre.Val < num { if pre.Val < num {
pre.Right = node pre.Right = node
@ -105,54 +105,54 @@ func (bst *binarySearchTree) insert(num int) *TreeNode {
return cur return cur
} }
/* 删除点 */ /* 删除点 */
func (bst *binarySearchTree) remove(num int) *TreeNode { func (bst *binarySearchTree) remove(num int) *TreeNode {
cur := bst.root cur := bst.root
// 若树为空,直接提前返回 // 若树为空,直接提前返回
if cur == nil { if cur == nil {
return nil return nil
} }
// 待删除结点之前的结点位置 // 待删除节点之前的节点位置
var pre *TreeNode = nil var pre *TreeNode = nil
// 循环查找,越过叶点后跳出 // 循环查找,越过叶点后跳出
for cur != nil { for cur != nil {
if cur.Val == num { if cur.Val == num {
break break
} }
pre = cur pre = cur
if cur.Val < num { if cur.Val < num {
// 待删除点在右子树中 // 待删除点在右子树中
cur = cur.Right cur = cur.Right
} else { } else {
// 待删除点在左子树中 // 待删除点在左子树中
cur = cur.Left cur = cur.Left
} }
} }
// 若无待删除点,则直接返回 // 若无待删除点,则直接返回
if cur == nil { if cur == nil {
return nil return nil
} }
// 子点数为 0 或 1 // 子点数为 0 或 1
if cur.Left == nil || cur.Right == nil { if cur.Left == nil || cur.Right == nil {
var child *TreeNode = nil var child *TreeNode = nil
// 取出待删除结点的子结 // 取出待删除节点的子节
if cur.Left != nil { if cur.Left != nil {
child = cur.Left child = cur.Left
} else { } else {
child = cur.Right child = cur.Right
} }
// 将子结点替换为待删除结 // 将子节点替换为待删除节
if pre.Left == cur { if pre.Left == cur {
pre.Left = child pre.Left = child
} else { } else {
pre.Right = child pre.Right = child
} }
// 子点数为 2 // 子点数为 2
} else { } else {
// 获取中序遍历中待删除结点 cur 的下一个结 // 获取中序遍历中待删除节点 cur 的下一个节
next := bst.getInOrderNext(cur) next := bst.getInOrderNext(cur)
temp := next.Val temp := next.Val
// 递归删除点 next // 递归删除点 next
bst.remove(next.Val) bst.remove(next.Val)
// 将 next 的值复制给 cur // 将 next 的值复制给 cur
cur.Val = temp cur.Val = temp

View File

@ -15,27 +15,27 @@ func TestBinarySearchTree(t *testing.T) {
fmt.Println("\n初始化的二叉树为:") fmt.Println("\n初始化的二叉树为:")
bst.print() bst.print()
// 获取根 // 获取根
node := bst.getRoot() node := bst.getRoot()
fmt.Println("\n二叉树的根点为:", node.Val) fmt.Println("\n二叉树的根点为:", node.Val)
// 查找 // 查找
node = bst.search(7) node = bst.search(7)
fmt.Println("查找到的结点对象为", node, ",结点值 =", node.Val) fmt.Println("查找到的节点对象为", node, ",节点值 =", node.Val)
// 插入 // 插入
node = bst.insert(16) node = bst.insert(16)
fmt.Println("\n插入点后 16 的二叉树为:") fmt.Println("\n插入点后 16 的二叉树为:")
bst.print() bst.print()
// 删除 // 删除
bst.remove(1) bst.remove(1)
fmt.Println("\n删除点 1 后的二叉树为:") fmt.Println("\n删除点 1 后的二叉树为:")
bst.print() bst.print()
bst.remove(2) bst.remove(2)
fmt.Println("\n删除点 2 后的二叉树为:") fmt.Println("\n删除点 2 后的二叉树为:")
bst.print() bst.print()
bst.remove(4) bst.remove(4)
fmt.Println("\n删除点 4 后的二叉树为:") fmt.Println("\n删除点 4 后的二叉树为:")
bst.print() bst.print()
} }

View File

@ -12,7 +12,7 @@ import (
/* 层序遍历 */ /* 层序遍历 */
func levelOrder(root *TreeNode) []int { func levelOrder(root *TreeNode) []int {
// 初始化队列,加入根 // 初始化队列,加入根
queue := list.New() queue := list.New()
queue.PushBack(root) queue.PushBack(root)
// 初始化一个切片,用于保存遍历序列 // 初始化一个切片,用于保存遍历序列
@ -20,14 +20,14 @@ func levelOrder(root *TreeNode) []int {
for queue.Len() > 0 { for queue.Len() > 0 {
// 队列出队 // 队列出队
node := queue.Remove(queue.Front()).(*TreeNode) node := queue.Remove(queue.Front()).(*TreeNode)
// 保存点值 // 保存点值
nums = append(nums, node.Val) nums = append(nums, node.Val)
if node.Left != nil { if node.Left != nil {
// 左子点入队 // 左子点入队
queue.PushBack(node.Left) queue.PushBack(node.Left)
} }
if node.Right != nil { if node.Right != nil {
// 右子点入队 // 右子点入队
queue.PushBack(node.Right) queue.PushBack(node.Right)
} }
} }

View File

@ -20,5 +20,5 @@ func TestLevelOrder(t *testing.T) {
// 层序遍历 // 层序遍历
nums := levelOrder(root) nums := levelOrder(root)
fmt.Println("\n层序遍历的点打印序列 =", nums) fmt.Println("\n层序遍历的点打印序列 =", nums)
} }

View File

@ -15,7 +15,7 @@ func preOrder(node *TreeNode) {
if node == nil { if node == nil {
return return
} }
// 访问优先级:根点 -> 左子树 -> 右子树 // 访问优先级:根点 -> 左子树 -> 右子树
nums = append(nums, node.Val) nums = append(nums, node.Val)
preOrder(node.Left) preOrder(node.Left)
preOrder(node.Right) preOrder(node.Right)
@ -26,7 +26,7 @@ func inOrder(node *TreeNode) {
if node == nil { if node == nil {
return return
} }
// 访问优先级:左子树 -> 根点 -> 右子树 // 访问优先级:左子树 -> 根点 -> 右子树
inOrder(node.Left) inOrder(node.Left)
nums = append(nums, node.Val) nums = append(nums, node.Val)
inOrder(node.Right) inOrder(node.Right)
@ -37,7 +37,7 @@ func postOrder(node *TreeNode) {
if node == nil { if node == nil {
return return
} }
// 访问优先级:左子树 -> 右子树 -> 根 // 访问优先级:左子树 -> 右子树 -> 根
postOrder(node.Left) postOrder(node.Left)
postOrder(node.Right) postOrder(node.Right)
nums = append(nums, node.Val) nums = append(nums, node.Val)

View File

@ -21,15 +21,15 @@ func TestPreInPostOrderTraversal(t *testing.T) {
// 前序遍历 // 前序遍历
nums = nil nums = nil
preOrder(root) preOrder(root)
fmt.Println("\n前序遍历的点打印序列 =", nums) fmt.Println("\n前序遍历的点打印序列 =", nums)
// 中序遍历 // 中序遍历
nums = nil nums = nil
inOrder(root) inOrder(root)
fmt.Println("\n中序遍历的点打印序列 =", nums) fmt.Println("\n中序遍历的点打印序列 =", nums)
// 后序遍历 // 后序遍历
nums = nil nums = nil
postOrder(root) postOrder(root)
fmt.Println("\n后序遍历的点打印序列 =", nums) fmt.Println("\n后序遍历的点打印序列 =", nums)
} }

View File

@ -13,7 +13,7 @@ import (
func TestBinaryTree(t *testing.T) { func TestBinaryTree(t *testing.T) {
/* 初始化二叉树 */ /* 初始化二叉树 */
// 初始化 // 初始化
n1 := NewTreeNode(1) n1 := NewTreeNode(1)
n2 := NewTreeNode(2) n2 := NewTreeNode(2)
n3 := NewTreeNode(3) n3 := NewTreeNode(3)
@ -27,15 +27,15 @@ func TestBinaryTree(t *testing.T) {
fmt.Println("初始化二叉树") fmt.Println("初始化二叉树")
PrintTree(n1) PrintTree(n1)
/* 插入与删除点 */ /* 插入与删除点 */
// 插入 // 插入
p := NewTreeNode(0) p := NewTreeNode(0)
n1.Left = p n1.Left = p
p.Left = n2 p.Left = n2
fmt.Println("插入点 P 后") fmt.Println("插入点 P 后")
PrintTree(n1) PrintTree(n1)
// 删除 // 删除
n1.Left = n2 n1.Left = n2
fmt.Println("删除点 P 后") fmt.Println("删除点 P 后")
PrintTree(n1) PrintTree(n1)
} }

View File

@ -9,10 +9,10 @@ import (
) )
type TreeNode struct { type TreeNode struct {
Val int // 点值 Val int // 点值
Height int // 点高度 Height int // 点高度
Left *TreeNode // 左子点引用 Left *TreeNode // 左子点引用
Right *TreeNode // 右子点引用 Right *TreeNode // 右子点引用
} }
func NewTreeNode(v int) *TreeNode { func NewTreeNode(v int) *TreeNode {

View File

@ -9,14 +9,14 @@ package chapter_array_and_linkedlist;
import include.*; import include.*;
public class linked_list { public class linked_list {
/* 在链表的结点 n0 之后插入结点 P */ /* 在链表的节点 n0 之后插入节点 P */
static void insert(ListNode n0, ListNode P) { static void insert(ListNode n0, ListNode P) {
ListNode n1 = n0.next; ListNode n1 = n0.next;
P.next = n1; P.next = n1;
n0.next = P; n0.next = P;
} }
/* 删除链表的结点 n0 之后的首个结点 */ /* 删除链表的节点 n0 之后的首个节点 */
static void remove(ListNode n0) { static void remove(ListNode n0) {
if (n0.next == null) if (n0.next == null)
return; return;
@ -26,7 +26,7 @@ public class linked_list {
n0.next = n1; n0.next = n1;
} }
/* 访问链表中索引为 index 的点 */ /* 访问链表中索引为 index 的点 */
static ListNode access(ListNode head, int index) { static ListNode access(ListNode head, int index) {
for (int i = 0; i < index; i++) { for (int i = 0; i < index; i++) {
if (head == null) if (head == null)
@ -36,7 +36,7 @@ public class linked_list {
return head; return head;
} }
/* 在链表中查找值为 target 的首个点 */ /* 在链表中查找值为 target 的首个点 */
static int find(ListNode head, int target) { static int find(ListNode head, int target) {
int index = 0; int index = 0;
while (head != null) { while (head != null) {
@ -51,7 +51,7 @@ public class linked_list {
/* Driver Code */ /* Driver Code */
public static void main(String[] args) { public static void main(String[] args) {
/* 初始化链表 */ /* 初始化链表 */
// 初始化各个 // 初始化各个
ListNode n0 = new ListNode(1); ListNode n0 = new ListNode(1);
ListNode n1 = new ListNode(3); ListNode n1 = new ListNode(3);
ListNode n2 = new ListNode(2); ListNode n2 = new ListNode(2);
@ -65,22 +65,22 @@ public class linked_list {
System.out.println("初始化的链表为"); System.out.println("初始化的链表为");
PrintUtil.printLinkedList(n0); PrintUtil.printLinkedList(n0);
/* 插入点 */ /* 插入点 */
insert(n0, new ListNode(0)); insert(n0, new ListNode(0));
System.out.println("插入点后的链表为"); System.out.println("插入点后的链表为");
PrintUtil.printLinkedList(n0); PrintUtil.printLinkedList(n0);
/* 删除点 */ /* 删除点 */
remove(n0); remove(n0);
System.out.println("删除点后的链表为"); System.out.println("删除点后的链表为");
PrintUtil.printLinkedList(n0); PrintUtil.printLinkedList(n0);
/* 访问点 */ /* 访问点 */
ListNode node = access(n0, 3); ListNode node = access(n0, 3);
System.out.println("链表中索引 3 处的点的值 = " + node.val); System.out.println("链表中索引 3 处的点的值 = " + node.val);
/* 查找点 */ /* 查找点 */
int index = find(n0, 2); int index = find(n0, 2);
System.out.println("链表中值为 2 的点的索引 = " + index); System.out.println("链表中值为 2 的点的索引 = " + index);
} }
} }

View File

@ -18,23 +18,23 @@ class MaxHeap {
public MaxHeap(List<Integer> nums) { public MaxHeap(List<Integer> nums) {
// 将列表元素原封不动添加进堆 // 将列表元素原封不动添加进堆
maxHeap = new ArrayList<>(nums); maxHeap = new ArrayList<>(nums);
// 堆化除叶结点以外的其他所有结 // 堆化除叶节点以外的其他所有节
for (int i = parent(size() - 1); i >= 0; i--) { for (int i = parent(size() - 1); i >= 0; i--) {
siftDown(i); siftDown(i);
} }
} }
/* 获取左子点索引 */ /* 获取左子点索引 */
private int left(int i) { private int left(int i) {
return 2 * i + 1; return 2 * i + 1;
} }
/* 获取右子点索引 */ /* 获取右子点索引 */
private int right(int i) { private int right(int i) {
return 2 * i + 2; return 2 * i + 2;
} }
/* 获取父点索引 */ /* 获取父点索引 */
private int parent(int i) { private int parent(int i) {
return (i - 1) / 2; // 向下整除 return (i - 1) / 2; // 向下整除
} }
@ -65,21 +65,21 @@ class MaxHeap {
/* 元素入堆 */ /* 元素入堆 */
public void push(int val) { public void push(int val) {
// 添加 // 添加
maxHeap.add(val); maxHeap.add(val);
// 从底至顶堆化 // 从底至顶堆化
siftUp(size() - 1); siftUp(size() - 1);
} }
/* 从点 i 开始,从底至顶堆化 */ /* 从点 i 开始,从底至顶堆化 */
private void siftUp(int i) { private void siftUp(int i) {
while (true) { while (true) {
// 获取结点 i 的父结 // 获取节点 i 的父节
int p = parent(i); int p = parent(i);
// 越过根结点点无需修复结束堆化 // 越过根节点点无需修复结束堆化
if (p < 0 || maxHeap.get(i) <= maxHeap.get(p)) if (p < 0 || maxHeap.get(i) <= maxHeap.get(p))
break; break;
// 交换两 // 交换两
swap(i, p); swap(i, p);
// 循环向上堆化 // 循环向上堆化
i = p; i = p;
@ -91,9 +91,9 @@ class MaxHeap {
// 判空处理 // 判空处理
if (isEmpty()) if (isEmpty())
throw new EmptyStackException(); throw new EmptyStackException();
// 交换根结点与最右叶结即交换首元素与尾元素 // 交换根节点与最右叶节即交换首元素与尾元素
swap(0, size() - 1); swap(0, size() - 1);
// 删除 // 删除
int val = maxHeap.remove(size() - 1); int val = maxHeap.remove(size() - 1);
// 从顶至底堆化 // 从顶至底堆化
siftDown(0); siftDown(0);
@ -101,18 +101,18 @@ class MaxHeap {
return val; return val;
} }
/* 从点 i 开始,从顶至底堆化 */ /* 从点 i 开始,从顶至底堆化 */
private void siftDown(int i) { private void siftDown(int i) {
while (true) { while (true) {
// 判断 i, l, r 中值最大的记为 ma // 判断 i, l, r 中值最大的记为 ma
int l = left(i), r = right(i), ma = i; int l = left(i), r = right(i), ma = i;
if (l < size() && maxHeap.get(l) > maxHeap.get(ma)) if (l < size() && maxHeap.get(l) > maxHeap.get(ma))
ma = l; ma = l;
if (r < size() && maxHeap.get(r) > maxHeap.get(ma)) if (r < size() && maxHeap.get(r) > maxHeap.get(ma))
ma = r; ma = r;
// i 最大或索引 l, r 越界则无需继续堆化跳出 // i 最大或索引 l, r 越界则无需继续堆化跳出
if (ma == i) break; if (ma == i) break;
// 交换两 // 交换两
swap(i, ma); swap(i, ma);
// 循环向下堆化 // 循环向下堆化
i = ma; i = ma;

View File

@ -19,7 +19,7 @@ public class hashing_search {
/* 哈希查找(链表) */ /* 哈希查找(链表) */
static ListNode hashingSearchLinkedList(Map<Integer, ListNode> map, int target) { static ListNode hashingSearchLinkedList(Map<Integer, ListNode> map, int target) {
// 哈希表的 key: 目标结点值value: 点对象 // 哈希表的 key: 目标节点值value: 点对象
// 若哈希表中无此 key 返回 null // 若哈希表中无此 key 返回 null
return map.getOrDefault(target, null); return map.getOrDefault(target, null);
} }
@ -42,10 +42,10 @@ public class hashing_search {
// 初始化哈希表 // 初始化哈希表
Map<Integer, ListNode> map1 = new HashMap<>(); Map<Integer, ListNode> map1 = new HashMap<>();
while (head != null) { while (head != null) {
map1.put(head.val, head); // key: 结点值value: map1.put(head.val, head); // key: 节点值value:
head = head.next; head = head.next;
} }
ListNode node = hashingSearchLinkedList(map1, target); ListNode node = hashingSearchLinkedList(map1, target);
System.out.println("目标结点值 3 的对应结点对象为 " + node); System.out.println("目标节点值 3 的对应节点对象为 " + node);
} }
} }

View File

@ -25,12 +25,12 @@ public class linear_search {
static ListNode linearSearchLinkedList(ListNode head, int target) { static ListNode linearSearchLinkedList(ListNode head, int target) {
// 遍历链表 // 遍历链表
while (head != null) { while (head != null) {
// 找到目标返回之 // 找到目标返回之
if (head.val == target) if (head.val == target)
return head; return head;
head = head.next; head = head.next;
} }
// 未找到目标返回 null // 未找到目标返回 null
return null; return null;
} }
@ -45,6 +45,6 @@ public class linear_search {
/* 在链表中执行线性查找 */ /* 在链表中执行线性查找 */
ListNode head = ListNode.arrToLinkedList(nums); ListNode head = ListNode.arrToLinkedList(nums);
ListNode node = linearSearchLinkedList(head, target); ListNode node = linearSearchLinkedList(head, target);
System.out.println("目标结点值 3 的对应结点对象为 " + node); System.out.println("目标节点值 3 的对应节点对象为 " + node);
} }
} }

View File

@ -8,11 +8,11 @@ package chapter_stack_and_queue;
import java.util.*; import java.util.*;
/* 双向链表点 */ /* 双向链表点 */
class ListNode { class ListNode {
int val; // 点值 int val; // 点值
ListNode next; // 后继点引用指针 ListNode next; // 后继点引用指针
ListNode prev; // 前驱点引用指针 ListNode prev; // 前驱点引用指针
ListNode(int val) { ListNode(int val) {
this.val = val; this.val = val;
prev = next = null; prev = next = null;
@ -21,7 +21,7 @@ class ListNode {
/* 基于双向链表实现的双向队列 */ /* 基于双向链表实现的双向队列 */
class LinkedListDeque { class LinkedListDeque {
private ListNode front, rear; // 结点 front 尾结 rear private ListNode front, rear; // 节点 front 尾节 rear
private int queSize = 0; // 双向队列的长度 private int queSize = 0; // 双向队列的长度
public LinkedListDeque() { public LinkedListDeque() {
@ -49,13 +49,13 @@ class LinkedListDeque {
// node 添加至链表头部 // node 添加至链表头部
front.prev = node; front.prev = node;
node.next = front; node.next = front;
front = node; // 更新头 front = node; // 更新头
// 队尾入队操作 // 队尾入队操作
} else { } else {
// node 添加至链表尾部 // node 添加至链表尾部
rear.next = node; rear.next = node;
node.prev = rear; node.prev = rear;
rear = node; // 更新尾 rear = node; // 更新尾
} }
queSize++; // 更新队列长度 queSize++; // 更新队列长度
} }
@ -78,24 +78,24 @@ class LinkedListDeque {
int val; int val;
// 队首出队操作 // 队首出队操作
if (isFront) { if (isFront) {
val = front.val; // 暂存头点值 val = front.val; // 暂存头点值
// 删除头 // 删除头
ListNode fNext = front.next; ListNode fNext = front.next;
if (fNext != null) { if (fNext != null) {
fNext.prev = null; fNext.prev = null;
front.next = null; front.next = null;
} }
front = fNext; // 更新头 front = fNext; // 更新头
// 队尾出队操作 // 队尾出队操作
} else { } else {
val = rear.val; // 暂存尾点值 val = rear.val; // 暂存尾点值
// 删除尾 // 删除尾
ListNode rPrev = rear.prev; ListNode rPrev = rear.prev;
if (rPrev != null) { if (rPrev != null) {
rPrev.next = null; rPrev.next = null;
rear.prev = null; rear.prev = null;
} }
rear = rPrev; // 更新尾 rear = rPrev; // 更新尾
} }
queSize--; // 更新队列长度 queSize--; // 更新队列长度
return val; return val;

View File

@ -10,7 +10,7 @@ import java.util.*;
/* 基于链表实现的队列 */ /* 基于链表实现的队列 */
class LinkedListQueue { class LinkedListQueue {
private ListNode front, rear; // 结点 front 尾结 rear private ListNode front, rear; // 节点 front 尾节 rear
private int queSize = 0; private int queSize = 0;
public LinkedListQueue() { public LinkedListQueue() {
@ -30,13 +30,13 @@ class LinkedListQueue {
/* 入队 */ /* 入队 */
public void push(int num) { public void push(int num) {
// 点后添加 num // 点后添加 num
ListNode node = new ListNode(num); ListNode node = new ListNode(num);
// 如果队列为空则令头结点都指向该结 // 如果队列为空则令头节点都指向该节
if (front == null) { if (front == null) {
front = node; front = node;
rear = node; rear = node;
// 如果队列不为空则将该结点添加到尾结点后 // 如果队列不为空则将该节点添加到尾节点后
} else { } else {
rear.next = node; rear.next = node;
rear = node; rear = node;
@ -47,7 +47,7 @@ class LinkedListQueue {
/* 出队 */ /* 出队 */
public int pop() { public int pop() {
int num = peek(); int num = peek();
// 删除头 // 删除头
front = front.next; front = front.next;
queSize--; queSize--;
return num; return num;

View File

@ -11,7 +11,7 @@ import include.*;
/* 基于链表实现的栈 */ /* 基于链表实现的栈 */
class LinkedListStack { class LinkedListStack {
private ListNode stackPeek; // 将头点作为栈顶 private ListNode stackPeek; // 将头点作为栈顶
private int stkSize = 0; // 栈的长度 private int stkSize = 0; // 栈的长度
public LinkedListStack() { public LinkedListStack() {

View File

@ -10,25 +10,25 @@ import include.*;
/* AVL 树 */ /* AVL 树 */
class AVLTree { class AVLTree {
TreeNode root; // TreeNode root; //
/* 获取点高度 */ /* 获取点高度 */
public int height(TreeNode node) { public int height(TreeNode node) {
// 结点高度为 -1 叶结点高度为 0 // 节点高度为 -1 叶节点高度为 0
return node == null ? -1 : node.height; return node == null ? -1 : node.height;
} }
/* 更新点高度 */ /* 更新点高度 */
private void updateHeight(TreeNode node) { private void updateHeight(TreeNode node) {
// 点高度等于最高子树高度 + 1 // 点高度等于最高子树高度 + 1
node.height = Math.max(height(node.left), height(node.right)) + 1; node.height = Math.max(height(node.left), height(node.right)) + 1;
} }
/* 获取平衡因子 */ /* 获取平衡因子 */
public int balanceFactor(TreeNode node) { public int balanceFactor(TreeNode node) {
// 点平衡因子为 0 // 点平衡因子为 0
if (node == null) return 0; if (node == null) return 0;
// 点平衡因子 = 左子树高度 - 右子树高度 // 点平衡因子 = 左子树高度 - 右子树高度
return height(node.left) - height(node.right); return height(node.left) - height(node.right);
} }
@ -39,10 +39,10 @@ class AVLTree {
// child 为原点 node 向右旋转 // child 为原点 node 向右旋转
child.right = node; child.right = node;
node.left = grandChild; node.left = grandChild;
// 更新点高度 // 更新点高度
updateHeight(node); updateHeight(node);
updateHeight(child); updateHeight(child);
// 返回旋转后子树的根 // 返回旋转后子树的根
return child; return child;
} }
@ -53,16 +53,16 @@ class AVLTree {
// child 为原点 node 向左旋转 // child 为原点 node 向左旋转
child.left = node; child.left = node;
node.right = grandChild; node.right = grandChild;
// 更新点高度 // 更新点高度
updateHeight(node); updateHeight(node);
updateHeight(child); updateHeight(child);
// 返回旋转后子树的根 // 返回旋转后子树的根
return child; return child;
} }
/* 执行旋转操作,使该子树重新恢复平衡 */ /* 执行旋转操作,使该子树重新恢复平衡 */
private TreeNode rotate(TreeNode node) { private TreeNode rotate(TreeNode node) {
// 获取 node 的平衡因子 // 获取 node 的平衡因子
int balanceFactor = balanceFactor(node); int balanceFactor = balanceFactor(node);
// 左偏树 // 左偏树
if (balanceFactor > 1) { if (balanceFactor > 1) {
@ -90,39 +90,39 @@ class AVLTree {
return node; return node;
} }
/* 插入点 */ /* 插入点 */
public TreeNode insert(int val) { public TreeNode insert(int val) {
root = insertHelper(root, val); root = insertHelper(root, val);
return root; return root;
} }
/* 递归插入点(辅助方法) */ /* 递归插入点(辅助方法) */
private TreeNode insertHelper(TreeNode node, int val) { private TreeNode insertHelper(TreeNode node, int val) {
if (node == null) return new TreeNode(val); if (node == null) return new TreeNode(val);
/* 1. 查找插入位置,并插入点 */ /* 1. 查找插入位置,并插入点 */
if (val < node.val) if (val < node.val)
node.left = insertHelper(node.left, val); node.left = insertHelper(node.left, val);
else if (val > node.val) else if (val > node.val)
node.right = insertHelper(node.right, val); node.right = insertHelper(node.right, val);
else else
return node; // 重复点不插入直接返回 return node; // 重复点不插入直接返回
updateHeight(node); // 更新点高度 updateHeight(node); // 更新点高度
/* 2. 执行旋转操作,使该子树重新恢复平衡 */ /* 2. 执行旋转操作,使该子树重新恢复平衡 */
node = rotate(node); node = rotate(node);
// 返回子树的根 // 返回子树的根
return node; return node;
} }
/* 删除点 */ /* 删除点 */
public TreeNode remove(int val) { public TreeNode remove(int val) {
root = removeHelper(root, val); root = removeHelper(root, val);
return root; return root;
} }
/* 递归删除点(辅助方法) */ /* 递归删除点(辅助方法) */
private TreeNode removeHelper(TreeNode node, int val) { private TreeNode removeHelper(TreeNode node, int val) {
if (node == null) return null; if (node == null) return null;
/* 1. 查找点,并删除之 */ /* 1. 查找点,并删除之 */
if (val < node.val) if (val < node.val)
node.left = removeHelper(node.left, val); node.left = removeHelper(node.left, val);
else if (val > node.val) else if (val > node.val)
@ -130,52 +130,52 @@ class AVLTree {
else { else {
if (node.left == null || node.right == null) { if (node.left == null || node.right == null) {
TreeNode child = node.left != null ? node.left : node.right; TreeNode child = node.left != null ? node.left : node.right;
// 点数量 = 0 直接删除 node 并返回 // 点数量 = 0 直接删除 node 并返回
if (child == null) if (child == null)
return null; return null;
// 点数量 = 1 直接删除 node // 点数量 = 1 直接删除 node
else else
node = child; node = child;
} else { } else {
// 点数量 = 2 则将中序遍历的下个结点删除并用该结点替换当前结 // 点数量 = 2 则将中序遍历的下个节点删除并用该节点替换当前节
TreeNode temp = getInOrderNext(node.right); TreeNode temp = getInOrderNext(node.right);
node.right = removeHelper(node.right, temp.val); node.right = removeHelper(node.right, temp.val);
node.val = temp.val; node.val = temp.val;
} }
} }
updateHeight(node); // 更新点高度 updateHeight(node); // 更新点高度
/* 2. 执行旋转操作,使该子树重新恢复平衡 */ /* 2. 执行旋转操作,使该子树重新恢复平衡 */
node = rotate(node); node = rotate(node);
// 返回子树的根 // 返回子树的根
return node; return node;
} }
/* 获取中序遍历中的下一个结点(仅适用于 root 有左子结点的情况) */ /* 获取中序遍历中的下一个节点(仅适用于 root 有左子节点的情况) */
private TreeNode getInOrderNext(TreeNode node) { private TreeNode getInOrderNext(TreeNode node) {
if (node == null) return node; if (node == null) return node;
// 循环访问左子结点直到叶结点时为最小结跳出 // 循环访问左子节点直到叶节点时为最小节跳出
while (node.left != null) { while (node.left != null) {
node = node.left; node = node.left;
} }
return node; return node;
} }
/* 查找点 */ /* 查找点 */
public TreeNode search(int val) { public TreeNode search(int val) {
TreeNode cur = root; TreeNode cur = root;
// 循环查找越过叶点后跳出 // 循环查找越过叶点后跳出
while (cur != null) { while (cur != null) {
// 目标点在 cur 的右子树中 // 目标点在 cur 的右子树中
if (cur.val < val) if (cur.val < val)
cur = cur.right; cur = cur.right;
// 目标点在 cur 的左子树中 // 目标点在 cur 的左子树中
else if (cur.val > val) else if (cur.val > val)
cur = cur.left; cur = cur.left;
// 找到目标跳出循环 // 找到目标跳出循环
else else
break; break;
} }
// 返回目标 // 返回目标
return cur; return cur;
} }
} }
@ -183,13 +183,13 @@ class AVLTree {
public class avl_tree { public class avl_tree {
static void testInsert(AVLTree tree, int val) { static void testInsert(AVLTree tree, int val) {
tree.insert(val); tree.insert(val);
System.out.println("\n插入" + val + "AVL 树为"); System.out.println("\n插入" + val + "AVL 树为");
PrintUtil.printTree(tree.root); PrintUtil.printTree(tree.root);
} }
static void testRemove(AVLTree tree, int val) { static void testRemove(AVLTree tree, int val) {
tree.remove(val); tree.remove(val);
System.out.println("\n删除" + val + "AVL 树为"); System.out.println("\n删除" + val + "AVL 树为");
PrintUtil.printTree(tree.root); PrintUtil.printTree(tree.root);
} }
@ -197,8 +197,8 @@ public class avl_tree {
/* 初始化空 AVL 树 */ /* 初始化空 AVL 树 */
AVLTree avlTree = new AVLTree(); AVLTree avlTree = new AVLTree();
/* 插入点 */ /* 插入点 */
// 请关注插入点后AVL 树是如何保持平衡的 // 请关注插入点后AVL 树是如何保持平衡的
testInsert(avlTree, 1); testInsert(avlTree, 1);
testInsert(avlTree, 2); testInsert(avlTree, 2);
testInsert(avlTree, 3); testInsert(avlTree, 3);
@ -210,17 +210,17 @@ public class avl_tree {
testInsert(avlTree, 10); testInsert(avlTree, 10);
testInsert(avlTree, 6); testInsert(avlTree, 6);
/* 插入重复点 */ /* 插入重复点 */
testInsert(avlTree, 7); testInsert(avlTree, 7);
/* 删除点 */ /* 删除点 */
// 请关注删除点后AVL 树是如何保持平衡的 // 请关注删除点后AVL 树是如何保持平衡的
testRemove(avlTree, 8); // 删除度为 0 testRemove(avlTree, 8); // 删除度为 0
testRemove(avlTree, 5); // 删除度为 1 testRemove(avlTree, 5); // 删除度为 1
testRemove(avlTree, 4); // 删除度为 2 testRemove(avlTree, 4); // 删除度为 2
/* 查询点 */ /* 查询点 */
TreeNode node = avlTree.search(7); TreeNode node = avlTree.search(7);
System.out.println("\n查找到的点对象为 " + node + "点值 = " + node.val); System.out.println("\n查找到的点对象为 " + node + "点值 = " + node.val);
} }
} }

View File

@ -18,7 +18,7 @@ class BinarySearchTree {
root = buildTree(nums, 0, nums.length - 1); // 构建二叉搜索树 root = buildTree(nums, 0, nums.length - 1); // 构建二叉搜索树
} }
/* 获取二叉树根点 */ /* 获取二叉树根点 */
public TreeNode getRoot() { public TreeNode getRoot() {
return root; return root;
} }
@ -26,7 +26,7 @@ class BinarySearchTree {
/* 构建二叉搜索树 */ /* 构建二叉搜索树 */
public TreeNode buildTree(int[] nums, int i, int j) { public TreeNode buildTree(int[] nums, int i, int j) {
if (i > j) return null; if (i > j) return null;
// 将数组中间结点作为根结 // 将数组中间节点作为根节
int mid = (i + j) / 2; int mid = (i + j) / 2;
TreeNode root = new TreeNode(nums[mid]); TreeNode root = new TreeNode(nums[mid]);
// 递归建立左子树和右子树 // 递归建立左子树和右子树
@ -35,30 +35,30 @@ class BinarySearchTree {
return root; return root;
} }
/* 查找点 */ /* 查找点 */
public TreeNode search(int num) { public TreeNode search(int num) {
TreeNode cur = root; TreeNode cur = root;
// 循环查找越过叶点后跳出 // 循环查找越过叶点后跳出
while (cur != null) { while (cur != null) {
// 目标点在 cur 的右子树中 // 目标点在 cur 的右子树中
if (cur.val < num) cur = cur.right; if (cur.val < num) cur = cur.right;
// 目标点在 cur 的左子树中 // 目标点在 cur 的左子树中
else if (cur.val > num) cur = cur.left; else if (cur.val > num) cur = cur.left;
// 找到目标跳出循环 // 找到目标跳出循环
else break; else break;
} }
// 返回目标 // 返回目标
return cur; return cur;
} }
/* 插入点 */ /* 插入点 */
public TreeNode insert(int num) { public TreeNode insert(int num) {
// 若树为空直接提前返回 // 若树为空直接提前返回
if (root == null) return null; if (root == null) return null;
TreeNode cur = root, pre = null; TreeNode cur = root, pre = null;
// 循环查找越过叶点后跳出 // 循环查找越过叶点后跳出
while (cur != null) { while (cur != null) {
// 找到重复直接返回 // 找到重复直接返回
if (cur.val == num) return null; if (cur.val == num) return null;
pre = cur; pre = cur;
// 插入位置在 cur 的右子树中 // 插入位置在 cur 的右子树中
@ -66,44 +66,44 @@ class BinarySearchTree {
// 插入位置在 cur 的左子树中 // 插入位置在 cur 的左子树中
else cur = cur.left; else cur = cur.left;
} }
// 插入 val // 插入 val
TreeNode node = new TreeNode(num); TreeNode node = new TreeNode(num);
if (pre.val < num) pre.right = node; if (pre.val < num) pre.right = node;
else pre.left = node; else pre.left = node;
return node; return node;
} }
/* 删除点 */ /* 删除点 */
public TreeNode remove(int num) { public TreeNode remove(int num) {
// 若树为空直接提前返回 // 若树为空直接提前返回
if (root == null) return null; if (root == null) return null;
TreeNode cur = root, pre = null; TreeNode cur = root, pre = null;
// 循环查找越过叶点后跳出 // 循环查找越过叶点后跳出
while (cur != null) { while (cur != null) {
// 找到待删除跳出循环 // 找到待删除跳出循环
if (cur.val == num) break; if (cur.val == num) break;
pre = cur; pre = cur;
// 待删除点在 cur 的右子树中 // 待删除点在 cur 的右子树中
if (cur.val < num) cur = cur.right; if (cur.val < num) cur = cur.right;
// 待删除点在 cur 的左子树中 // 待删除点在 cur 的左子树中
else cur = cur.left; else cur = cur.left;
} }
// 若无待删除则直接返回 // 若无待删除则直接返回
if (cur == null) return null; if (cur == null) return null;
// 点数量 = 0 or 1 // 点数量 = 0 or 1
if (cur.left == null || cur.right == null) { if (cur.left == null || cur.right == null) {
// 当子点数量 = 0 / 1 child = null / 该子 // 当子点数量 = 0 / 1 child = null / 该子
TreeNode child = cur.left != null ? cur.left : cur.right; TreeNode child = cur.left != null ? cur.left : cur.right;
// 删除 cur // 删除 cur
if (pre.left == cur) pre.left = child; if (pre.left == cur) pre.left = child;
else pre.right = child; else pre.right = child;
} }
// 点数量 = 2 // 点数量 = 2
else { else {
// 获取中序遍历中 cur 的下一个 // 获取中序遍历中 cur 的下一个
TreeNode nex = getInOrderNext(cur.right); TreeNode nex = getInOrderNext(cur.right);
int tmp = nex.val; int tmp = nex.val;
// 递归删除 nex // 递归删除 nex
remove(nex.val); remove(nex.val);
// nex 的值复制给 cur // nex 的值复制给 cur
cur.val = tmp; cur.val = tmp;
@ -111,10 +111,10 @@ class BinarySearchTree {
return cur; return cur;
} }
/* 获取中序遍历中的下一个结点(仅适用于 root 有左子结点的情况) */ /* 获取中序遍历中的下一个节点(仅适用于 root 有左子节点的情况) */
public TreeNode getInOrderNext(TreeNode root) { public TreeNode getInOrderNext(TreeNode root) {
if (root == null) return root; if (root == null) return root;
// 循环访问左子结点直到叶结点时为最小结跳出 // 循环访问左子节点直到叶节点时为最小节跳出
while (root.left != null) { while (root.left != null) {
root = root.left; root = root.left;
} }
@ -130,24 +130,24 @@ public class binary_search_tree {
System.out.println("\n初始化的二叉树为\n"); System.out.println("\n初始化的二叉树为\n");
PrintUtil.printTree(bst.getRoot()); PrintUtil.printTree(bst.getRoot());
/* 查找点 */ /* 查找点 */
TreeNode node = bst.search(7); TreeNode node = bst.search(7);
System.out.println("\n查找到的点对象为 " + node + "点值 = " + node.val); System.out.println("\n查找到的点对象为 " + node + "点值 = " + node.val);
/* 插入点 */ /* 插入点 */
node = bst.insert(16); node = bst.insert(16);
System.out.println("\n插入点 16 后,二叉树为\n"); System.out.println("\n插入点 16 后,二叉树为\n");
PrintUtil.printTree(bst.getRoot()); PrintUtil.printTree(bst.getRoot());
/* 删除点 */ /* 删除点 */
bst.remove(1); bst.remove(1);
System.out.println("\n删除点 1 后,二叉树为\n"); System.out.println("\n删除点 1 后,二叉树为\n");
PrintUtil.printTree(bst.getRoot()); PrintUtil.printTree(bst.getRoot());
bst.remove(2); bst.remove(2);
System.out.println("\n删除点 2 后,二叉树为\n"); System.out.println("\n删除点 2 后,二叉树为\n");
PrintUtil.printTree(bst.getRoot()); PrintUtil.printTree(bst.getRoot());
bst.remove(4); bst.remove(4);
System.out.println("\n删除点 4 后,二叉树为\n"); System.out.println("\n删除点 4 后,二叉树为\n");
PrintUtil.printTree(bst.getRoot()); PrintUtil.printTree(bst.getRoot());
} }
} }

View File

@ -11,7 +11,7 @@ import include.*;
public class binary_tree { public class binary_tree {
public static void main(String[] args) { public static void main(String[] args) {
/* 初始化二叉树 */ /* 初始化二叉树 */
// 初始化 // 初始化
TreeNode n1 = new TreeNode(1); TreeNode n1 = new TreeNode(1);
TreeNode n2 = new TreeNode(2); TreeNode n2 = new TreeNode(2);
TreeNode n3 = new TreeNode(3); TreeNode n3 = new TreeNode(3);
@ -25,16 +25,16 @@ public class binary_tree {
System.out.println("\n初始化二叉树\n"); System.out.println("\n初始化二叉树\n");
PrintUtil.printTree(n1); PrintUtil.printTree(n1);
/* 插入与删除点 */ /* 插入与删除点 */
TreeNode P = new TreeNode(0); TreeNode P = new TreeNode(0);
// n1 -> n2 中间插入 P // n1 -> n2 中间插入 P
n1.left = P; n1.left = P;
P.left = n2; P.left = n2;
System.out.println("\n插入点 P 后\n"); System.out.println("\n插入点 P 后\n");
PrintUtil.printTree(n1); PrintUtil.printTree(n1);
// 删除 P // 删除 P
n1.left = n2; n1.left = n2;
System.out.println("\n删除点 P 后\n"); System.out.println("\n删除点 P 后\n");
PrintUtil.printTree(n1); PrintUtil.printTree(n1);
} }
} }

View File

@ -12,17 +12,17 @@ import java.util.*;
public class binary_tree_bfs { public class binary_tree_bfs {
/* 层序遍历 */ /* 层序遍历 */
static List<Integer> levelOrder(TreeNode root) { static List<Integer> levelOrder(TreeNode root) {
// 初始化队列加入根 // 初始化队列加入根
Queue<TreeNode> queue = new LinkedList<>() {{ add(root); }}; Queue<TreeNode> queue = new LinkedList<>() {{ add(root); }};
// 初始化一个列表用于保存遍历序列 // 初始化一个列表用于保存遍历序列
List<Integer> list = new ArrayList<>(); List<Integer> list = new ArrayList<>();
while (!queue.isEmpty()) { while (!queue.isEmpty()) {
TreeNode node = queue.poll(); // 队列出队 TreeNode node = queue.poll(); // 队列出队
list.add(node.val); // 保存点值 list.add(node.val); // 保存点值
if (node.left != null) if (node.left != null)
queue.offer(node.left); // 左子点入队 queue.offer(node.left); // 左子点入队
if (node.right != null) if (node.right != null)
queue.offer(node.right); // 右子点入队 queue.offer(node.right); // 右子点入队
} }
return list; return list;
} }
@ -36,6 +36,6 @@ public class binary_tree_bfs {
/* 层序遍历 */ /* 层序遍历 */
List<Integer> list = levelOrder(root); List<Integer> list = levelOrder(root);
System.out.println("\n层序遍历的点打印序列 = " + list); System.out.println("\n层序遍历的点打印序列 = " + list);
} }
} }

View File

@ -16,7 +16,7 @@ public class binary_tree_dfs {
/* 前序遍历 */ /* 前序遍历 */
static void preOrder(TreeNode root) { static void preOrder(TreeNode root) {
if (root == null) return; if (root == null) return;
// 访问优先级 -> 左子树 -> 右子树 // 访问优先级 -> 左子树 -> 右子树
list.add(root.val); list.add(root.val);
preOrder(root.left); preOrder(root.left);
preOrder(root.right); preOrder(root.right);
@ -25,7 +25,7 @@ public class binary_tree_dfs {
/* 中序遍历 */ /* 中序遍历 */
static void inOrder(TreeNode root) { static void inOrder(TreeNode root) {
if (root == null) return; if (root == null) return;
// 访问优先级左子树 -> -> 右子树 // 访问优先级左子树 -> -> 右子树
inOrder(root.left); inOrder(root.left);
list.add(root.val); list.add(root.val);
inOrder(root.right); inOrder(root.right);
@ -34,7 +34,7 @@ public class binary_tree_dfs {
/* 后序遍历 */ /* 后序遍历 */
static void postOrder(TreeNode root) { static void postOrder(TreeNode root) {
if (root == null) return; if (root == null) return;
// 访问优先级左子树 -> 右子树 -> // 访问优先级左子树 -> 右子树 ->
postOrder(root.left); postOrder(root.left);
postOrder(root.right); postOrder(root.right);
list.add(root.val); list.add(root.val);
@ -50,16 +50,16 @@ public class binary_tree_dfs {
/* 前序遍历 */ /* 前序遍历 */
list.clear(); list.clear();
preOrder(root); preOrder(root);
System.out.println("\n前序遍历的点打印序列 = " + list); System.out.println("\n前序遍历的点打印序列 = " + list);
/* 中序遍历 */ /* 中序遍历 */
list.clear(); list.clear();
inOrder(root); inOrder(root);
System.out.println("\n中序遍历的点打印序列 = " + list); System.out.println("\n中序遍历的点打印序列 = " + list);
/* 后序遍历 */ /* 后序遍历 */
list.clear(); list.clear();
postOrder(root); postOrder(root);
System.out.println("\n后序遍历的点打印序列 = " + list); System.out.println("\n后序遍历的点打印序列 = " + list);
} }
} }

View File

@ -12,10 +12,10 @@ import java.util.*;
* Definition for a binary tree node. * Definition for a binary tree node.
*/ */
public class TreeNode { public class TreeNode {
public int val; // 点值 public int val; // 点值
public int height; // 点高度 public int height; // 点高度
public TreeNode left; // 左子点引用 public TreeNode left; // 左子点引用
public TreeNode right; // 右子点引用 public TreeNode right; // 右子点引用
public TreeNode(int x) { public TreeNode(int x) {
val = x; val = x;

View File

@ -7,14 +7,14 @@
const { printLinkedList } = require("../modules/PrintUtil"); const { printLinkedList } = require("../modules/PrintUtil");
const { ListNode } = require("../modules/ListNode"); const { ListNode } = require("../modules/ListNode");
/* 在链表的结点 n0 之后插入结点 P */ /* 在链表的节点 n0 之后插入节点 P */
function insert(n0, P) { function insert(n0, P) {
const n1 = n0.next; const n1 = n0.next;
P.next = n1; P.next = n1;
n0.next = P; n0.next = P;
} }
/* 删除链表的结点 n0 之后的首个结点 */ /* 删除链表的节点 n0 之后的首个节点 */
function remove(n0) { function remove(n0) {
if (!n0.next) if (!n0.next)
return; return;
@ -24,7 +24,7 @@ function remove(n0) {
n0.next = n1; n0.next = n1;
} }
/* 访问链表中索引为 index 的点 */ /* 访问链表中索引为 index 的点 */
function access(head, index) { function access(head, index) {
for (let i = 0; i < index; i++) { for (let i = 0; i < index; i++) {
if (!head) { if (!head) {
@ -35,7 +35,7 @@ function access(head, index) {
return head; return head;
} }
/* 在链表中查找值为 target 的首个点 */ /* 在链表中查找值为 target 的首个点 */
function find(head, target) { function find(head, target) {
let index = 0; let index = 0;
while (head !== null) { while (head !== null) {
@ -50,7 +50,7 @@ function find(head, target) {
/* Driver Code */ /* Driver Code */
/* 初始化链表 */ /* 初始化链表 */
// 初始化各个 // 初始化各个
const n0 = new ListNode(1); const n0 = new ListNode(1);
const n1 = new ListNode(3); const n1 = new ListNode(3);
const n2 = new ListNode(2); const n2 = new ListNode(2);
@ -64,20 +64,20 @@ n3.next = n4;
console.log("初始化的链表为"); console.log("初始化的链表为");
printLinkedList(n0); printLinkedList(n0);
/* 插入点 */ /* 插入点 */
insert(n0, new ListNode(0)); insert(n0, new ListNode(0));
console.log("插入点后的链表为"); console.log("插入点后的链表为");
printLinkedList(n0); printLinkedList(n0);
/* 删除点 */ /* 删除点 */
remove(n0); remove(n0);
console.log("删除点后的链表为"); console.log("删除点后的链表为");
printLinkedList(n0); printLinkedList(n0);
/* 访问点 */ /* 访问点 */
const node = access(n0, 3); const node = access(n0, 3);
console.log("链表中索引 3 处的点的值 = " + node.val); console.log("链表中索引 3 处的点的值 = " + node.val);
/* 查找点 */ /* 查找点 */
const index = find(n0, 2); const index = find(n0, 2);
console.log("链表中值为 2 的点的索引 = " + index); console.log("链表中值为 2 的点的索引 = " + index);

View File

@ -14,23 +14,23 @@ class MaxHeap {
constructor(nums) { constructor(nums) {
// 将列表元素原封不动添加进堆 // 将列表元素原封不动添加进堆
this.#maxHeap = nums === undefined ? [] : [...nums]; this.#maxHeap = nums === undefined ? [] : [...nums];
// 堆化除叶结点以外的其他所有结 // 堆化除叶节点以外的其他所有节
for (let i = this.#parent(this.size() - 1); i >= 0; i--) { for (let i = this.#parent(this.size() - 1); i >= 0; i--) {
this.#siftDown(i); this.#siftDown(i);
} }
} }
/* 获取左子点索引 */ /* 获取左子点索引 */
#left(i) { #left(i) {
return 2 * i + 1; return 2 * i + 1;
} }
/* 获取右子点索引 */ /* 获取右子点索引 */
#right(i) { #right(i) {
return 2 * i + 2; return 2 * i + 2;
} }
/* 获取父点索引 */ /* 获取父点索引 */
#parent(i) { #parent(i) {
return Math.floor((i - 1) / 2); // 向下整除 return Math.floor((i - 1) / 2); // 向下整除
} }
@ -61,20 +61,20 @@ class MaxHeap {
/* 元素入堆 */ /* 元素入堆 */
push(val) { push(val) {
// 添加 // 添加
this.#maxHeap.push(val); this.#maxHeap.push(val);
// 从底至顶堆化 // 从底至顶堆化
this.#siftUp(this.size() - 1); this.#siftUp(this.size() - 1);
} }
/* 从点 i 开始,从底至顶堆化 */ /* 从点 i 开始,从底至顶堆化 */
#siftUp(i) { #siftUp(i) {
while (true) { while (true) {
// 获取结点 i 的父结 // 获取节点 i 的父节
const p = this.#parent(i); const p = this.#parent(i);
// 当“越过根结点”或“结点无需修复”时,结束堆化 // 当“越过根节点”或“节点无需修复”时,结束堆化
if (p < 0 || this.#maxHeap[i] <= this.#maxHeap[p]) break; if (p < 0 || this.#maxHeap[i] <= this.#maxHeap[p]) break;
// 交换两 // 交换两
this.#swap(i, p); this.#swap(i, p);
// 循环向上堆化 // 循环向上堆化
i = p; i = p;
@ -85,9 +85,9 @@ class MaxHeap {
pop() { pop() {
// 判空处理 // 判空处理
if (this.isEmpty()) throw new Error("堆为空"); if (this.isEmpty()) throw new Error("堆为空");
// 交换根结点与最右叶结点(即交换首元素与尾元素) // 交换根节点与最右叶节点(即交换首元素与尾元素)
this.#swap(0, this.size() - 1); this.#swap(0, this.size() - 1);
// 删除 // 删除
const val = this.#maxHeap.pop(); const val = this.#maxHeap.pop();
// 从顶至底堆化 // 从顶至底堆化
this.#siftDown(0); this.#siftDown(0);
@ -95,18 +95,18 @@ class MaxHeap {
return val; return val;
} }
/* 从点 i 开始,从顶至底堆化 */ /* 从点 i 开始,从顶至底堆化 */
#siftDown(i) { #siftDown(i) {
while (true) { while (true) {
// 判断结点 i, l, r 中值最大的结点,记为 ma // 判断节点 i, l, r 中值最大的节点,记为 ma
const l = this.#left(i), const l = this.#left(i),
r = this.#right(i); r = this.#right(i);
let ma = i; let ma = i;
if (l < this.size() && this.#maxHeap[l] > this.#maxHeap[ma]) ma = l; if (l < this.size() && this.#maxHeap[l] > this.#maxHeap[ma]) ma = l;
if (r < this.size() && this.#maxHeap[r] > this.#maxHeap[ma]) ma = r; if (r < this.size() && this.#maxHeap[r] > this.#maxHeap[ma]) ma = r;
// 若点 i 最大或索引 l, r 越界,则无需继续堆化,跳出 // 若点 i 最大或索引 l, r 越界,则无需继续堆化,跳出
if (ma == i) break; if (ma == i) break;
// 交换两 // 交换两
this.#swap(i, ma); this.#swap(i, ma);
// 循环向下堆化 // 循环向下堆化
i = ma; i = ma;

View File

@ -15,7 +15,7 @@ function hashingSearchArray(map, target) {
/* 哈希查找(链表) */ /* 哈希查找(链表) */
function hashingSearchLinkedList(map, target) { function hashingSearchLinkedList(map, target) {
// 哈希表的 key: 目标结点值value: 结点对象 // 哈希表的 key: 目标节点值value: 节点对象
// 若哈希表中无此 key ,返回 null // 若哈希表中无此 key ,返回 null
return map.has(target) ? map.get(target) : null; return map.has(target) ? map.get(target) : null;
} }
@ -38,8 +38,8 @@ let head = arrToLinkedList(nums)
// 初始化哈希表 // 初始化哈希表
const map1 = new Map(); const map1 = new Map();
while (head != null) { while (head != null) {
map1.set(head.val, head); // key: 结点值value: 结 map1.set(head.val, head); // key: 节点值value: 节
head = head.next; head = head.next;
} }
const node = hashingSearchLinkedList(map1, target); const node = hashingSearchLinkedList(map1, target);
console.log("目标结点值 3 的对应结点对象为", node); console.log("目标节点值 3 的对应节点对象为", node);

View File

@ -23,13 +23,13 @@ function linearSearchArray(nums, target) {
function linearSearchLinkedList(head, target) { function linearSearchLinkedList(head, target) {
// 遍历链表 // 遍历链表
while(head) { while(head) {
// 找到目标点,返回之 // 找到目标点,返回之
if(head.val === target) { if(head.val === target) {
return head; return head;
} }
head = head.next; head = head.next;
} }
// 未找到目标点,返回 null // 未找到目标点,返回 null
return null; return null;
} }
@ -44,4 +44,4 @@ console.log("目标元素 3 的索引 = " + index);
/* 在链表中执行线性查找 */ /* 在链表中执行线性查找 */
const head = arrToLinkedList(nums); const head = arrToLinkedList(nums);
const node = linearSearchLinkedList(head, target); const node = linearSearchLinkedList(head, target);
console.log("目标结点值 3 的对应结点对象为 ", node); console.log("目标节点值 3 的对应节点对象为 ", node);

View File

@ -4,11 +4,11 @@
* Author: Zhuo Qinyue (1403450829@qq.com) * Author: Zhuo Qinyue (1403450829@qq.com)
*/ */
/* 双向链表点 */ /* 双向链表点 */
class ListNode { class ListNode {
prev; // 前驱点引用 (指针) prev; // 前驱点引用 (指针)
next; // 后继点引用 (指针) next; // 后继点引用 (指针)
val; // 点值 val; // 点值
constructor(val) { constructor(val) {
this.val = val; this.val = val;
@ -19,8 +19,8 @@ class ListNode {
/* 基于双向链表实现的双向队列 */ /* 基于双向链表实现的双向队列 */
class LinkedListDeque { class LinkedListDeque {
#front; // 头点 front #front; // 头点 front
#rear; // 尾点 rear #rear; // 尾点 rear
#queSize; // 双向队列的长度 #queSize; // 双向队列的长度
constructor() { constructor() {
@ -40,7 +40,7 @@ class LinkedListDeque {
// 将 node 添加至链表尾部 // 将 node 添加至链表尾部
this.#rear.next = node; this.#rear.next = node;
node.prev = this.#rear; node.prev = this.#rear;
this.#rear = node; // 更新尾 this.#rear = node; // 更新尾
} }
this.#queSize++; this.#queSize++;
} }
@ -56,7 +56,7 @@ class LinkedListDeque {
// 将 node 添加至链表头部 // 将 node 添加至链表头部
this.#front.prev = node; this.#front.prev = node;
node.next = this.#front; node.next = this.#front;
this.#front = node; // 更新头 this.#front = node; // 更新头
} }
this.#queSize++; this.#queSize++;
} }
@ -66,14 +66,14 @@ class LinkedListDeque {
if (this.#queSize === 0) { if (this.#queSize === 0) {
return null; return null;
} }
const value = this.#rear.val; // 存储尾点值 const value = this.#rear.val; // 存储尾点值
// 删除尾 // 删除尾
let temp = this.#rear.prev; let temp = this.#rear.prev;
if (temp !== null) { if (temp !== null) {
temp.next = null; temp.next = null;
this.#rear.prev = null; this.#rear.prev = null;
} }
this.#rear = temp; // 更新尾 this.#rear = temp; // 更新尾
this.#queSize--; this.#queSize--;
return value; return value;
} }
@ -83,14 +83,14 @@ class LinkedListDeque {
if (this.#queSize === 0) { if (this.#queSize === 0) {
return null; return null;
} }
const value = this.#front.val; // 存储尾点值 const value = this.#front.val; // 存储尾点值
// 删除头 // 删除头
let temp = this.#front.next; let temp = this.#front.next;
if (temp !== null) { if (temp !== null) {
temp.prev = null; temp.prev = null;
this.#front.next = null; this.#front.next = null;
} }
this.#front = temp; // 更新头 this.#front = temp; // 更新头
this.#queSize--; this.#queSize--;
return value; return value;
} }

View File

@ -8,8 +8,8 @@ const { ListNode } = require("../modules/ListNode");
/* 基于链表实现的队列 */ /* 基于链表实现的队列 */
class LinkedListQueue { class LinkedListQueue {
#front; // 头点 #front #front; // 头点 #front
#rear; // 尾点 #rear #rear; // 尾点 #rear
#queSize = 0; #queSize = 0;
constructor() { constructor() {
@ -29,13 +29,13 @@ class LinkedListQueue {
/* 入队 */ /* 入队 */
push(num) { push(num) {
// 尾点后添加 num // 尾点后添加 num
const node = new ListNode(num); const node = new ListNode(num);
// 如果队列为空,则令头、尾结点都指向该结 // 如果队列为空,则令头、尾节点都指向该节
if (!this.#front) { if (!this.#front) {
this.#front = node; this.#front = node;
this.#rear = node; this.#rear = node;
// 如果队列不为空,则将该结点添加到尾结点后 // 如果队列不为空,则将该节点添加到尾节点后
} else { } else {
this.#rear.next = node; this.#rear.next = node;
this.#rear = node; this.#rear = node;
@ -46,7 +46,7 @@ class LinkedListQueue {
/* 出队 */ /* 出队 */
pop() { pop() {
const num = this.peek(); const num = this.peek();
// 删除头 // 删除头
this.#front = this.#front.next; this.#front = this.#front.next;
this.#queSize--; this.#queSize--;
return num; return num;

View File

@ -8,7 +8,7 @@ const { ListNode } = require("../modules/ListNode");
/* 基于链表实现的栈 */ /* 基于链表实现的栈 */
class LinkedListStack { class LinkedListStack {
#stackPeek; // 将头点作为栈顶 #stackPeek; // 将头点作为栈顶
#stkSize = 0; // 栈的长度 #stkSize = 0; // 栈的长度
constructor() { constructor() {

View File

@ -11,26 +11,26 @@ const { printTree } = require("../modules/PrintUtil");
class AVLTree { class AVLTree {
/*构造方法*/ /*构造方法*/
constructor() { constructor() {
this.root = null; //根 this.root = null; //根
} }
/* 获取点高度 */ /* 获取点高度 */
height(node) { height(node) {
// 空结点高度为 -1 ,叶结点高度为 0 // 空节点高度为 -1 ,叶节点高度为 0
return node === null ? -1 : node.height; return node === null ? -1 : node.height;
} }
/* 更新点高度 */ /* 更新点高度 */
#updateHeight(node) { #updateHeight(node) {
// 点高度等于最高子树高度 + 1 // 点高度等于最高子树高度 + 1
node.height = Math.max(this.height(node.left), this.height(node.right)) + 1; node.height = Math.max(this.height(node.left), this.height(node.right)) + 1;
} }
/* 获取平衡因子 */ /* 获取平衡因子 */
balanceFactor(node) { balanceFactor(node) {
// 空点平衡因子为 0 // 空点平衡因子为 0
if (node === null) return 0; if (node === null) return 0;
// 点平衡因子 = 左子树高度 - 右子树高度 // 点平衡因子 = 左子树高度 - 右子树高度
return this.height(node.left) - this.height(node.right); return this.height(node.left) - this.height(node.right);
} }
@ -41,10 +41,10 @@ class AVLTree {
// 以 child 为原点,将 node 向右旋转 // 以 child 为原点,将 node 向右旋转
child.right = node; child.right = node;
node.left = grandChild; node.left = grandChild;
// 更新点高度 // 更新点高度
this.#updateHeight(node); this.#updateHeight(node);
this.#updateHeight(child); this.#updateHeight(child);
// 返回旋转后子树的根 // 返回旋转后子树的根
return child; return child;
} }
@ -55,16 +55,16 @@ class AVLTree {
// 以 child 为原点,将 node 向左旋转 // 以 child 为原点,将 node 向左旋转
child.left = node; child.left = node;
node.right = grandChild; node.right = grandChild;
// 更新点高度 // 更新点高度
this.#updateHeight(node); this.#updateHeight(node);
this.#updateHeight(child); this.#updateHeight(child);
// 返回旋转后子树的根 // 返回旋转后子树的根
return child; return child;
} }
/* 执行旋转操作,使该子树重新恢复平衡 */ /* 执行旋转操作,使该子树重新恢复平衡 */
#rotate(node) { #rotate(node) {
// 获取点 node 的平衡因子 // 获取点 node 的平衡因子
const balanceFactor = this.balanceFactor(node); const balanceFactor = this.balanceFactor(node);
// 左偏树 // 左偏树
if (balanceFactor > 1) { if (balanceFactor > 1) {
@ -92,103 +92,103 @@ class AVLTree {
return node; return node;
} }
/* 插入点 */ /* 插入点 */
insert(val) { insert(val) {
this.root = this.#insertHelper(this.root, val); this.root = this.#insertHelper(this.root, val);
return this.root; return this.root;
} }
/* 递归插入点(辅助方法) */ /* 递归插入点(辅助方法) */
#insertHelper(node, val) { #insertHelper(node, val) {
if (node === null) return new TreeNode(val); if (node === null) return new TreeNode(val);
/* 1. 查找插入位置,并插入点 */ /* 1. 查找插入位置,并插入点 */
if (val < node.val) node.left = this.#insertHelper(node.left, val); if (val < node.val) node.left = this.#insertHelper(node.left, val);
else if (val > node.val) node.right = this.#insertHelper(node.right, val); else if (val > node.val) node.right = this.#insertHelper(node.right, val);
else return node; // 重复点不插入,直接返回 else return node; // 重复点不插入,直接返回
this.#updateHeight(node); // 更新点高度 this.#updateHeight(node); // 更新点高度
/* 2. 执行旋转操作,使该子树重新恢复平衡 */ /* 2. 执行旋转操作,使该子树重新恢复平衡 */
node = this.#rotate(node); node = this.#rotate(node);
// 返回子树的根 // 返回子树的根
return node; return node;
} }
/* 删除点 */ /* 删除点 */
remove(val) { remove(val) {
this.root = this.#removeHelper(this.root, val); this.root = this.#removeHelper(this.root, val);
return this.root; return this.root;
} }
/* 递归删除点(辅助方法) */ /* 递归删除点(辅助方法) */
#removeHelper(node, val) { #removeHelper(node, val) {
if (node === null) return null; if (node === null) return null;
/* 1. 查找点,并删除之 */ /* 1. 查找点,并删除之 */
if (val < node.val) node.left = this.#removeHelper(node.left, val); if (val < node.val) node.left = this.#removeHelper(node.left, val);
else if (val > node.val) node.right = this.#removeHelper(node.right, val); else if (val > node.val) node.right = this.#removeHelper(node.right, val);
else { else {
if (node.left === null || node.right === null) { if (node.left === null || node.right === null) {
const child = node.left !== null ? node.left : node.right; const child = node.left !== null ? node.left : node.right;
// 子点数量 = 0 ,直接删除 node 并返回 // 子点数量 = 0 ,直接删除 node 并返回
if (child === null) return null; if (child === null) return null;
// 子点数量 = 1 ,直接删除 node // 子点数量 = 1 ,直接删除 node
else node = child; else node = child;
} else { } else {
// 子结点数量 = 2 ,则将中序遍历的下个结点删除,并用该结点替换当前结 // 子节点数量 = 2 ,则将中序遍历的下个节点删除,并用该节点替换当前节
const temp = this.#getInOrderNext(node.right); const temp = this.#getInOrderNext(node.right);
node.right = this.#removeHelper(node.right, temp.val); node.right = this.#removeHelper(node.right, temp.val);
node.val = temp.val; node.val = temp.val;
} }
} }
this.#updateHeight(node); // 更新点高度 this.#updateHeight(node); // 更新点高度
/* 2. 执行旋转操作,使该子树重新恢复平衡 */ /* 2. 执行旋转操作,使该子树重新恢复平衡 */
node = this.#rotate(node); node = this.#rotate(node);
// 返回子树的根 // 返回子树的根
return node; return node;
} }
/* 获取中序遍历中的下一个结点(仅适用于 root 有左子结点的情况) */ /* 获取中序遍历中的下一个节点(仅适用于 root 有左子节点的情况) */
#getInOrderNext(node) { #getInOrderNext(node) {
if (node === null) return node; if (node === null) return node;
// 循环访问左子结点,直到叶结点时为最小结点,跳出 // 循环访问左子节点,直到叶节点时为最小节点,跳出
while (node.left !== null) { while (node.left !== null) {
node = node.left; node = node.left;
} }
return node; return node;
} }
/* 查找点 */ /* 查找点 */
search(val) { search(val) {
let cur = this.root; let cur = this.root;
// 循环查找,越过叶点后跳出 // 循环查找,越过叶点后跳出
while (cur !== null) { while (cur !== null) {
// 目标点在 cur 的右子树中 // 目标点在 cur 的右子树中
if (cur.val < val) cur = cur.right; if (cur.val < val) cur = cur.right;
// 目标点在 cur 的左子树中 // 目标点在 cur 的左子树中
else if (cur.val > val) cur = cur.left; else if (cur.val > val) cur = cur.left;
// 找到目标点,跳出循环 // 找到目标点,跳出循环
else break; else break;
} }
// 返回目标 // 返回目标
return cur; return cur;
} }
} }
function testInsert(tree, val) { function testInsert(tree, val) {
tree.insert(val); tree.insert(val);
console.log("\n插入点 " + val + " 后AVL 树为"); console.log("\n插入点 " + val + " 后AVL 树为");
printTree(tree.root); printTree(tree.root);
} }
function testRemove(tree, val) { function testRemove(tree, val) {
tree.remove(val); tree.remove(val);
console.log("\n删除点 " + val + " 后AVL 树为"); console.log("\n删除点 " + val + " 后AVL 树为");
printTree(tree.root); printTree(tree.root);
} }
/* Driver Code */ /* Driver Code */
/* 初始化空 AVL 树 */ /* 初始化空 AVL 树 */
const avlTree = new AVLTree(); const avlTree = new AVLTree();
/* 插入点 */ /* 插入点 */
// 请关注插入点后AVL 树是如何保持平衡的 // 请关注插入点后AVL 树是如何保持平衡的
testInsert(avlTree, 1); testInsert(avlTree, 1);
testInsert(avlTree, 2); testInsert(avlTree, 2);
testInsert(avlTree, 3); testInsert(avlTree, 3);
@ -200,15 +200,15 @@ testInsert(avlTree, 9);
testInsert(avlTree, 10); testInsert(avlTree, 10);
testInsert(avlTree, 6); testInsert(avlTree, 6);
/* 插入重复点 */ /* 插入重复点 */
testInsert(avlTree, 7); testInsert(avlTree, 7);
/* 删除点 */ /* 删除点 */
// 请关注删除点后AVL 树是如何保持平衡的 // 请关注删除点后AVL 树是如何保持平衡的
testRemove(avlTree, 8); // 删除度为 0 的 testRemove(avlTree, 8); // 删除度为 0 的
testRemove(avlTree, 5); // 删除度为 1 的 testRemove(avlTree, 5); // 删除度为 1 的
testRemove(avlTree, 4); // 删除度为 2 的 testRemove(avlTree, 4); // 删除度为 2 的
/* 查询点 */ /* 查询点 */
const node = avlTree.search(7); const node = avlTree.search(7);
console.log("\n查找到的结点对象为", node, ",结点值 = " + node.val); console.log("\n查找到的节点对象为", node, ",节点值 = " + node.val);

View File

@ -15,7 +15,7 @@ function BinarySearchTree(nums) {
root = buildTree(nums, 0, nums.length - 1); // 构建二叉搜索树 root = buildTree(nums, 0, nums.length - 1); // 构建二叉搜索树
} }
/* 获取二叉树根点 */ /* 获取二叉树根点 */
function getRoot() { function getRoot() {
return root; return root;
} }
@ -23,7 +23,7 @@ function getRoot() {
/* 构建二叉搜索树 */ /* 构建二叉搜索树 */
function buildTree(nums, i, j) { function buildTree(nums, i, j) {
if (i > j) return null; if (i > j) return null;
// 将数组中间结点作为根结 // 将数组中间节点作为根节
let mid = Math.floor((i + j) / 2); let mid = Math.floor((i + j) / 2);
let root = new TreeNode(nums[mid]); let root = new TreeNode(nums[mid]);
// 递归建立左子树和右子树 // 递归建立左子树和右子树
@ -32,30 +32,30 @@ function buildTree(nums, i, j) {
return root; return root;
} }
/* 查找点 */ /* 查找点 */
function search(num) { function search(num) {
let cur = root; let cur = root;
// 循环查找,越过叶点后跳出 // 循环查找,越过叶点后跳出
while (cur !== null) { while (cur !== null) {
// 目标点在 cur 的右子树中 // 目标点在 cur 的右子树中
if (cur.val < num) cur = cur.right; if (cur.val < num) cur = cur.right;
// 目标点在 cur 的左子树中 // 目标点在 cur 的左子树中
else if (cur.val > num) cur = cur.left; else if (cur.val > num) cur = cur.left;
// 找到目标点,跳出循环 // 找到目标点,跳出循环
else break; else break;
} }
// 返回目标 // 返回目标
return cur; return cur;
} }
/* 插入点 */ /* 插入点 */
function insert(num) { function insert(num) {
// 若树为空,直接提前返回 // 若树为空,直接提前返回
if (root === null) return null; if (root === null) return null;
let cur = root, pre = null; let cur = root, pre = null;
// 循环查找,越过叶点后跳出 // 循环查找,越过叶点后跳出
while (cur !== null) { while (cur !== null) {
// 找到重复点,直接返回 // 找到重复点,直接返回
if (cur.val === num) return null; if (cur.val === num) return null;
pre = cur; pre = cur;
// 插入位置在 cur 的右子树中 // 插入位置在 cur 的右子树中
@ -63,44 +63,44 @@ function insert(num) {
// 插入位置在 cur 的左子树中 // 插入位置在 cur 的左子树中
else cur = cur.left; else cur = cur.left;
} }
// 插入点 val // 插入点 val
let node = new TreeNode(num); let node = new TreeNode(num);
if (pre.val < num) pre.right = node; if (pre.val < num) pre.right = node;
else pre.left = node; else pre.left = node;
return node; return node;
} }
/* 删除点 */ /* 删除点 */
function remove(num) { function remove(num) {
// 若树为空,直接提前返回 // 若树为空,直接提前返回
if (root === null) return null; if (root === null) return null;
let cur = root, pre = null; let cur = root, pre = null;
// 循环查找,越过叶点后跳出 // 循环查找,越过叶点后跳出
while (cur !== null) { while (cur !== null) {
// 找到待删除点,跳出循环 // 找到待删除点,跳出循环
if (cur.val === num) break; if (cur.val === num) break;
pre = cur; pre = cur;
// 待删除点在 cur 的右子树中 // 待删除点在 cur 的右子树中
if (cur.val < num) cur = cur.right; if (cur.val < num) cur = cur.right;
// 待删除点在 cur 的左子树中 // 待删除点在 cur 的左子树中
else cur = cur.left; else cur = cur.left;
} }
// 若无待删除点,则直接返回 // 若无待删除点,则直接返回
if (cur === null) return null; if (cur === null) return null;
// 子点数量 = 0 or 1 // 子点数量 = 0 or 1
if (cur.left === null || cur.right === null) { if (cur.left === null || cur.right === null) {
// 当子结点数量 = 0 / 1 时, child = null / 该子结 // 当子节点数量 = 0 / 1 时, child = null / 该子节
let child = cur.left !== null ? cur.left : cur.right; let child = cur.left !== null ? cur.left : cur.right;
// 删除点 cur // 删除点 cur
if (pre.left === cur) pre.left = child; if (pre.left === cur) pre.left = child;
else pre.right = child; else pre.right = child;
} }
// 子点数量 = 2 // 子点数量 = 2
else { else {
// 获取中序遍历中 cur 的下一个 // 获取中序遍历中 cur 的下一个
let nex = getInOrderNext(cur.right); let nex = getInOrderNext(cur.right);
let tmp = nex.val; let tmp = nex.val;
// 递归删除点 nex // 递归删除点 nex
remove(nex.val); remove(nex.val);
// 将 nex 的值复制给 cur // 将 nex 的值复制给 cur
cur.val = tmp; cur.val = tmp;
@ -108,10 +108,10 @@ function remove(num) {
return cur; return cur;
} }
/* 获取中序遍历中的下一个结点(仅适用于 root 有左子结点的情况) */ /* 获取中序遍历中的下一个节点(仅适用于 root 有左子节点的情况) */
function getInOrderNext(root) { function getInOrderNext(root) {
if (root === null) return root; if (root === null) return root;
// 循环访问左子结点,直到叶结点时为最小结点,跳出 // 循环访问左子节点,直到叶节点时为最小节点,跳出
while (root.left !== null) { while (root.left !== null) {
root = root.left; root = root.left;
} }
@ -125,22 +125,22 @@ BinarySearchTree(nums);
console.log("\n初始化的二叉树为\n"); console.log("\n初始化的二叉树为\n");
printTree(getRoot()); printTree(getRoot());
/* 查找点 */ /* 查找点 */
let node = search(7); let node = search(7);
console.log("\n查找到的结点对象为 " + node + ",结点值 = " + node.val); console.log("\n查找到的节点对象为 " + node + ",节点值 = " + node.val);
/* 插入点 */ /* 插入点 */
node = insert(16); node = insert(16);
console.log("\n插入点 16 后,二叉树为\n"); console.log("\n插入点 16 后,二叉树为\n");
printTree(getRoot()); printTree(getRoot());
/* 删除点 */ /* 删除点 */
remove(1); remove(1);
console.log("\n删除点 1 后,二叉树为\n"); console.log("\n删除点 1 后,二叉树为\n");
printTree(getRoot()); printTree(getRoot());
remove(2); remove(2);
console.log("\n删除点 2 后,二叉树为\n"); console.log("\n删除点 2 后,二叉树为\n");
printTree(getRoot()); printTree(getRoot());
remove(4); remove(4);
console.log("\n删除点 4 后,二叉树为\n"); console.log("\n删除点 4 后,二叉树为\n");
printTree(getRoot()); printTree(getRoot());

View File

@ -8,7 +8,7 @@ const { TreeNode } = require("../modules/TreeNode");
const { printTree } = require("../modules/PrintUtil"); const { printTree } = require("../modules/PrintUtil");
/* 初始化二叉树 */ /* 初始化二叉树 */
// 初始化 // 初始化
let n1 = new TreeNode(1), let n1 = new TreeNode(1),
n2 = new TreeNode(2), n2 = new TreeNode(2),
n3 = new TreeNode(3), n3 = new TreeNode(3),
@ -22,14 +22,14 @@ n2.right = n5;
console.log("\n初始化二叉树\n"); console.log("\n初始化二叉树\n");
printTree(n1); printTree(n1);
/* 插入与删除点 */ /* 插入与删除点 */
const P = new TreeNode(0); const P = new TreeNode(0);
// 在 n1 -> n2 中间插入点 P // 在 n1 -> n2 中间插入点 P
n1.left = P; n1.left = P;
P.left = n2; P.left = n2;
console.log("\n插入点 P 后\n"); console.log("\n插入点 P 后\n");
printTree(n1); printTree(n1);
// 删除点 P // 删除点 P
n1.left = n2; n1.left = n2;
console.log("\n删除点 P 后\n"); console.log("\n删除点 P 后\n");
printTree(n1); printTree(n1);

View File

@ -9,17 +9,17 @@ const { printTree } = require("../modules/PrintUtil");
/* 层序遍历 */ /* 层序遍历 */
function levelOrder(root) { function levelOrder(root) {
// 初始化队列,加入根 // 初始化队列,加入根
const queue = [root]; const queue = [root];
// 初始化一个列表,用于保存遍历序列 // 初始化一个列表,用于保存遍历序列
const list = []; const list = [];
while (queue.length) { while (queue.length) {
let node = queue.shift(); // 队列出队 let node = queue.shift(); // 队列出队
list.push(node.val); // 保存点值 list.push(node.val); // 保存点值
if (node.left) if (node.left)
queue.push(node.left); // 左子点入队 queue.push(node.left); // 左子点入队
if (node.right) if (node.right)
queue.push(node.right); // 右子点入队 queue.push(node.right); // 右子点入队
} }
return list; return list;
@ -34,4 +34,4 @@ printTree(root);
/* 层序遍历 */ /* 层序遍历 */
const list = levelOrder(root); const list = levelOrder(root);
console.log("\n层序遍历的点打印序列 = " + list); console.log("\n层序遍历的点打印序列 = " + list);

View File

@ -13,7 +13,7 @@ const list = [];
/* 前序遍历 */ /* 前序遍历 */
function preOrder(root) { function preOrder(root) {
if (root === null) return; if (root === null) return;
// 访问优先级:根点 -> 左子树 -> 右子树 // 访问优先级:根点 -> 左子树 -> 右子树
list.push(root.val); list.push(root.val);
preOrder(root.left); preOrder(root.left);
preOrder(root.right); preOrder(root.right);
@ -22,7 +22,7 @@ function preOrder(root) {
/* 中序遍历 */ /* 中序遍历 */
function inOrder(root) { function inOrder(root) {
if (root === null) return; if (root === null) return;
// 访问优先级:左子树 -> 根点 -> 右子树 // 访问优先级:左子树 -> 根点 -> 右子树
inOrder(root.left); inOrder(root.left);
list.push(root.val); list.push(root.val);
inOrder(root.right); inOrder(root.right);
@ -31,7 +31,7 @@ function inOrder(root) {
/* 后序遍历 */ /* 后序遍历 */
function postOrder(root) { function postOrder(root) {
if (root === null) return; if (root === null) return;
// 访问优先级:左子树 -> 右子树 -> 根 // 访问优先级:左子树 -> 右子树 -> 根
postOrder(root.left); postOrder(root.left);
postOrder(root.right); postOrder(root.right);
list.push(root.val); list.push(root.val);
@ -47,14 +47,14 @@ printTree(root);
/* 前序遍历 */ /* 前序遍历 */
list.length = 0; list.length = 0;
preOrder(root); preOrder(root);
console.log("\n前序遍历的点打印序列 = " + list); console.log("\n前序遍历的点打印序列 = " + list);
/* 中序遍历 */ /* 中序遍历 */
list.length = 0; list.length = 0;
inOrder(root); inOrder(root);
console.log("\n中序遍历的点打印序列 = " + list); console.log("\n中序遍历的点打印序列 = " + list);
/* 后序遍历 */ /* 后序遍历 */
list.length = 0; list.length = 0;
postOrder(root); postOrder(root);
console.log("\n后序遍历的点打印序列 = " + list); console.log("\n后序遍历的点打印序列 = " + list);

View File

@ -8,10 +8,10 @@
* Definition for a binary tree node. * Definition for a binary tree node.
*/ */
class TreeNode { class TreeNode {
val; // 点值 val; // 点值
left; // 左子点指针 left; // 左子点指针
right; // 右子点指针 right; // 右子点指针
height; //点高度 height; //点高度
constructor(val, left, right, height) { constructor(val, left, right, height) {
this.val = val === undefined ? 0 : val; this.val = val === undefined ? 0 : val;
this.left = left === undefined ? null : left; this.left = left === undefined ? null : left;

View File

@ -9,13 +9,13 @@ sys.path.append(osp.dirname(osp.dirname(osp.abspath(__file__))))
from modules import * from modules import *
def insert(n0: ListNode, P: ListNode) -> None: def insert(n0: ListNode, P: ListNode) -> None:
""" 在链表的结点 n0 之后插入结点 P """ """ 在链表的节点 n0 之后插入节点 P """
n1 = n0.next n1 = n0.next
P.next = n1 P.next = n1
n0.next = P n0.next = P
def remove(n0: ListNode) -> None: def remove(n0: ListNode) -> None:
""" 删除链表的结点 n0 之后的首个结""" """ 删除链表的节点 n0 之后的首个节"""
if not n0.next: if not n0.next:
return return
# n0 -> P -> n1 # n0 -> P -> n1
@ -24,7 +24,7 @@ def remove(n0: ListNode) -> None:
n0.next = n1 n0.next = n1
def access(head: ListNode, index: int) -> ListNode | None: def access(head: ListNode, index: int) -> ListNode | None:
""" 访问链表中索引为 index 的""" """ 访问链表中索引为 index 的"""
for _ in range(index): for _ in range(index):
if not head: if not head:
return None return None
@ -32,7 +32,7 @@ def access(head: ListNode, index: int) -> ListNode | None:
return head return head
def find(head: ListNode, target: int) -> int: def find(head: ListNode, target: int) -> int:
""" 在链表中查找值为 target 的首个""" """ 在链表中查找值为 target 的首个"""
index = 0 index = 0
while head: while head:
if head.val == target: if head.val == target:
@ -45,7 +45,7 @@ def find(head: ListNode, target: int) -> int:
""" Driver Code """ """ Driver Code """
if __name__ == "__main__": if __name__ == "__main__":
""" 初始化链表 """ """ 初始化链表 """
# 初始化各个 # 初始化各个
n0 = ListNode(1) n0 = ListNode(1)
n1 = ListNode(3) n1 = ListNode(3)
n2 = ListNode(2) n2 = ListNode(2)
@ -59,20 +59,20 @@ if __name__ == "__main__":
print("初始化的链表为") print("初始化的链表为")
print_linked_list(n0) print_linked_list(n0)
""" 插入""" """ 插入"""
insert(n0, ListNode(0)) insert(n0, ListNode(0))
print("插入点后的链表为") print("插入点后的链表为")
print_linked_list(n0) print_linked_list(n0)
""" 删除""" """ 删除"""
remove(n0) remove(n0)
print("删除点后的链表为") print("删除点后的链表为")
print_linked_list(n0) print_linked_list(n0)
""" 访问""" """ 访问"""
node: ListNode = access(n0, 3) node: ListNode = access(n0, 3)
print("链表中索引 3 处的点的值 = {}".format(node.val)) print("链表中索引 3 处的点的值 = {}".format(node.val))
""" 查找""" """ 查找"""
index: int = find(n0, 2) index: int = find(n0, 2)
print("链表中值为 2 的点的索引 = {}".format(index)) print("链表中值为 2 的点的索引 = {}".format(index))

View File

@ -14,20 +14,20 @@ class MaxHeap:
""" 构造方法 """ """ 构造方法 """
# 将列表元素原封不动添加进堆 # 将列表元素原封不动添加进堆
self.max_heap = nums self.max_heap = nums
# 堆化除叶结点以外的其他所有结 # 堆化除叶节点以外的其他所有节
for i in range(self.parent(self.size() - 1), -1, -1): for i in range(self.parent(self.size() - 1), -1, -1):
self.sift_down(i) self.sift_down(i)
def left(self, i: int) -> int: def left(self, i: int) -> int:
""" 获取左子点索引 """ """ 获取左子点索引 """
return 2 * i + 1 return 2 * i + 1
def right(self, i: int) -> int: def right(self, i: int) -> int:
""" 获取右子点索引 """ """ 获取右子点索引 """
return 2 * i + 2 return 2 * i + 2
def parent(self, i: int) -> int: def parent(self, i: int) -> int:
""" 获取父点索引 """ """ 获取父点索引 """
return (i - 1) // 2 # 向下整除 return (i - 1) // 2 # 向下整除
def swap(self, i: int, j: int): def swap(self, i: int, j: int):
@ -49,20 +49,20 @@ class MaxHeap:
def push(self, val: int): def push(self, val: int):
""" 元素入堆 """ """ 元素入堆 """
# 添加 # 添加
self.max_heap.append(val) self.max_heap.append(val)
# 从底至顶堆化 # 从底至顶堆化
self.sift_up(self.size() - 1) self.sift_up(self.size() - 1)
def sift_up(self, i: int): def sift_up(self, i: int):
"""点 i 开始,从底至顶堆化 """ """点 i 开始,从底至顶堆化 """
while True: while True:
# 获取结点 i 的父结 # 获取节点 i 的父节
p = self.parent(i) p = self.parent(i)
# 当“越过根结点”或“结点无需修复”时,结束堆化 # 当“越过根节点”或“节点无需修复”时,结束堆化
if p < 0 or self.max_heap[i] <= self.max_heap[p]: if p < 0 or self.max_heap[i] <= self.max_heap[p]:
break break
# 交换两 # 交换两
self.swap(i, p) self.swap(i, p)
# 循环向上堆化 # 循环向上堆化
i = p i = p
@ -71,9 +71,9 @@ class MaxHeap:
""" 元素出堆 """ """ 元素出堆 """
# 判空处理 # 判空处理
assert not self.is_empty() assert not self.is_empty()
# 交换根结点与最右叶结点(即交换首元素与尾元素) # 交换根节点与最右叶节点(即交换首元素与尾元素)
self.swap(0, self.size() - 1) self.swap(0, self.size() - 1)
# 删除 # 删除
val = self.max_heap.pop() val = self.max_heap.pop()
# 从顶至底堆化 # 从顶至底堆化
self.sift_down(0) self.sift_down(0)
@ -81,18 +81,18 @@ class MaxHeap:
return val return val
def sift_down(self, i: int): def sift_down(self, i: int):
"""点 i 开始,从顶至底堆化 """ """点 i 开始,从顶至底堆化 """
while True: while True:
# 判断结点 i, l, r 中值最大的结点,记为 ma # 判断节点 i, l, r 中值最大的节点,记为 ma
l, r, ma = self.left(i), self.right(i), i l, r, ma = self.left(i), self.right(i), i
if l < self.size() and self.max_heap[l] > self.max_heap[ma]: if l < self.size() and self.max_heap[l] > self.max_heap[ma]:
ma = l ma = l
if r < self.size() and self.max_heap[r] > self.max_heap[ma]: if r < self.size() and self.max_heap[r] > self.max_heap[ma]:
ma = r ma = r
# 若点 i 最大或索引 l, r 越界,则无需继续堆化,跳出 # 若点 i 最大或索引 l, r 越界,则无需继续堆化,跳出
if ma == i: if ma == i:
break break
# 交换两 # 交换两
self.swap(i, ma) self.swap(i, ma)
# 循环向下堆化 # 循环向下堆化
i = ma i = ma

View File

@ -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: def hashing_search_linkedlist(mapp: dict[int, ListNode], target: int) -> ListNode | None:
""" 哈希查找(链表) """ """ 哈希查找(链表) """
# 哈希表的 key: 目标元素value: 点对象 # 哈希表的 key: 目标元素value: 点对象
# 若哈希表中无此 key ,返回 None # 若哈希表中无此 key ,返回 None
return mapp.get(target, None) return mapp.get(target, None)
@ -39,7 +39,7 @@ if __name__ == '__main__':
# 初始化哈希表 # 初始化哈希表
map1 = dict[int, ListNode]() map1 = dict[int, ListNode]()
while head: while head:
map1[head.val] = head # key: 结点值value: 结 map1[head.val] = head # key: 节点值value: 节
head = head.next head = head.next
node: ListNode = hashing_search_linkedlist(map1, target) node: ListNode = hashing_search_linkedlist(map1, target)
print("目标结点值 3 的对应结点对象为", node) print("目标节点值 3 的对应节点对象为", node)

View File

@ -20,10 +20,10 @@ def linear_search_linkedlist(head: ListNode, target: int) -> ListNode | None:
""" 线性查找(链表) """ """ 线性查找(链表) """
# 遍历链表 # 遍历链表
while head: while head:
if head.val == target: # 找到目标点,返回之 if head.val == target: # 找到目标点,返回之
return head return head
head = head.next head = head.next
return None # 未找到目标点,返回 None return None # 未找到目标点,返回 None
""" Driver Code """ """ Driver Code """
@ -38,4 +38,4 @@ if __name__ == '__main__':
# 在链表中执行线性查找 # 在链表中执行线性查找
head: ListNode = list_to_linked_list(nums) head: ListNode = list_to_linked_list(nums)
node: ListNode | None = linear_search_linkedlist(head, target) node: ListNode | None = linear_search_linkedlist(head, target)
print("目标结点值 3 的对应结点对象为", node) print("目标节点值 3 的对应节点对象为", node)

View File

@ -5,19 +5,19 @@ Author: Krahets (krahets@163.com)
""" """
class ListNode: class ListNode:
""" 双向链表""" """ 双向链表"""
def __init__(self, val: int) -> None: def __init__(self, val: int) -> None:
""" 构造方法 """ """ 构造方法 """
self.val: int = val self.val: int = val
self.next: ListNode | None = None # 后继点引用(指针) self.next: ListNode | None = None # 后继点引用(指针)
self.prev: ListNode | None = None # 前驱点引用(指针) self.prev: ListNode | None = None # 前驱点引用(指针)
class LinkedListDeque: class LinkedListDeque:
""" 基于双向链表实现的双向队列 """ """ 基于双向链表实现的双向队列 """
def __init__(self) -> None: def __init__(self) -> None:
""" 构造方法 """ """ 构造方法 """
self.front: ListNode | None = None # 头点 front self.front: ListNode | None = None # 头点 front
self.rear: ListNode | None = None # 尾点 rear self.rear: ListNode | None = None # 尾点 rear
self.__size: int = 0 # 双向队列的长度 self.__size: int = 0 # 双向队列的长度
def size(self) -> int: def size(self) -> int:
@ -39,13 +39,13 @@ class LinkedListDeque:
# 将 node 添加至链表头部 # 将 node 添加至链表头部
self.front.prev = node self.front.prev = node
node.next = self.front node.next = self.front
self.front = node # 更新头 self.front = node # 更新头
# 队尾入队操作 # 队尾入队操作
else: else:
# 将 node 添加至链表尾部 # 将 node 添加至链表尾部
self.rear.next = node self.rear.next = node
node.prev = self.rear node.prev = self.rear
self.rear = node # 更新尾 self.rear = node # 更新尾
self.__size += 1 # 更新队列长度 self.__size += 1 # 更新队列长度
def push_first(self, num: int) -> None: def push_first(self, num: int) -> None:
@ -63,22 +63,22 @@ class LinkedListDeque:
return None return None
# 队首出队操作 # 队首出队操作
if is_front: if is_front:
val: int = self.front.val # 暂存头点值 val: int = self.front.val # 暂存头点值
# 删除头 # 删除头
fnext: ListNode | None = self.front.next fnext: ListNode | None = self.front.next
if fnext != None: if fnext != None:
fnext.prev = None fnext.prev = None
self.front.next = None self.front.next = None
self.front = fnext # 更新头 self.front = fnext # 更新头
# 队尾出队操作 # 队尾出队操作
else: else:
val: int = self.rear.val # 暂存尾点值 val: int = self.rear.val # 暂存尾点值
# 删除尾 # 删除尾
rprev: ListNode | None = self.rear.prev rprev: ListNode | None = self.rear.prev
if rprev != None: if rprev != None:
rprev.next = None rprev.next = None
self.rear.prev = None self.rear.prev = None
self.rear = rprev # 更新尾 self.rear = rprev # 更新尾
self.__size -= 1 # 更新队列长度 self.__size -= 1 # 更新队列长度
return val return val

View File

@ -12,8 +12,8 @@ class LinkedListQueue:
""" 基于链表实现的队列 """ """ 基于链表实现的队列 """
def __init__(self): def __init__(self):
""" 构造方法 """ """ 构造方法 """
self.__front: ListNode | None = None # 头点 front self.__front: ListNode | None = None # 头点 front
self.__rear: ListNode | None = None # 尾点 rear self.__rear: ListNode | None = None # 尾点 rear
self.__size: int = 0 self.__size: int = 0
def size(self) -> int: def size(self) -> int:
@ -26,13 +26,13 @@ class LinkedListQueue:
def push(self, num: int) -> None: def push(self, num: int) -> None:
""" 入队 """ """ 入队 """
# 尾点后添加 num # 尾点后添加 num
node = ListNode(num) node = ListNode(num)
# 如果队列为空,则令头、尾结点都指向该结 # 如果队列为空,则令头、尾节点都指向该节
if self.__front is None: if self.__front is None:
self.__front = node self.__front = node
self.__rear = node self.__rear = node
# 如果队列不为空,则将该结点添加到尾结点后 # 如果队列不为空,则将该节点添加到尾节点后
else: else:
self.__rear.next = node self.__rear.next = node
self.__rear = node self.__rear = node
@ -41,7 +41,7 @@ class LinkedListQueue:
def pop(self) -> int: def pop(self) -> int:
""" 出队 """ """ 出队 """
num = self.peek() num = self.peek()
# 删除头 # 删除头
self.__front = self.__front.next self.__front = self.__front.next
self.__size -= 1 self.__size -= 1
return num return num

View File

@ -19,23 +19,23 @@ class AVLTree:
return self.__root return self.__root
def height(self, node: TreeNode | None) -> int: def height(self, node: TreeNode | None) -> int:
""" 获取点高度 """ """ 获取点高度 """
# 空结点高度为 -1 ,叶结点高度为 0 # 空节点高度为 -1 ,叶节点高度为 0
if node is not None: if node is not None:
return node.height return node.height
return -1 return -1
def __update_height(self, node: TreeNode | None): def __update_height(self, node: TreeNode | None):
""" 更新点高度 """ """ 更新点高度 """
# 点高度等于最高子树高度 + 1 # 点高度等于最高子树高度 + 1
node.height = max([self.height(node.left), self.height(node.right)]) + 1 node.height = max([self.height(node.left), self.height(node.right)]) + 1
def balance_factor(self, node: TreeNode | None) -> int: def balance_factor(self, node: TreeNode | None) -> int:
""" 获取平衡因子 """ """ 获取平衡因子 """
# 空点平衡因子为 0 # 空点平衡因子为 0
if node is None: if node is None:
return 0 return 0
# 点平衡因子 = 左子树高度 - 右子树高度 # 点平衡因子 = 左子树高度 - 右子树高度
return self.height(node.left) - self.height(node.right) return self.height(node.left) - self.height(node.right)
def __right_rotate(self, node: TreeNode | None) -> TreeNode | None: def __right_rotate(self, node: TreeNode | None) -> TreeNode | None:
@ -45,10 +45,10 @@ class AVLTree:
# 以 child 为原点,将 node 向右旋转 # 以 child 为原点,将 node 向右旋转
child.right = node child.right = node
node.left = grand_child node.left = grand_child
# 更新点高度 # 更新点高度
self.__update_height(node) self.__update_height(node)
self.__update_height(child) self.__update_height(child)
# 返回旋转后子树的根 # 返回旋转后子树的根
return child return child
def __left_rotate(self, node: TreeNode | None) -> TreeNode | None: def __left_rotate(self, node: TreeNode | None) -> TreeNode | None:
@ -58,15 +58,15 @@ class AVLTree:
# 以 child 为原点,将 node 向左旋转 # 以 child 为原点,将 node 向左旋转
child.left = node child.left = node
node.right = grand_child node.right = grand_child
# 更新点高度 # 更新点高度
self.__update_height(node) self.__update_height(node)
self.__update_height(child) self.__update_height(child)
# 返回旋转后子树的根 # 返回旋转后子树的根
return child return child
def __rotate(self, node: TreeNode | None) -> TreeNode | None: def __rotate(self, node: TreeNode | None) -> TreeNode | None:
""" 执行旋转操作,使该子树重新恢复平衡 """ """ 执行旋转操作,使该子树重新恢复平衡 """
# 获取点 node 的平衡因子 # 获取点 node 的平衡因子
balance_factor = self.balance_factor(node) balance_factor = self.balance_factor(node)
# 左偏树 # 左偏树
if balance_factor > 1: if balance_factor > 1:
@ -90,37 +90,37 @@ class AVLTree:
return node return node
def insert(self, val) -> TreeNode: def insert(self, val) -> TreeNode:
""" 插入""" """ 插入"""
self.__root = self.__insert_helper(self.__root, val) self.__root = self.__insert_helper(self.__root, val)
return self.__root return self.__root
def __insert_helper(self, node: TreeNode | None, val: int) -> TreeNode: def __insert_helper(self, node: TreeNode | None, val: int) -> TreeNode:
""" 递归插入点(辅助方法)""" """ 递归插入点(辅助方法)"""
if node is None: if node is None:
return TreeNode(val) return TreeNode(val)
# 1. 查找插入位置,并插入 # 1. 查找插入位置,并插入
if val < node.val: if val < node.val:
node.left = self.__insert_helper(node.left, val) node.left = self.__insert_helper(node.left, val)
elif val > node.val: elif val > node.val:
node.right = self.__insert_helper(node.right, val) node.right = self.__insert_helper(node.right, val)
else: else:
# 重复点不插入,直接返回 # 重复点不插入,直接返回
return node return node
# 更新点高度 # 更新点高度
self.__update_height(node) self.__update_height(node)
# 2. 执行旋转操作,使该子树重新恢复平衡 # 2. 执行旋转操作,使该子树重新恢复平衡
return self.__rotate(node) return self.__rotate(node)
def remove(self, val: int) -> TreeNode | None: def remove(self, val: int) -> TreeNode | None:
""" 删除""" """ 删除"""
self.__root = self.__remove_helper(self.__root, val) self.__root = self.__remove_helper(self.__root, val)
return self.__root return self.__root
def __remove_helper(self, node: TreeNode | None, val: int) -> TreeNode | None: def __remove_helper(self, node: TreeNode | None, val: int) -> TreeNode | None:
""" 递归删除点(辅助方法) """ """ 递归删除点(辅助方法) """
if node is None: if node is None:
return None return None
# 1. 查找点,并删除之 # 1. 查找点,并删除之
if val < node.val: if val < node.val:
node.left = self.__remove_helper(node.left, val) node.left = self.__remove_helper(node.left, val)
elif val > node.val: elif val > node.val:
@ -128,45 +128,45 @@ class AVLTree:
else: else:
if node.left is None or node.right is None: if node.left is None or node.right is None:
child = node.left or node.right child = node.left or node.right
# 子点数量 = 0 ,直接删除 node 并返回 # 子点数量 = 0 ,直接删除 node 并返回
if child is None: if child is None:
return None return None
# 子点数量 = 1 ,直接删除 node # 子点数量 = 1 ,直接删除 node
else: else:
node = child node = child
else: # 子结点数量 = 2 ,则将中序遍历的下个结点删除,并用该结点替换当前结 else: # 子节点数量 = 2 ,则将中序遍历的下个节点删除,并用该节点替换当前节
temp = self.__get_inorder_next(node.right) temp = self.__get_inorder_next(node.right)
node.right = self.__remove_helper(node.right, temp.val) node.right = self.__remove_helper(node.right, temp.val)
node.val = temp.val node.val = temp.val
# 更新点高度 # 更新点高度
self.__update_height(node) self.__update_height(node)
# 2. 执行旋转操作,使该子树重新恢复平衡 # 2. 执行旋转操作,使该子树重新恢复平衡
return self.__rotate(node) return self.__rotate(node)
def __get_inorder_next(self, node: TreeNode | None) -> TreeNode | None: def __get_inorder_next(self, node: TreeNode | None) -> TreeNode | None:
""" 获取中序遍历中的下一个结点(仅适用于 root 有左子结点的情况) """ """ 获取中序遍历中的下一个节点(仅适用于 root 有左子节点的情况) """
if node is None: if node is None:
return None return None
# 循环访问左子结点,直到叶结点时为最小结点,跳出 # 循环访问左子节点,直到叶节点时为最小节点,跳出
while node.left is not None: while node.left is not None:
node = node.left node = node.left
return node return node
def search(self, val: int) -> TreeNode | None: def search(self, val: int) -> TreeNode | None:
""" 查找""" """ 查找"""
cur = self.__root cur = self.__root
# 循环查找,越过叶点后跳出 # 循环查找,越过叶点后跳出
while cur is not None: while cur is not None:
# 目标点在 cur 的右子树中 # 目标点在 cur 的右子树中
if cur.val < val: if cur.val < val:
cur = cur.right cur = cur.right
# 目标点在 cur 的左子树中 # 目标点在 cur 的左子树中
elif cur.val > val: elif cur.val > val:
cur = cur.left cur = cur.left
# 找到目标点,跳出循环 # 找到目标点,跳出循环
else: else:
break break
# 返回目标 # 返回目标
return cur return cur
@ -174,19 +174,19 @@ class AVLTree:
if __name__ == "__main__": if __name__ == "__main__":
def test_insert(tree: AVLTree, val: int): def test_insert(tree: AVLTree, val: int):
tree.insert(val) tree.insert(val)
print("\n插入{}AVL 树为".format(val)) print("\n插入{}AVL 树为".format(val))
print_tree(tree.root) print_tree(tree.root)
def test_remove(tree: AVLTree, val: int): def test_remove(tree: AVLTree, val: int):
tree.remove(val) tree.remove(val)
print("\n删除{}AVL 树为".format(val)) print("\n删除{}AVL 树为".format(val))
print_tree(tree.root) print_tree(tree.root)
# 初始化空 AVL 树 # 初始化空 AVL 树
avl_tree = AVLTree() avl_tree = AVLTree()
# 插入 # 插入
# 请关注插入点后AVL 树是如何保持平衡的 # 请关注插入点后AVL 树是如何保持平衡的
test_insert(avl_tree, 1) test_insert(avl_tree, 1)
test_insert(avl_tree, 2) test_insert(avl_tree, 2)
test_insert(avl_tree, 3) test_insert(avl_tree, 3)
@ -198,14 +198,14 @@ if __name__ == "__main__":
test_insert(avl_tree, 10) test_insert(avl_tree, 10)
test_insert(avl_tree, 6) test_insert(avl_tree, 6)
# 插入重复 # 插入重复
test_insert(avl_tree, 7) test_insert(avl_tree, 7)
# 删除 # 删除
# 请关注删除点后AVL 树是如何保持平衡的 # 请关注删除点后AVL 树是如何保持平衡的
test_remove(avl_tree, 8) # 删除度为 0 的 test_remove(avl_tree, 8) # 删除度为 0 的
test_remove(avl_tree, 5) # 删除度为 1 的 test_remove(avl_tree, 5) # 删除度为 1 的
test_remove(avl_tree, 4) # 删除度为 2 的 test_remove(avl_tree, 4) # 删除度为 2 的
result_node = avl_tree.search(7) result_node = avl_tree.search(7)
print("\n查找到的结点对象为 {},结点值 = {}".format(result_node, result_node.val)) print("\n查找到的节点对象为 {},节点值 = {}".format(result_node, result_node.val))

View File

@ -21,7 +21,7 @@ class BinarySearchTree:
if start_index > end_index: if start_index > end_index:
return None return None
# 将数组中间结点作为根结 # 将数组中间节点作为根节
mid: int = (start_index + end_index) // 2 mid: int = (start_index + end_index) // 2
root = TreeNode(nums[mid]) root = TreeNode(nums[mid])
# 递归建立左子树和右子树 # 递归建立左子树和右子树
@ -34,31 +34,31 @@ class BinarySearchTree:
return self.__root return self.__root
def search(self, num: int) -> TreeNode | None: def search(self, num: int) -> TreeNode | None:
""" 查找""" """ 查找"""
cur: TreeNode | None = self.__root cur: TreeNode | None = self.__root
# 循环查找,越过叶点后跳出 # 循环查找,越过叶点后跳出
while cur is not None: while cur is not None:
# 目标点在 cur 的右子树中 # 目标点在 cur 的右子树中
if cur.val < num: if cur.val < num:
cur = cur.right cur = cur.right
# 目标点在 cur 的左子树中 # 目标点在 cur 的左子树中
elif cur.val > num: elif cur.val > num:
cur = cur.left cur = cur.left
# 找到目标点,跳出循环 # 找到目标点,跳出循环
else: else:
break break
return cur return cur
def insert(self, num: int) -> TreeNode | None: def insert(self, num: int) -> TreeNode | None:
""" 插入""" """ 插入"""
# 若树为空,直接提前返回 # 若树为空,直接提前返回
if self.__root is None: if self.__root is None:
return None return None
# 循环查找,越过叶点后跳出 # 循环查找,越过叶点后跳出
cur, pre = self.__root, None cur, pre = self.__root, None
while cur is not None: while cur is not None:
# 找到重复点,直接返回 # 找到重复点,直接返回
if cur.val == num: if cur.val == num:
return None return None
pre = cur pre = cur
@ -69,7 +69,7 @@ class BinarySearchTree:
else: else:
cur = cur.left cur = cur.left
# 插入点 val # 插入点 val
node = TreeNode(num) node = TreeNode(num)
if pre.val < num: if pre.val < num:
pre.right = node pre.right = node
@ -78,51 +78,51 @@ class BinarySearchTree:
return node return node
def remove(self, num: int) -> TreeNode | None: def remove(self, num: int) -> TreeNode | None:
""" 删除""" """ 删除"""
# 若树为空,直接提前返回 # 若树为空,直接提前返回
if self.__root is None: if self.__root is None:
return None return None
# 循环查找,越过叶点后跳出 # 循环查找,越过叶点后跳出
cur, pre = self.__root, None cur, pre = self.__root, None
while cur is not None: while cur is not None:
# 找到待删除点,跳出循环 # 找到待删除点,跳出循环
if cur.val == num: if cur.val == num:
break break
pre = cur pre = cur
if cur.val < num: # 待删除点在 cur 的右子树中 if cur.val < num: # 待删除点在 cur 的右子树中
cur = cur.right cur = cur.right
else: # 待删除点在 cur 的左子树中 else: # 待删除点在 cur 的左子树中
cur = cur.left cur = cur.left
# 若无待删除点,则直接返回 # 若无待删除点,则直接返回
if cur is None: if cur is None:
return None return None
# 子点数量 = 0 or 1 # 子点数量 = 0 or 1
if cur.left is None or cur.right is None: if cur.left is None or cur.right is None:
# 当子结点数量 = 0 / 1 时, child = null / 该子结 # 当子节点数量 = 0 / 1 时, child = null / 该子节
child = cur.left or cur.right child = cur.left or cur.right
# 删除点 cur # 删除点 cur
if pre.left == cur: if pre.left == cur:
pre.left = child pre.left = child
else: else:
pre.right = child pre.right = child
# 子点数量 = 2 # 子点数量 = 2
else: else:
# 获取中序遍历中 cur 的下一个 # 获取中序遍历中 cur 的下一个
nex: TreeNode = self.get_inorder_next(cur.right) nex: TreeNode = self.get_inorder_next(cur.right)
tmp: int = nex.val tmp: int = nex.val
# 递归删除点 nex # 递归删除点 nex
self.remove(nex.val) self.remove(nex.val)
# 将 nex 的值复制给 cur # 将 nex 的值复制给 cur
cur.val = tmp cur.val = tmp
return cur return cur
def get_inorder_next(self, root: TreeNode | None) -> TreeNode | None: def get_inorder_next(self, root: TreeNode | None) -> TreeNode | None:
""" 获取中序遍历中的下一个结点(仅适用于 root 有左子结点的情况) """ """ 获取中序遍历中的下一个节点(仅适用于 root 有左子节点的情况) """
if root is None: if root is None:
return root return root
# 循环访问左子结点,直到叶结点时为最小结点,跳出 # 循环访问左子节点,直到叶节点时为最小节点,跳出
while root.left is not None: while root.left is not None:
root = root.left root = root.left
return root return root
@ -136,24 +136,24 @@ if __name__ == "__main__":
print("\n初始化的二叉树为\n") print("\n初始化的二叉树为\n")
print_tree(bst.root) print_tree(bst.root)
# 查找 # 查找
node = bst.search(7) node = bst.search(7)
print("\n查找到的结点对象为: {},结点值 = {}".format(node, node.val)) print("\n查找到的节点对象为: {},节点值 = {}".format(node, node.val))
# 插入 # 插入
node = bst.insert(16) node = bst.insert(16)
print("\n插入点 16 后,二叉树为\n") print("\n插入点 16 后,二叉树为\n")
print_tree(bst.root) print_tree(bst.root)
# 删除 # 删除
bst.remove(1) bst.remove(1)
print("\n删除点 1 后,二叉树为\n") print("\n删除点 1 后,二叉树为\n")
print_tree(bst.root) print_tree(bst.root)
bst.remove(2) bst.remove(2)
print("\n删除点 2 后,二叉树为\n") print("\n删除点 2 后,二叉树为\n")
print_tree(bst.root) print_tree(bst.root)
bst.remove(4) bst.remove(4)
print("\n删除点 4 后,二叉树为\n") print("\n删除点 4 后,二叉树为\n")
print_tree(bst.root) print_tree(bst.root)

Some files were not shown because too many files have changed in this diff Show More