This commit is contained in:
krahets
2023-04-14 04:01:38 +08:00
parent cf431646e9
commit 4d318e8e6b
26 changed files with 469 additions and 295 deletions
+33 -28
View File
@@ -177,13 +177,13 @@ G. M. Adelson-Velsky 和 E. M. Landis 在其 1962 年发表的论文 "An algorit
```cpp title="avl_tree.cpp"
/* 获取节点高度 */
int height(TreeNode* node) {
int height(TreeNode *node) {
// 空节点高度为 -1 ,叶节点高度为 0
return node == nullptr ? -1 : node->height;
}
/* 更新节点高度 */
void updateHeight(TreeNode* node) {
void updateHeight(TreeNode *node) {
// 节点高度等于最高子树高度 + 1
node->height = max(height(node->left), height(node->right)) + 1;
}
@@ -331,7 +331,8 @@ G. M. Adelson-Velsky 和 E. M. Landis 在其 1962 年发表的论文 "An algorit
/* 获取平衡因子 */
int balanceFactor(TreeNode node) {
// 空节点平衡因子为 0
if (node == null) return 0;
if (node == null)
return 0;
// 节点平衡因子 = 左子树高度 - 右子树高度
return height(node.left) - height(node.right);
}
@@ -341,9 +342,10 @@ G. M. Adelson-Velsky 和 E. M. Landis 在其 1962 年发表的论文 "An algorit
```cpp title="avl_tree.cpp"
/* 获取平衡因子 */
int balanceFactor(TreeNode* node) {
int balanceFactor(TreeNode *node) {
// 空节点平衡因子为 0
if (node == nullptr) return 0;
if (node == nullptr)
return 0;
// 节点平衡因子 = 左子树高度 - 右子树高度
return height(node->left) - height(node->right);
}
@@ -498,9 +500,9 @@ AVL 树的特点在于「旋转 Rotation」操作,它能够在不影响二叉
```cpp title="avl_tree.cpp"
/* 右旋操作 */
TreeNode* rightRotate(TreeNode* node) {
TreeNode* child = node->left;
TreeNode* grandChild = child->right;
TreeNode *rightRotate(TreeNode *node) {
TreeNode *child = node->left;
TreeNode *grandChild = child->right;
// 以 child 为原点,将 node 向右旋转
child->right = node;
node->left = grandChild;
@@ -682,9 +684,9 @@ AVL 树的特点在于「旋转 Rotation」操作,它能够在不影响二叉
```cpp title="avl_tree.cpp"
/* 左旋操作 */
TreeNode* leftRotate(TreeNode* node) {
TreeNode* child = node->right;
TreeNode* grandChild = child->left;
TreeNode *leftRotate(TreeNode *node) {
TreeNode *child = node->right;
TreeNode *grandChild = child->left;
// 以 child 为原点,将 node 向左旋转
child->left = node;
node->right = grandChild;
@@ -905,7 +907,7 @@ AVL 树的特点在于「旋转 Rotation」操作,它能够在不影响二叉
```cpp title="avl_tree.cpp"
/* 执行旋转操作,使该子树重新恢复平衡 */
TreeNode* rotate(TreeNode* node) {
TreeNode *rotate(TreeNode *node) {
// 获取节点 node 的平衡因子
int _balanceFactor = balanceFactor(node);
// 左偏树
@@ -1201,15 +1203,16 @@ AVL 树的特点在于「旋转 Rotation」操作,它能够在不影响二叉
/* 递归插入节点(辅助方法) */
TreeNode insertHelper(TreeNode node, int val) {
if (node == null) return new TreeNode(val);
if (node == null)
return new TreeNode(val);
/* 1. 查找插入位置,并插入节点 */
if (val < node.val)
node.left = insertHelper(node.left, val);
else if (val > node.val)
node.right = insertHelper(node.right, val);
else
return node; // 重复节点不插入,直接返回
updateHeight(node); // 更新节点高度
return node; // 重复节点不插入,直接返回
updateHeight(node); // 更新节点高度
/* 2. 执行旋转操作,使该子树重新恢复平衡 */
node = rotate(node);
// 返回子树的根节点
@@ -1221,13 +1224,13 @@ AVL 树的特点在于「旋转 Rotation」操作,它能够在不影响二叉
```cpp title="avl_tree.cpp"
/* 插入节点 */
TreeNode* insert(int val) {
TreeNode *insert(int val) {
root = insertHelper(root, val);
return root;
}
/* 递归插入节点(辅助方法) */
TreeNode* insertHelper(TreeNode* node, int val) {
TreeNode *insertHelper(TreeNode *node, int val) {
if (node == nullptr)
return new TreeNode(val);
/* 1. 查找插入位置,并插入节点 */
@@ -1236,8 +1239,8 @@ AVL 树的特点在于「旋转 Rotation」操作,它能够在不影响二叉
else if (val > node->val)
node->right = insertHelper(node->right, val);
else
return node; // 重复节点不插入,直接返回
updateHeight(node); // 更新节点高度
return node; // 重复节点不插入,直接返回
updateHeight(node); // 更新节点高度
/* 2. 执行旋转操作,使该子树重新恢复平衡 */
node = rotate(node);
// 返回子树的根节点
@@ -1472,7 +1475,8 @@ AVL 树的特点在于「旋转 Rotation」操作,它能够在不影响二叉
/* 递归删除节点(辅助方法) */
TreeNode removeHelper(TreeNode node, int val) {
if (node == null) return null;
if (node == null)
return null;
/* 1. 查找节点,并删除之 */
if (val < node.val)
node.left = removeHelper(node.left, val);
@@ -1494,7 +1498,7 @@ AVL 树的特点在于「旋转 Rotation」操作,它能够在不影响二叉
node.val = temp.val;
}
}
updateHeight(node); // 更新节点高度
updateHeight(node); // 更新节点高度
/* 2. 执行旋转操作,使该子树重新恢复平衡 */
node = rotate(node);
// 返回子树的根节点
@@ -1503,7 +1507,8 @@ AVL 树的特点在于「旋转 Rotation」操作,它能够在不影响二叉
/* 获取中序遍历中的下一个节点(仅适用于 root 有左子节点的情况) */
TreeNode getInOrderNext(TreeNode node) {
if (node == null) return node;
if (node == null)
return node;
// 循环访问左子节点,直到叶节点时为最小节点,跳出
while (node.left != null) {
node = node.left;
@@ -1516,13 +1521,13 @@ AVL 树的特点在于「旋转 Rotation」操作,它能够在不影响二叉
```cpp title="avl_tree.cpp"
/* 删除节点 */
TreeNode* remove(int val) {
TreeNode *remove(int val) {
root = removeHelper(root, val);
return root;
}
/* 递归删除节点(辅助方法) */
TreeNode* removeHelper(TreeNode* node, int val) {
TreeNode *removeHelper(TreeNode *node, int val) {
if (node == nullptr)
return nullptr;
/* 1. 查找节点,并删除之 */
@@ -1532,7 +1537,7 @@ AVL 树的特点在于「旋转 Rotation」操作,它能够在不影响二叉
node->right = removeHelper(node->right, val);
else {
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 并返回
if (child == nullptr) {
delete node;
@@ -1545,13 +1550,13 @@ AVL 树的特点在于「旋转 Rotation」操作,它能够在不影响二叉
}
} else {
// 子节点数量 = 2 ,则将中序遍历的下个节点删除,并用该节点替换当前节点
TreeNode* temp = getInOrderNext(node->right);
TreeNode *temp = getInOrderNext(node->right);
int tempVal = temp->val;
node->right = removeHelper(node->right, temp->val);
node->val = tempVal;
}
}
updateHeight(node); // 更新节点高度
updateHeight(node); // 更新节点高度
/* 2. 执行旋转操作,使该子树重新恢复平衡 */
node = rotate(node);
// 返回子树的根节点
@@ -1559,7 +1564,7 @@ AVL 树的特点在于「旋转 Rotation」操作,它能够在不影响二叉
}
/* 获取中序遍历中的下一个节点(仅适用于 root 有左子节点的情况) */
TreeNode* getInOrderNext(TreeNode* node) {
TreeNode *getInOrderNext(TreeNode *node) {
if (node == nullptr)
return node;
// 循环访问左子节点,直到叶节点时为最小节点,跳出