Files
Data-Structure/BinaryTree/BalanceTree/AVLTree/avl.h
2025-08-19 18:01:45 +08:00

264 lines
6.8 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//
// 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