cpp-algo-cases/chapter_tree/avl_tree.cpp

234 lines
6.5 KiB
C++
Raw Normal View History

2024-02-20 16:13:23 +08:00
/**
* File: avl_tree.cpp
* Created Time: 2023-02-03
* Author: what-is-me (whatisme@outlook.jp)
*/
#include "../utils/common.hpp"
/* AVL <20><> */
class AVLTree {
public:
TreeNode *root; // <20><><EFBFBD>ڵ<EFBFBD>
private:
/* <20><><EFBFBD>½ڵ<C2BD><DAB5>߶<EFBFBD> */
void updateHeight(TreeNode *node) {
// <20>ڵ<EFBFBD><DAB5>߶ȵ<DFB6><C8B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>߶<EFBFBD> + 1
node->height = max(height(node->left), height(node->right)) + 1;
}
/* <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> */
TreeNode *rightRotate(TreeNode *node) {
TreeNode *child = node->left;
TreeNode *grandChild = child->right;
// <20><> child Ϊԭ<CEAA><EFBFBD><E3A3AC> node <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ת
child->right = node;
node->left = grandChild;
// <20><><EFBFBD>½ڵ<C2BD><DAB5>߶<EFBFBD>
updateHeight(node);
updateHeight(child);
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ת<EFBFBD><D7AA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ĸ<EFBFBD><C4B8>ڵ<EFBFBD>
return child;
}
/* <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> */
TreeNode *leftRotate(TreeNode *node) {
TreeNode *child = node->right;
TreeNode *grandChild = child->left;
// <20><> child Ϊԭ<CEAA><EFBFBD><E3A3AC> node <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ת
child->left = node;
node->right = grandChild;
// <20><><EFBFBD>½ڵ<C2BD><DAB5>߶<EFBFBD>
updateHeight(node);
updateHeight(child);
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ת<EFBFBD><D7AA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ĸ<EFBFBD><C4B8>ڵ<EFBFBD>
return child;
}
/* ִ<><D6B4><EFBFBD><EFBFBD>ת<EFBFBD><D7AA><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD><CAB9><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>»ָ<C2BB>ƽ<EFBFBD><C6BD> */
TreeNode *rotate(TreeNode *node) {
// <20><>ȡ<EFBFBD>ڵ<EFBFBD> node <20><>ƽ<EFBFBD><C6BD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
int _balanceFactor = balanceFactor(node);
// <20><>ƫ<EFBFBD><C6AB>
if (_balanceFactor > 1) {
if (balanceFactor(node->left) >= 0) {
// <20><><EFBFBD><EFBFBD>
return rightRotate(node);
} else {
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
node->left = leftRotate(node->left);
return rightRotate(node);
}
}
// <20><>ƫ<EFBFBD><C6AB>
if (_balanceFactor < -1) {
if (balanceFactor(node->right) <= 0) {
// <20><><EFBFBD><EFBFBD>
return leftRotate(node);
} else {
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
node->right = rightRotate(node->right);
return leftRotate(node);
}
}
// ƽ<><C6BD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ת<EFBFBD><D7AA>ֱ<EFBFBD>ӷ<EFBFBD><D3B7><EFBFBD>
return node;
}
/* <20>ݹ<EFBFBD><DDB9><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڵ㣨<DAB5><E3A3A8><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> */
TreeNode *insertHelper(TreeNode *node, int val) {
if (node == nullptr)
return new TreeNode(val);
/* 1. <20><><EFBFBD>Ҳ<EFBFBD><D2B2><EFBFBD>λ<EFBFBD>ò<EFBFBD><C3B2><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڵ<EFBFBD> */
if (val < node->val)
node->left = insertHelper(node->left, val);
else if (val > node->val)
node->right = insertHelper(node->right, val);
else
return node; // <20>ظ<EFBFBD><D8B8>ڵ㲻<DAB5><E3B2BB><EFBFBD>룬ֱ<EBA3AC>ӷ<EFBFBD><D3B7><EFBFBD>
updateHeight(node); // <20><><EFBFBD>½ڵ<C2BD><DAB5>߶<EFBFBD>
/* 2. ִ<><D6B4><EFBFBD><EFBFBD>ת<EFBFBD><D7AA><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD><CAB9><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>»ָ<C2BB>ƽ<EFBFBD><C6BD> */
node = rotate(node);
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ĸ<EFBFBD><C4B8>ڵ<EFBFBD>
return node;
}
/* <20>ݹ<EFBFBD>ɾ<EFBFBD><C9BE><EFBFBD>ڵ㣨<DAB5><E3A3A8><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> */
TreeNode *removeHelper(TreeNode *node, int val) {
if (node == nullptr)
return nullptr;
/* 1. <20><><EFBFBD>ҽڵ㲢ɾ<E3B2A2><C9BE> */
if (val < node->val)
node->left = removeHelper(node->left, val);
else if (val > node->val)
node->right = removeHelper(node->right, val);
else {
if (node->left == nullptr || node->right == nullptr) {
TreeNode *child = node->left != nullptr ? node->left : node->right;
// <20>ӽڵ<D3BD><DAB5><EFBFBD><EFBFBD><EFBFBD> = 0 <20><>ֱ<EFBFBD><D6B1>ɾ<EFBFBD><C9BE> node <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
if (child == nullptr) {
delete node;
return nullptr;
}
// <20>ӽڵ<D3BD><DAB5><EFBFBD><EFBFBD><EFBFBD> = 1 <20><>ֱ<EFBFBD><D6B1>ɾ<EFBFBD><C9BE> node
else {
delete node;
node = child;
}
} else {
// <20>ӽڵ<D3BD><DAB5><EFBFBD><EFBFBD><EFBFBD> = 2 <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>¸<EFBFBD><C2B8>ڵ<EFBFBD>ɾ<EFBFBD><C9BE><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>øýڵ<C3BD><DAB5><EFBFBD><E6BBBB>ǰ<EFBFBD>ڵ<EFBFBD>
TreeNode *temp = node->right;
while (temp->left != nullptr) {
temp = temp->left;
}
int tempVal = temp->val;
node->right = removeHelper(node->right, temp->val);
node->val = tempVal;
}
}
updateHeight(node); // <20><><EFBFBD>½ڵ<C2BD><DAB5>߶<EFBFBD>
/* 2. ִ<><D6B4><EFBFBD><EFBFBD>ת<EFBFBD><D7AA><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD><CAB9><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>»ָ<C2BB>ƽ<EFBFBD><C6BD> */
node = rotate(node);
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ĸ<EFBFBD><C4B8>ڵ<EFBFBD>
return node;
}
public:
/* <20><>ȡ<EFBFBD>ڵ<EFBFBD><DAB5>߶<EFBFBD> */
int height(TreeNode *node) {
// <20>սڵ<D5BD><DAB5>߶<EFBFBD>Ϊ -1 <20><>Ҷ<EFBFBD>ڵ<EFBFBD><DAB5>߶<EFBFBD>Ϊ 0
return node == nullptr ? -1 : node->height;
}
/* <20><>ȡƽ<C8A1><C6BD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> */
int balanceFactor(TreeNode *node) {
// <20>սڵ<D5BD>ƽ<EFBFBD><C6BD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ 0
if (node == nullptr)
return 0;
// <20>ڵ<EFBFBD>ƽ<EFBFBD><C6BD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> = <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>߶<EFBFBD> - <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>߶<EFBFBD>
return height(node->left) - height(node->right);
}
/* <20><><EFBFBD><EFBFBD><EFBFBD>ڵ<EFBFBD> */
void insert(int val) {
root = insertHelper(root, val);
}
/* ɾ<><C9BE><EFBFBD>ڵ<EFBFBD> */
void remove(int val) {
root = removeHelper(root, val);
}
/* <20><><EFBFBD>ҽڵ<D2BD> */
TreeNode *search(int val) {
TreeNode *cur = root;
// ѭ<><D1AD><EFBFBD><EFBFBD><EFBFBD>ң<EFBFBD>Խ<EFBFBD><D4BD>Ҷ<EFBFBD>ڵ<EFBFBD><DAB5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
while (cur != nullptr) {
// Ŀ<><C4BF><EFBFBD>ڵ<EFBFBD><DAB5><EFBFBD> cur <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
if (cur->val < val)
cur = cur->right;
// Ŀ<><C4BF><EFBFBD>ڵ<EFBFBD><DAB5><EFBFBD> cur <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
else if (cur->val > val)
cur = cur->left;
// <20>ҵ<EFBFBD>Ŀ<EFBFBD><C4BF><EFBFBD>ڵ㣬<DAB5><E3A3AC><EFBFBD><EFBFBD>ѭ<EFBFBD><D1AD>
else
break;
}
// <20><><EFBFBD><EFBFBD>Ŀ<EFBFBD><C4BF><EFBFBD>ڵ<EFBFBD>
return cur;
}
/*<2A><><EFBFBD><EFBFBD><ECB7BD>*/
AVLTree() : root(nullptr) {
}
/*<2A><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>*/
~AVLTree() {
freeMemoryTree(root);
}
};
void testInsert(AVLTree &tree, int val) {
tree.insert(val);
cout << "\n<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڵ<EFBFBD> " << val << " <20><><EFBFBD><EFBFBD>AVL <20><>Ϊ" << endl;
printTree(tree.root);
}
void testRemove(AVLTree &tree, int val) {
tree.remove(val);
cout << "\nɾ<EFBFBD><EFBFBD><EFBFBD>ڵ<EFBFBD> " << val << " <20><><EFBFBD><EFBFBD>AVL <20><>Ϊ" << endl;
printTree(tree.root);
}
/* Driver Code */
int main() {
/* <20><>ʼ<EFBFBD><CABC><EFBFBD><EFBFBD> AVL <20><> */
AVLTree avlTree;
/* <20><><EFBFBD><EFBFBD><EFBFBD>ڵ<EFBFBD> */
// <20><><EFBFBD><EFBFBD>ע<EFBFBD><D7A2><EFBFBD><EFBFBD><EFBFBD>ڵ<EFBFBD><DAB5><EFBFBD><EFBFBD><EFBFBD>AVL <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>α<EFBFBD><CEB1><EFBFBD>ƽ<EFBFBD><C6BD><EFBFBD><EFBFBD>
testInsert(avlTree, 1);
testInsert(avlTree, 2);
testInsert(avlTree, 3);
testInsert(avlTree, 4);
testInsert(avlTree, 5);
testInsert(avlTree, 8);
testInsert(avlTree, 7);
testInsert(avlTree, 9);
testInsert(avlTree, 10);
testInsert(avlTree, 6);
/* <20><><EFBFBD><EFBFBD><EFBFBD>ظ<EFBFBD><D8B8>ڵ<EFBFBD> */
testInsert(avlTree, 7);
/* ɾ<><C9BE><EFBFBD>ڵ<EFBFBD> */
// <20><><EFBFBD><EFBFBD>עɾ<D7A2><C9BE><EFBFBD>ڵ<EFBFBD><DAB5><EFBFBD><EFBFBD><EFBFBD>AVL <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>α<EFBFBD><CEB1><EFBFBD>ƽ<EFBFBD><C6BD><EFBFBD><EFBFBD>
testRemove(avlTree, 8); // ɾ<><C9BE><EFBFBD><EFBFBD>Ϊ 0 <20>Ľڵ<C4BD>
testRemove(avlTree, 5); // ɾ<><C9BE><EFBFBD><EFBFBD>Ϊ 1 <20>Ľڵ<C4BD>
testRemove(avlTree, 4); // ɾ<><C9BE><EFBFBD><EFBFBD>Ϊ 2 <20>Ľڵ<C4BD>
/* <20><>ѯ<EFBFBD>ڵ<EFBFBD> */
TreeNode *node = avlTree.search(7);
cout << "\n<EFBFBD><EFBFBD><EFBFBD>ҵ<EFBFBD><EFBFBD>Ľڵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ " << node << "<EFBFBD><EFBFBD><EFBFBD>ڵ<EFBFBD>ֵ = " << node->val << endl;
}