实现AVL树的构建、插入结点、删除结点、AVL树的销毁等操作,已通过100条样例测试。
代码如下:
#include <algorithm>
#include <cstdio>
#include <iostream>
#include <string>
template <typename T>
struct AVLTreeNode {
AVLTreeNode(T value, AVLTreeNode<T>* l = nullptr, AVLTreeNode<T>* r = nullptr)
: key(value), lchild(l), rchild(r) {}
T key;
int height;
AVLTreeNode<T>* lchild;
AVLTreeNode<T>* rchild;
};
template <typename T>
class AVLTree {
public:
AVLTree() = default;
~AVLTree() { destory(root); }
void print(const std::string& op) {
if (!root) {
std::cout << "EMPTY" << std::endl;
return;
}
if (op == "PRE") {
preOrder(root);
} else if (op == "IN") {
InOrder(root);
} else if (op == "POST") {
postOrder(root);
}
std::cout << std::endl;
}
void insert(T key) { root = insert(root, key); }
void remove(T key) { root = remove(root, key); }
private:
AVLTreeNode<T>* insert(AVLTreeNode<T>* subRoot, T k) {
if (subRoot == nullptr) {
return new AVLTreeNode<T>(k);
}
if (subRoot->key == k) {
return subRoot;
}
if (k >= subRoot->key) {
subRoot->rchild = insert(subRoot->rchild, k);
} else {
subRoot->lchild = insert(subRoot->lchild, k);
}
subRoot = balance(subRoot);
return subRoot;
}
AVLTreeNode<T>* remove(AVLTreeNode<T>* subRoot, T k) {
if (subRoot == nullptr) {
return nullptr;
}
if (subRoot->key == k) {
if (subRoot->lchild == nullptr && subRoot->rchild == nullptr) {
delete subRoot;
return nullptr;
} else if (subRoot->lchild == nullptr) {
AVLTreeNode<T>* temp = subRoot->rchild;
delete subRoot;
return temp;
} else if (subRoot->rchild == nullptr) {
AVLTreeNode<T>* temp = subRoot->lchild;
delete subRoot;
return temp;
} else {
AVLTreeNode<T>* maxNode = treeMax(subRoot->lchild);
T temp = subRoot->key;
subRoot->key = maxNode->key;
maxNode->key = temp;
subRoot->lchild = remove(subRoot->lchild, k);
}
} else if (subRoot->key < k) {
subRoot->rchild = remove(subRoot->rchild, k);
} else {
subRoot->lchild = remove(subRoot->lchild, k);
}
subRoot = balance(subRoot);
return subRoot;
}
AVLTreeNode<T>* search(T k) {
AVLTreeNode<T>* p = root;
while (p) {
if (p->key == k) {
break;
} else if (p->key < k) {
p = p->lchild;
} else {
p = p->rchild;
}
}
return p;
}
AVLTreeNode<T>* treeMax(AVLTreeNode<T>* subTree) {
if (subTree == nullptr) {
return nullptr;
}
while (subTree->rchild) {
subTree = subTree->rchild;
}
return subTree;
}
AVLTreeNode<T>* treeMin(AVLTreeNode<T>* subTree) {
if (subTree == nullptr) {
return nullptr;
}
while (subTree->lchild) {
subTree = subTree->lchild;
}
return subTree;
}
AVLTreeNode<T>* llRotation(AVLTreeNode<T>* subRoot) {
AVLTreeNode<T>* temp = subRoot->lchild;
subRoot->lchild = temp->rchild;
temp->rchild = subRoot;
return temp;
}
AVLTreeNode<T>* rrRotation(AVLTreeNode<T>* subRoot) {
AVLTreeNode<T>* temp = subRoot->rchild;
subRoot->rchild = temp->lchild;
temp->lchild = subRoot;
return temp;
}
AVLTreeNode<T>* rlRotation(AVLTreeNode<T>* subRoot) {
subRoot->rchild = llRotation(subRoot->rchild);
return rrRotation(subRoot);
}
AVLTreeNode<T>* lrRotation(AVLTreeNode<T>* subRoot) {
subRoot->lchild = rrRotation(subRoot->lchild);
return llRotation(subRoot);
}
int height(AVLTreeNode<T>* pnode) {
if (pnode == nullptr) {
return 0;
}
int l = height(pnode->lchild);
int r = height(pnode->rchild);
return std::max(l, r) + 1;
}
int balanceFactor(AVLTreeNode<T>* p) {
return height(p->lchild) - height(p->rchild);
}
AVLTreeNode<T>* balance(AVLTreeNode<T>* subRoot) {
int bf = balanceFactor(subRoot);
if (bf > 1) {
if (balanceFactor(subRoot->lchild) == 0) {
subRoot = llRotation(subRoot);
} else if (balanceFactor(subRoot->lchild) > 0) {
subRoot = llRotation(subRoot);
} else {
subRoot = lrRotation(subRoot);
}
} else if (bf < -1) {
if (balanceFactor(subRoot->rchild) == 0) {
subRoot = rrRotation(subRoot);
} else if (balanceFactor(subRoot->rchild) > 0) {
subRoot = rlRotation(subRoot);
} else {
subRoot = rrRotation(subRoot);
}
}
return subRoot;
}
void preOrder(AVLTreeNode<T>* p) {
if (p == nullptr) {
return;
}
std::cout << p->key << " ";
preOrder(p->lchild);
preOrder(p->rchild);
}
void InOrder(AVLTreeNode<T>* p) {
if (p == nullptr) {
return;
}
InOrder(p->lchild);
std::cout << p->key << " ";
InOrder(p->rchild);
}
void postOrder(AVLTreeNode<T>* p) {
if (p == nullptr) {
return;
}
postOrder(p->lchild);
postOrder(p->rchild);
std::cout << p->key << " ";
}
void destory(AVLTreeNode<T>* p) {
if (p == nullptr) {
return;
}
destory(p->lchild);
destory(p->rchild);
delete p;
}
AVLTreeNode<T>* root{nullptr};
};
上面是实现的AVL类,下面可以对其进行测试,输入输出格式描述如下:
1. 输入格式:
输入是n个用空格分隔的字符串,前n-1个字符串的格式描述如下:
- Aint(字符A后面跟一个int类型的数字,例如A3)表示将int类型的数插入到AVL树中,A3表示将3插入到AVL树中,如果3已经在树中,则直接返回,不会插入一个相同的数字。
- Dint(字符D后面跟一个int类型的数字,例如D3)表示将int类型的数从AVL树中删除,D3表示从AVL树中删除,如果3不在AVL树中,则直接返回。
第n个字符串有三种类型:PRE、IN、POST,分别代表最后AVL树以什么顺序输出。
2. 输出格式
输出按照输入说明的输出格式打印AVL树,如果AVL树是空,打印EMPTY。
例如:
# 对于输入:
A1 A2 A3 IN
# 输出:
1 2 3
# 对于输入:
A1 A2 A3 PRE
# 输出
2 1 3
# 对于输入
A1 D1 POST
# 输出
EMPTY
下面是测试代码:
int main() {
std::string op;
AVLTree<int> tree;
while (std::cin >> op) {
if (op == "IN" || op == "PRE" || op == "POST") {
tree.print(op);
break;
}
if (op[0] == 'A') {
tree.insert(std::stoi(op.substr(1)));
} else if (op[0] == 'D') {
tree.remove(std::stoi(op.substr(1)));
}
}
return 0;
}