• AVL 二叉平衡树 C++ 实现


    头文件

    #ifndef DEBUG_LRN_AVL_H
    #define DEBUG_LRN_AVL_H
    
    #include <iostream>
    
    using namespace std;
    
    template <class T>
    
    class AVLTreeNode {
    public:
        T key;
        int height; //
        AVLTreeNode* left;
        AVLTreeNode* right;
        AVLTreeNode(T value, AVLTreeNode *l, AVLTreeNode *r):
                     key(value), height(0),left(l),right(r) {}
    };
    
    
    
    
    template <class T>
    class AVLTree {
    private:
        AVLTreeNode<T> *mRoot;    // 根结点
    
    public:
        AVLTree();
        ~AVLTree();
    
        // 获取树的高度
        int get_height();
        // 获取树的高度
        int max(int a, int b);
    
        // 前序遍历"AVL树"
        void preOrder();
        // 中序遍历"AVL树"
        void inOrder();
        // 后序遍历"AVL树"
        void postOrder();
    
        // (递归实现)查找"AVL树"中键值为key的节点
        AVLTreeNode<T>* search(T key);
        // (非递归实现)查找"AVL树"中键值为key的节点
        AVLTreeNode<T>* iterativeSearch(T key);
    
        // 查找最小结点:返回最小结点的键值。
        T minimum();
        // 查找最大结点:返回最大结点的键值。
        T maximum();
    
        // 将结点(key为节点键值)插入到AVL树中
        void insert(T key);
    
        // 删除结点(key为节点键值)
        void remove(T key);
    
        // 销毁AVL树
        void destroy();
    
        // 打印AVL树
        void print();
    private:
        // 获取树的高度
        int get_height(AVLTreeNode<T>* tree) ;
    
        // 前序遍历"AVL树"
        void preOrder(AVLTreeNode<T>* tree) const;
        // 中序遍历"AVL树"
        void inOrder(AVLTreeNode<T>* tree) const;
        // 后序遍历"AVL树"
        void postOrder(AVLTreeNode<T>* tree) const;
    
        // (递归实现)查找"AVL树x"中键值为key的节点
        AVLTreeNode<T>* search(AVLTreeNode<T>* x, T key) const;
        // (非递归实现)查找"AVL树x"中键值为key的节点
        AVLTreeNode<T>* iterativeSearch(AVLTreeNode<T>* x, T key) const;
    
        // 查找最小结点:返回tree为根结点的AVL树的最小结点。
        AVLTreeNode<T>* minimum(AVLTreeNode<T>* tree);
        // 查找最大结点:返回tree为根结点的AVL树的最大结点。
        AVLTreeNode<T>* maximum(AVLTreeNode<T>* tree);
    
        // LL:左左对应的情况(左单旋转)。
        AVLTreeNode<T>* leftLeftRotation(AVLTreeNode<T>* k2);
    
        // RR:右右对应的情况(右单旋转)。
        AVLTreeNode<T>* rightRightRotation(AVLTreeNode<T>* k1);
    
        // LR:左右对应的情况(左双旋转)。
        AVLTreeNode<T>* leftRightRotation(AVLTreeNode<T>* k3);
    
        // RL:右左对应的情况(右双旋转)。
        AVLTreeNode<T>* rightLeftRotation(AVLTreeNode<T>* k1);
    
        // 将结点(z)插入到AVL树(tree)中
        AVLTreeNode<T>* insert(AVLTreeNode<T>* &tree, T key);
    
        // 删除AVL树(tree)中的结点(z),并返回被删除的结点
        AVLTreeNode<T>* remove(AVLTreeNode<T>* &tree, AVLTreeNode<T>* z);
    
        // 销毁AVL树
        void destroy(AVLTreeNode<T>* &tree);
    
        // 打印AVL树
        void print(AVLTreeNode<T>* tree, T key, int direction);
    };
    
    
    int test_avl_tree();
    
    #endif //DEBUG_LRN_AVL_H
    

    源文件

    #include <vector>
    #include <iomanip>
    #include "AVLTreeNode.h"
    
    template <class T>
    AVLTree<T>::AVLTree():mRoot(nullptr){}
    
    template <class T>
    AVLTree<T>::~AVLTree() {
        destroy(mRoot);
    }
    
    /*
     * 获取树的高度
     */
    template <class T>
    int AVLTree<T>::get_height(AVLTreeNode<T>* tree)
    {
        if (tree != nullptr)
            return tree->height;
    
        return 0;
    }
    
    template <class T>
    int AVLTree<T>::get_height()
    {
        return get_height(mRoot);
    }
    
    /*
     * 比较两个值的大小
     */
    template <class T>
    int AVLTree<T>::max(int a, int b)
    {
        return a>b ? a : b;
    }
    
    
    /*
     * LL:左左对应的情况(左单旋转)。
     *
     * 返回值:旋转后的根节点
     */
    template <class T>
    AVLTreeNode<T>* AVLTree<T>::leftLeftRotation(AVLTreeNode<T>* k2)
    {
        AVLTreeNode<T>* k1;
    
        k1 = k2->left;
        k2->left = k1->right;
        k1->right = k2;
    
        k2->height = max( get_height(k2->left), get_height(k2->right)) + 1;
        k1->height = max( get_height(k1->left), k2->height) + 1;
    
        return k1;
    }
    
    /*
     * RR:右右对应的情况(右单旋转)。
     *
     * 返回值:旋转后的根节点
     */
    template <class T>
    AVLTreeNode<T>* AVLTree<T>::rightRightRotation(AVLTreeNode<T>* k1)
    {
        AVLTreeNode<T>* k2;
    
        k2 = k1->right;
        k1->right = k2->left;
        k2->left = k1;
    
        k1->height = max( get_height(k1->left), get_height(k1->right)) + 1;
        k2->height = max( get_height(k2->right), k1->height) + 1;
    
        return k2;
    }
    
    /*
     * LR:左右对应的情况(左双旋转)。
     *
     * 返回值:旋转后的根节点
     */
    template <class T>
    AVLTreeNode<T>* AVLTree<T>::leftRightRotation(AVLTreeNode<T>* k3)
    {
        k3->left = rightRightRotation(k3->left);
    
        return leftLeftRotation(k3);
    }
    
    
    /*
     * RL:右左对应的情况(右双旋转)。
     *
     * 返回值:旋转后的根节点
     */
    template <class T>
    AVLTreeNode<T>* AVLTree<T>::rightLeftRotation(AVLTreeNode<T>* k1)
    {
        k1->right = leftLeftRotation(k1->right);
    
        return rightRightRotation(k1);
    }
    
    /*
     * 将结点插入到AVL树中,并返回根节点
     *
     * 参数说明:
     *     tree AVL树的根结点
     *     key 插入的结点的键值
     * 返回值:
     *     根节点
     */
    template <class T>
    AVLTreeNode<T>* AVLTree<T>::insert(AVLTreeNode<T>* &tree, T key)
    {
        if (tree == nullptr)
        {
            // 新建节点
            tree = new AVLTreeNode<T>(key, nullptr, nullptr);
        }
        else if (key < tree->key) // 应该将key插入到"tree的左子树"的情况
        {
            tree->left = insert(tree->left, key);
            // 插入节点后,若AVL树失去平衡,则进行相应的调节。
            if (get_height(tree->left) - get_height(tree->right) == 2)
            {
                if (key < tree->left->key)
                    tree = leftLeftRotation(tree);
                else
                    tree = leftRightRotation(tree);
            }
        }
        else if (key > tree->key) // 应该将key插入到"tree的右子树"的情况
        {
            tree->right = insert(tree->right, key);
            // 插入节点后,若AVL树失去平衡,则进行相应的调节。
            if (get_height(tree->right) - get_height(tree->left) == 2)
            {
                if (key > tree->right->key)
                    tree = rightRightRotation(tree);
                else
                    tree = rightLeftRotation(tree);
            }
        }
        else //key == tree->key)
        {
            cout << "添加失败:不允许添加相同的节点!" << endl;
        }
    
        tree->height = max( get_height(tree->left), get_height(tree->right)) + 1;
    
        return tree;
    }
    
    template <class T>
    void AVLTree<T>::insert(T key)
    {
        insert(mRoot, key);
    }
    
    
    /* 
     * 删除结点(z),返回根节点
     *
     * 参数说明:
     *     tree AVL树的根结点
     *     z 待删除的结点
     * 返回值:
     *     根节点
     */
    template <class T>
    AVLTreeNode<T>* AVLTree<T>::remove(AVLTreeNode<T>* &tree, AVLTreeNode<T>* z)
    {
        // 根为空 或者 没有要删除的节点,直接返回nullptr。
        if (tree == nullptr || z == nullptr)
            return nullptr;
    
        if (z->key < tree->key)        // 待删除的节点在"tree的左子树"中
        {
            tree->left = remove(tree->left, z);
            // 删除节点后,若AVL树失去平衡,则进行相应的调节。
            if (get_height(tree->right) - get_height(tree->left) == 2)
            {
                AVLTreeNode<T> *r =  tree->right;
                if (get_height(r->left) > get_height(r->right))
                    tree = rightLeftRotation(tree);
                else
                    tree = rightRightRotation(tree);
            }
        }
        else if (z->key > tree->key)// 待删除的节点在"tree的右子树"中
        {
            tree->right = remove(tree->right, z);
            // 删除节点后,若AVL树失去平衡,则进行相应的调节。
            if (get_height(tree->left) - get_height(tree->right) == 2)
            {
                AVLTreeNode<T> *l =  tree->left;
                if (get_height(l->right) > get_height(l->left))
                    tree = leftRightRotation(tree);
                else
                    tree = leftLeftRotation(tree);
            }
        }
        else    // tree是对应要删除的节点。
        {
            // tree的左右孩子都非空
            if ((tree->left != nullptr) && (tree->right != nullptr))
            {
                if (get_height(tree->left) > get_height(tree->right))
                {
                    // 如果tree的左子树比右子树高;
                    // 则(01)找出tree的左子树中的最大节点
                    //   (02)将该最大节点的值赋值给tree。
                    //   (03)删除该最大节点。
                    // 这类似于用"tree的左子树中最大节点"做"tree"的替身;
                    // 采用这种方式的好处是:删除"tree的左子树中最大节点"之后,AVL树仍然是平衡的。
                    AVLTreeNode<T>* max = maximum(tree->left);
                    tree->key = max->key;
                    tree->left = remove(tree->left, max);
                }
                else
                {
                    // 如果tree的左子树不比右子树高(即它们相等,或右子树比左子树高1)
                    // 则(01)找出tree的右子树中的最小节点
                    //   (02)将该最小节点的值赋值给tree。
                    //   (03)删除该最小节点。
                    // 这类似于用"tree的右子树中最小节点"做"tree"的替身;
                    // 采用这种方式的好处是:删除"tree的右子树中最小节点"之后,AVL树仍然是平衡的。
                    AVLTreeNode<T>* min = maximum(tree->right);
                    tree->key = min->key;
                    tree->right = remove(tree->right, min);
                }
            }
            else
            {
                AVLTreeNode<T>* tmp = tree;
                tree = (tree->left != nullptr) ? tree->left : tree->right;
                delete tmp;
            }
        }
    
        return tree;
    }
    
    template <class T>
    void AVLTree<T>::remove(T key)
    {
        AVLTreeNode<T>* z;
    
        if ((z = search(mRoot, key)) != nullptr)
            mRoot = remove(mRoot, z);
    }
    
    template <class T>
    void AVLTree<T>::preOrder(AVLTreeNode<T> *tree) const {
        if (tree != nullptr){
            cout << tree->key << ", ";
            preOrder(tree->left);
            preOrder(tree->right);
        }
    }
    
    
    template <class T>
    void AVLTree<T>::preOrder(){
        return preOrder(mRoot);
    }
    
    
    template <class T>
    void AVLTree<T>::inOrder(AVLTreeNode<T> *tree) const {
        if (tree != nullptr){
            inOrder(tree->left);
            cout << tree->key << ", ";
            inOrder(tree->right);
        }
    }
    
    
    template <class T>
    void AVLTree<T>::inOrder(){
        return inOrder(mRoot);
    }
    
    template <class T>
    void AVLTree<T>::postOrder(AVLTreeNode<T> *tree) const {
        if (tree != nullptr){
            postOrder(tree->left);
            postOrder(tree->right);
            cout << tree->key << ", ";
        }
    }
    
    
    template <class T>
    void AVLTree<T>::postOrder(){
        return postOrder(mRoot);
    }
    
    template <class T>
    AVLTreeNode<T>* AVLTree<T>::minimum(AVLTreeNode<T> *tree) {
        if(tree == nullptr){
            return nullptr;
        }
        while(tree->left != nullptr){
            tree = tree->left;
        }
        return tree;
    }
    
    template <class T>
    T AVLTree<T>::minimum() {
        return minimum(mRoot)->key;
    }
    
    template <class T>
    AVLTreeNode<T>* AVLTree<T>::maximum(AVLTreeNode<T> *tree) {
        if(tree == nullptr){
            return nullptr;
        }
        while(tree->left != nullptr){
            tree = tree->left;
        }
        return tree;
    }
    
    template <class T>
    T AVLTree<T>::maximum() {
        return minimum(mRoot)->key;
    }
    
    //template <class T>
    //TreeNode* tree_search(TreeNode* x, int k)
    //{
    //    if(x == nullptr || k == x->key)
    //        return x;
    //    if(k < x->key)
    //        return tree_search(x->left, k);
    //    else return tree_search(x->right, k);
    //}
    
    template <class T>
    AVLTreeNode<T>* AVLTree<T>::search(AVLTreeNode<T>* x, T key) const{
        if( x == nullptr || key == x->key){
            return x;
        }
        if(key < x->key){
            return search(x->left, key);
        }
        else{
            return search(x->right, key);
        }
    }
    
    
    template <class T>
    AVLTreeNode<T>* AVLTree<T>::search(T key){
        return search(mRoot, key);
    }
    
    template <class T>
    AVLTreeNode<T>* AVLTree<T>::iterativeSearch(AVLTreeNode<T> *x, T key) const {
        while( x != nullptr && x->key != key){
            if(key < x->key){
                x = x->left;
            }
            else{
                x = x->right;
            }
        }
        return x;
    }
    
    template <class T>
    AVLTreeNode<T>* AVLTree<T>::iterativeSearch(T key) {
        return iterativeSearch(mRoot, key);
    }
    
    
    template <class T> void AVLTree<T>::destroy(AVLTreeNode<T>* &tree)
    {
         if (tree == nullptr)
             return ;
    
         if (tree->left != nullptr)
             destroy(tree->left);
         if (tree->right != nullptr)
             destroy(tree->right);
    
         delete tree;
    }
    
    template <class T>
    void AVLTree<T>::destroy()
    {
         destroy(mRoot);
    }
    
    
    template <class T>
    void AVLTree<T>::print(AVLTreeNode<T>* tree, T key, int direction){
        if(tree != nullptr){
            if(direction == 0){
                cout << setw(2) << tree->key << " is root" << endl;
            }
            else{
                cout << setw(2) << tree->key << " is " << setw(2) << key << "'s "  << setw(12) << (direction==1?"right child" : "left child") << endl;
            }
            print(tree->left, tree->key, -1);
            print(tree->right, tree->key, 1);
        }
    }
    
    template <class T>
    void AVLTree<T>::print()
    {
        if(mRoot != nullptr){
            print(mRoot, mRoot->key, 0);
        }
    }
    
    
    
    // 测试程序
    int test_avl_tree(){
        auto tree = new AVLTree<int>();
        vector<int> nums = {3,2,1,4,5,6,7,16,15,14,13,12,11,10,8,9};
        for(auto i: nums){
            tree->insert(i);
        }
        cout << " preOrder:" << endl;
        tree->print();
        cout << "==高度:" << tree->get_height() << endl;
        cout << "==最小值" << tree->minimum() << endl;
        cout << "==最大值" << tree->maximum() << endl;
        cout << tree->search(15)->key << endl;
        return 0;
    }
    
  • 相关阅读:
    【翻译自mos文章】 11gR1版本号 asmcmd的新命令--cp、md_backup、md_restore
    Android实现ListView或GridView首行/尾行距离屏幕边缘距离
    iOS-为方便项目开发在pch加入一些经常使用宏定义
    [ACM] FZU 1686 神龙的难题 (DLX 反复覆盖)
    Cocos2d-x Touch事件处理机制
    在linux環境下安裝jprofiler_linux_8_0_2.sh
    QT5 Failed to load platform plugin &quot;windows&quot; 终极解决方式 命令行问题
    我们想要如何子的生活?
    javaEE mvc样例具体解释
    安装Kali Linux操作系统Kali Linux无线网络渗透
  • 原文地址:https://www.cnblogs.com/theodoric008/p/9510864.html
Copyright © 2020-2023  润新知