234 lines
6.5 KiB
C++
234 lines
6.5 KiB
C++
|
/**
|
|||
|
* 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;
|
|||
|
}
|