zoukankan      html  css  js  c++  java
  • AVL树的实现(C++)

    AVL树,即平衡二叉搜索树,并且其左右子树的高度相差小于等于1。

    AVL树的实现,在于插入节点的同时,保持树的平衡性。共分为如下四种旋转:

    1. 左单边右旋转

    当在k1的左子树上插入节点以后,导致K2失去平衡后的旋转。

    代码实现如下:

          /*
        *
        * 左单边向右旋转
        */
        void singleRotateWithLeft(AvlNode * & k2)
        {
            AvlNode * k1 = k2->left;
            k2->left = k1->right;
            k1->right = k2;
    
            k2->h = max(h(k2->left), h(k2->right)) + 1;
            k1->h = max(h(k1->left), h(k1->right)) + 1;
    
            k2 = k1;
        }

    2. 右单边左旋转

     当在K2点右子树上插入节点后,导致的旋转,如下图;

    代码如下:

    代码如下:

           /*
        *
        * 右单边向左旋转
        *
        */
        void singleRotateWithRight(AvlNode * & k1)
        {
            AvlNode * k2 = k1->right;
            k1->right = k2->left;
            k2->left = k1;
    
            k1->h = max(h(k1->left), h(k1->right)) + 1;
            k2->h = max(h(k2->left), h(k2->right)) + 1;
    
            k1 = k2;
        }

    3. 左边2次旋转:

     当在K1的右子树上插入节点,导致K3失去平衡后的旋转。此时,需要做2次旋转。

    a. 以K1为根,进行右单边左旋转

    b. 以K3为根,进行左单边右旋转

    代码如下:

          /*
        *
        * 左单边向右doube旋转    
        */
        void doubleRotateWithLeft(AvlNode * & node)
        {
            singleRotateWithRight(node->left);
            singleRotateWithLeft(node);
        }

    4. 右边2次旋转

     

    代码

           /*
        *
        * 右单边向左doube旋转
        */
        void doubleRotateWithRight(AvlNode * & node)
        {
            singleRotateWithLeft(node->right);
            singleRotateWithRight(node);
        }

    all code :

    class MyAVLTree
    {
    private:
        struct AvlNode {
            int val;
            AvlNode * left;
            AvlNode * right;
            int h;
            AvlNode(int x) : val(x), h(0), left(NULL), right(NULL) {}
    
        };
    
        AvlNode * root;
    
        static const int ALLOWED_IMBALANCE = 1;
    
    public:
    
        MyAVLTree():root(NULL) {}
        AvlNode * getHead()
        {
            return root;
        }
    
        int h(AvlNode * root)
        {
            return root == NULL ? 0 : root->h;
        }
    
        void insert(int value)
        {
            insert(value, root);
        }
    
        void insert(int value,AvlNode * & node)
        {
            if (node == NULL)
            {
                node = new AvlNode{value};
            }
            else if (value < node->val) {
                insert(value, node->left);
            }
            else if (value > node->val)
            {
                insert(value, node->right);
            }
    
            balance(node);
        }
    
        void balance(AvlNode * & node)
        {
            if (node == NULL)
            {
                return;
            }
    
            if (h(node->left) - h(node->right) > ALLOWED_IMBALANCE)
            {
                if (h(node->left->left) >= h(node->left->right))
                {
                    singleRotateWithLeft(node);
                }
                else
                {
                    doubleRotateWithLeft(node);
                }
            }
            else if (h(node->right) - h(node->left) > ALLOWED_IMBALANCE)
            {
                if (h(node->right->right) >= h(node->right->left))
                {
                    singleRotateWithRight(node);
                }
                else
                {
                    doubleRotateWithRight(node);
                }
            }
    
    
            node->h = max(h(node->left), h(node->right)) + 1;
        }
    
        /*
        *
        * 左单边向右旋转
    
                k2                    k1
            k1     z    ==>       x         k2
        x       y                        y        z
    
        */
        void singleRotateWithLeft(AvlNode * & k2)
        {
            AvlNode * k1 = k2->left;
            k2->left = k1->right;
            k1->right = k2;
    
            k2->h = max(h(k2->left), h(k2->right)) + 1;
            k1->h = max(h(k1->left), h(k1->right)) + 1;
    
            k2 = k1;
        }
    
        /*
        *
        * 右单边向左旋转
        *        k1                         k2
        *   x       k2         ==>      k1      z
        *        y      z            x     y
        *
        *
        */
        void singleRotateWithRight(AvlNode * & k1)
        {
            AvlNode * k2 = k1->right;
            k1->right = k2->left;
            k2->left = k1;
    
            k1->h = max(h(k1->left), h(k1->right)) + 1;
            k2->h = max(h(k2->left), h(k2->right)) + 1;
    
            k1 = k2;
        }
    
        /*
        *
        * 左单边向右doube旋转    
        */
        void doubleRotateWithLeft(AvlNode * & node)
        {
            singleRotateWithRight(node->left);
            singleRotateWithLeft(node);
        }
    
    
        /*
        *
        * 右单边向左doube旋转
        */
        void doubleRotateWithRight(AvlNode * & node)
        {
            singleRotateWithLeft(node->right);
            singleRotateWithRight(node);
        }
    
    
        int max(int a, int b)
        {
            return a > b ? a : b;
        }
    
        void printAvlTreeWithPreOder(AvlNode * node)
        {
            
            if (node == NULL)
            {
                return;
            }
            cout << node->val << " ";
            printAvlTreeWithPreOder(node->left);
            printAvlTreeWithPreOder(node->right);
        }
    
        void printAvlTreeWithInOder(AvlNode * node)
        {
    
            if (node == NULL)
            {
                return;
            }
            printAvlTreeWithInOder(node->left);
            cout << node->val << " ";
            printAvlTreeWithInOder(node->right);
        }
    
    
    
    };
  • 相关阅读:
    总结ORACLE学习8023
    set @CurrentID=@@IDENTITY
    一个IT人:跳槽一定要谨慎
    SQL Server数据库开发(转自CSDN)
    46个不得不知的生活小常识
    CodeProjectSome Cool Tips For .Net 之一
    数据库原理综合习题答案
    EDM
    CodeProject Some Cool Tips for .NET之二
    The operation is not valid for the state of the transaction.
  • 原文地址:https://www.cnblogs.com/ordili/p/10432596.html
Copyright © 2011-2022 走看看