HolyAVLTree
This commit is contained in:
6
BinaryTree/BalanceTree/AVLTree/CMakeLists.txt
Normal file
6
BinaryTree/BalanceTree/AVLTree/CMakeLists.txt
Normal file
@@ -0,0 +1,6 @@
|
||||
cmake_minimum_required(VERSION 3.31)
|
||||
project(AVLTree)
|
||||
|
||||
set(CMAKE_CXX_STANDARD 20)
|
||||
|
||||
add_executable(AVLTree main.cpp)
|
BIN
BinaryTree/BalanceTree/AVLTree/OutputLogic.pdf
Normal file
BIN
BinaryTree/BalanceTree/AVLTree/OutputLogic.pdf
Normal file
Binary file not shown.
@@ -1,2 +1,4 @@
|
||||
# 旋转的本质:不能改变BST的属性
|
||||
左旋,是指把本节点移动到本节点右节点的左节点上; 右旋,是指把本节点移动到本节点左节点的右节点上
|
||||
LR的情况:先把LR的左节点左旋,形成LL,然后再按照LL的方式处理
|
||||
RL同理
|
263
BinaryTree/BalanceTree/AVLTree/avl.h
Normal file
263
BinaryTree/BalanceTree/AVLTree/avl.h
Normal file
@@ -0,0 +1,263 @@
|
||||
//
|
||||
// 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
|
97
BinaryTree/BalanceTree/AVLTree/main.cpp
Normal file
97
BinaryTree/BalanceTree/AVLTree/main.cpp
Normal file
@@ -0,0 +1,97 @@
|
||||
#include <iostream>
|
||||
#include "avl.h"
|
||||
using namespace std;
|
||||
int main() {
|
||||
AVL<int> tree;
|
||||
tree.insert(10);
|
||||
tree.display();
|
||||
tree.outputTree(10);
|
||||
tree.insert(20);
|
||||
tree.display();
|
||||
tree.outputTree(20);
|
||||
tree.insert(30);
|
||||
tree.display();
|
||||
tree.outputTree(30);
|
||||
tree.insert(100);
|
||||
tree.display();
|
||||
tree.outputTree(100);
|
||||
tree.insert(50);
|
||||
tree.display();
|
||||
tree.outputTree(50);
|
||||
tree.insert(70);
|
||||
tree.display();
|
||||
tree.outputTree(70);
|
||||
tree.insert(80);
|
||||
tree.display();
|
||||
tree.outputTree(80);
|
||||
tree.insert(60);
|
||||
tree.display();
|
||||
tree.outputTree(60);
|
||||
cout << endl << endl << endl;
|
||||
cout << "To erase: " << endl;
|
||||
tree.erase(60);
|
||||
tree.display();
|
||||
tree.outputTree(100);
|
||||
tree.erase(100);
|
||||
tree.display();
|
||||
tree.outputTree(80);
|
||||
|
||||
return 0;
|
||||
}
|
||||
/*
|
||||
OutputTree写的不好
|
||||
Root is: 10
|
||||
10
|
||||
10
|
||||
|
||||
Root is: 10
|
||||
10 20
|
||||
10
|
||||
20
|
||||
|
||||
Root is: 20
|
||||
10 20 30
|
||||
20
|
||||
10 30
|
||||
|
||||
Root is: 20
|
||||
10 20 30 100
|
||||
20
|
||||
10 30
|
||||
100
|
||||
|
||||
Root is: 20
|
||||
10 20 30 50 100
|
||||
20
|
||||
10 50
|
||||
|
||||
Root is: 50
|
||||
10 20 30 50 70 100
|
||||
50
|
||||
20 100
|
||||
10 30 70
|
||||
|
||||
Root is: 50
|
||||
10 20 30 50 70 80 100
|
||||
50
|
||||
20 80
|
||||
|
||||
Root is: 50
|
||||
10 20 30 50 60 70 80 100
|
||||
50
|
||||
20 80
|
||||
10 30 70 100
|
||||
60
|
||||
|
||||
To erase:
|
||||
Root is: 50
|
||||
10 20 30 50 70 80 100
|
||||
50
|
||||
20 80
|
||||
10 30 70 100
|
||||
|
||||
Root is: 50
|
||||
10 20 30 50 70 80
|
||||
50
|
||||
20 80
|
||||
*/
|
38
BinaryTree/BalanceTree/AVLTree/treenode.h
Normal file
38
BinaryTree/BalanceTree/AVLTree/treenode.h
Normal file
@@ -0,0 +1,38 @@
|
||||
//
|
||||
// Created by PC on 25-8-17.
|
||||
//
|
||||
|
||||
#ifndef TREENODE_H
|
||||
#define TREENODE_H
|
||||
template<class T>
|
||||
class TreeNode {
|
||||
public:
|
||||
T element;
|
||||
TreeNode<T>* left;
|
||||
TreeNode<T>* right;
|
||||
int height;
|
||||
|
||||
TreeNode(): left(nullptr), right(nullptr), height(0) {}
|
||||
explicit TreeNode(T e): element(e), left(nullptr), right(nullptr), height(1) {}
|
||||
TreeNode(T e, TreeNode<T>* l, TreeNode<T>* r): element(e), left(l), right(r), height(1) {}
|
||||
};
|
||||
|
||||
#endif //TREENODE_H
|
||||
/*
|
||||
30
|
||||
/ \
|
||||
25 35
|
||||
/ \
|
||||
20 32
|
||||
/
|
||||
5
|
||||
|
||||
旋转之后应该是:
|
||||
1
|
||||
/ \
|
||||
r 4
|
||||
/ \
|
||||
3 2
|
||||
/
|
||||
5
|
||||
*/
|
Reference in New Issue
Block a user