264 lines
6.8 KiB
C++
264 lines
6.8 KiB
C++
//
|
||
// Created by PC on 25-8-17.
|
||
//
|
||
|
||
#ifndef AVL_H
|
||
#define AVL_H
|
||
#include <iostream>
|
||
|
||
#include "TreeNode.h"
|
||
#include <iostream>
|
||
#include <deque>
|
||
template <class T>
|
||
class AVL {
|
||
private:
|
||
TreeNode<T>* root;
|
||
int totalHeight;
|
||
|
||
void insert(TreeNode<T>* &r, T element);
|
||
void erase(TreeNode<T>* &r, T element);
|
||
void inOrder(TreeNode<T>* r);
|
||
|
||
public:
|
||
//构造函数
|
||
AVL(): root(nullptr), totalHeight(0) {}
|
||
explicit AVL(TreeNode<T>* root): root(root), totalHeight(1) {}
|
||
AVL(TreeNode<T>* root, int height): root(root), totalHeight(height) {}
|
||
AVL(const AVL<T> &other) {/*深拷贝*/}
|
||
~AVL() {
|
||
dispose(root);
|
||
root = nullptr;
|
||
}
|
||
//返回
|
||
int getTotalHeight() const { return totalHeight; }
|
||
int getHeight(TreeNode<T>* node) const {
|
||
return node ? node->height : 0;
|
||
}
|
||
int getBalance(TreeNode<T>* node) const {
|
||
return getHeight(node->left) - getHeight(node->right);
|
||
}
|
||
TreeNode<T>* getRoot() { return root; }
|
||
|
||
//4种旋转,关注返回值(递归)
|
||
TreeNode<T>* LL(TreeNode<T>* &node);
|
||
TreeNode<T>* RR(TreeNode<T>* &node);
|
||
TreeNode<T>* LR(TreeNode<T>* &node);
|
||
TreeNode<T>* RL(TreeNode<T>* &node);
|
||
|
||
//中序遍历//删除节点
|
||
void display() {
|
||
std::cout << "Root is: " << root->element << std::endl;
|
||
inOrder(root);
|
||
std::cout << std::endl;
|
||
}
|
||
void dispose(TreeNode<T>* r);
|
||
|
||
//功能
|
||
void insert(T element);
|
||
void erase(T element);
|
||
void outputTree(int n);
|
||
};
|
||
|
||
template<class T>
|
||
TreeNode<T> * AVL<T>::LL(TreeNode<T> *&node) {
|
||
TreeNode<T>* left = node->left;
|
||
TreeNode<T>* right = left->right;
|
||
node->left = right;
|
||
left->right = node;
|
||
//调整高度,已更新
|
||
node->height = std::max(getHeight(node->right), getHeight(node->left)) + 1;
|
||
left->height = std::max(getHeight(left->left), getHeight(left->right)) + 1;
|
||
return left;
|
||
}
|
||
|
||
template<class T>
|
||
TreeNode<T>* AVL<T>::RR(TreeNode<T> *&node) {
|
||
TreeNode<T>* right = node->right;
|
||
TreeNode<T>* left = right->left;
|
||
right->left = node;
|
||
node->right = left;
|
||
//调整高度
|
||
node->height = std::max(getHeight(node->right), getHeight(node->left)) + 1;
|
||
right->height = std::max(getHeight(right->left), getHeight(right->right)) +1;
|
||
return right;
|
||
}
|
||
|
||
template<class T>
|
||
TreeNode<T> * AVL<T>::LR(TreeNode<T> *&node) {
|
||
node->left = RR(node->left);
|
||
node = LL(node);
|
||
//不用再调整高度,组合技
|
||
return node;
|
||
}
|
||
|
||
template<class T>
|
||
TreeNode<T> * AVL<T>::RL(TreeNode<T> *&node) {
|
||
node->right = LL(node->right);
|
||
node = RR(node);
|
||
return node;
|
||
}
|
||
|
||
template<class T>
|
||
void AVL<T>::inOrder(TreeNode<T> *r) {
|
||
if (r != nullptr) {
|
||
inOrder(r->left);
|
||
std::cout << r->element << " ";
|
||
inOrder(r->right);
|
||
}
|
||
}
|
||
|
||
template<class T>
|
||
void AVL<T>::dispose(TreeNode<T> *r) {
|
||
if (r != nullptr) {
|
||
dispose(r->left);
|
||
dispose(r->right);
|
||
delete r;
|
||
}
|
||
}
|
||
|
||
template<class T>
|
||
void AVL<T>::insert(T element) {
|
||
insert(root, element);
|
||
}
|
||
|
||
template<class T>
|
||
void AVL<T>::erase(T element) {
|
||
erase(root, element);
|
||
}
|
||
|
||
//n是输入的max
|
||
template<class T>
|
||
void AVL<T>::outputTree(int n) {
|
||
int index = 0;
|
||
std::deque<TreeNode<T> *> q;
|
||
q.push_back(root);
|
||
while (true) {
|
||
if (q[index] != nullptr && q[index]->element == n) {break;}
|
||
if (q[index]->left) q.push_back(q[index]->left);
|
||
if (q[index]->right) q.push_back(q[index]->right);
|
||
index++;
|
||
}
|
||
int cnt = 1;
|
||
int jmp = 1;
|
||
for (int i = 0; i <= index; i++) {
|
||
cnt--;
|
||
q[i] != nullptr ? std::cout << q[i]->element << " " : std::cout << "-1" << " ";
|
||
if (cnt == 0) {
|
||
jmp *= 2;
|
||
cnt = jmp;
|
||
std::cout << std::endl;
|
||
}
|
||
}
|
||
std::cout << std::endl;
|
||
}
|
||
|
||
template<class T>
|
||
void AVL<T>::insert(TreeNode<T>* &r, T element) {
|
||
//BST插入
|
||
if (r == nullptr) {
|
||
r = new TreeNode<T>(element);
|
||
return ;
|
||
}
|
||
|
||
if (element < r->element) {
|
||
insert(r->left, element);
|
||
}
|
||
else if (element > r->element) {
|
||
insert(r->right, element);
|
||
}
|
||
//更新高度,注意在回溯的时候,已经更新了每个父节点的height,不需要再调整(中序遍历一遍)
|
||
r->height = std::max(getHeight(r->left), getHeight(r->right)) + 1;
|
||
|
||
//旋转-关注四个条件
|
||
int balance = getBalance(r);
|
||
|
||
if (balance > 1 && element < r->left->element) {
|
||
//LL
|
||
r = LL(r);
|
||
}
|
||
else if (balance < -1 && element > r->right->element) {
|
||
//RR
|
||
r = RR(r);
|
||
}
|
||
else if (balance > 1 && element > r->left->element) {
|
||
//LR
|
||
r->left = RR(r->left);
|
||
r = LL(r);
|
||
}
|
||
else if (balance < -1 && element < r->right->element) {
|
||
//RL
|
||
r->right = LL(r->right);
|
||
r = RR(r);
|
||
}
|
||
}
|
||
|
||
template<class T>
|
||
void AVL<T>::erase(TreeNode<T> *&r, T element) {
|
||
/*
|
||
先按照二叉搜索树的规则删除节点:若删除节点没有孩子 → 直接删除 。
|
||
若只有一个孩子 → 让孩子接替它 。
|
||
若有两个孩子 → 找 中序后继(右子树最小) 或 中序前驱(左子树最大),替换值,再递归删除.
|
||
*/
|
||
if (r == nullptr) {
|
||
return;
|
||
}
|
||
TreeNode<T> *tmp = r;
|
||
if (element < r->element) {
|
||
erase(r->left, element);
|
||
}
|
||
else if (element > r->element) {
|
||
erase(r->right, element);
|
||
}
|
||
else {
|
||
//p = 0 or 1
|
||
if (r->left == nullptr || r->right == nullptr) {
|
||
tmp = r->left ? r->left : r->right;
|
||
if (!tmp) {
|
||
tmp = r;
|
||
r = nullptr;
|
||
}
|
||
else {
|
||
*r = *tmp;
|
||
}
|
||
delete tmp;
|
||
}
|
||
//p = 2
|
||
else if (r->left != nullptr && r->right != nullptr) {
|
||
//right-min或left-max,提到最上
|
||
TreeNode<T> *min = r->right;
|
||
while (min->left != nullptr) {
|
||
min = min->left;
|
||
}
|
||
r->element = min->element;
|
||
erase(r->right, min->element);
|
||
}
|
||
}
|
||
if (!r) return;
|
||
|
||
//这里再对每个节点进行操作,旋转;回溯的时候会将父/祖父节点都旋转
|
||
//更新高度
|
||
r->height = std::max(getHeight(r->left), getHeight(r->right)) + 1;
|
||
//检查左右孩子
|
||
int balance = getBalance(r);
|
||
//关注和insert的区别
|
||
if (balance > 1 && getBalance(r->left) >= 0) {
|
||
//LL
|
||
r = LL(r);
|
||
}
|
||
else if (balance < -1 && getBalance(r->right) <= 0) {
|
||
//RR
|
||
r = RR(r);
|
||
}
|
||
else if (balance > 1 && getBalance(r->left) < 0) {
|
||
//LR
|
||
r->left = RR(r->left);
|
||
r = LL(r);
|
||
}
|
||
else if (balance < -1 && getBalance(r->right) > 0) {
|
||
//RL
|
||
r->right = LL(r->right);
|
||
r = RR(r);
|
||
}
|
||
}
|
||
#endif //AVL_H
|