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