• 平衡二叉树(c语言实现代码)


    #pragma once
    class CAVLTree
    {
    private:
        struct TreeNode
        {
            TreeNode(const int& nVal) :m_nVal(nVal) {}
    
            int m_nVal = 0;     //数据
            int m_hHeight = 1;  //叶子结点的高度
            TreeNode* m_pParent = nullptr; //父亲
            TreeNode* m_pLeft = nullptr;   //左孩子
            TreeNode* m_pRight = nullptr;  //右孩子
        }; 
    
    public:
        CAVLTree();
        ~CAVLTree();
    
        void Insert(const int& nVal);  //插入
    
        //遍历
        void Layer();  //层序遍历
        void LDR();  //中序遍历
        void LDR_Loop();  //中序遍历
        void _LDR(TreeNode* pNode);  //中序遍历
        void DLR();   //前序遍历
        void DLR_Loop();   //前序遍历
        void LRD();   //后序遍历
        void LRD_Loop();   //后序遍历
    
    public:
        void Delete(const int& nVal);
    private:
        TreeNode* Find(const int& nVal);
        void DeleteNode(TreeNode* pNodeDel);
    
    private:
        void AdjustHeight(TreeNode* pNode);
        int GetHeight(TreeNode* pNode);
        void RotateRight(TreeNode* pNode);
        void RotateLeft(TreeNode* pNode);
        TreeNode* m_pRoot = nullptr;    //根结点
    };
    

      

    #include "stdafx.h"
    #include "AVLTree.h"
    #include <queue>
    #include <iostream>
    #include <stack>
    using namespace std;
    
    CAVLTree::CAVLTree()
    {
    }
    
    
    CAVLTree::~CAVLTree()
    {
    }
    
    void CAVLTree::Insert(const int& nVal)
    {
        //创建新结点
        TreeNode* pNewNode = new TreeNode(nVal);
    
        //空树
        if (m_pRoot == nullptr)
        {
            m_pRoot = pNewNode;
            return;
        }
    
        //插入新数据
        TreeNode* pNode = m_pRoot;
        do 
        {
            //如果值比结点的值小,则取结点的左孩子
            if (nVal < pNode->m_nVal)
            {
                //左孩子不存在,则新结点插入
                if (pNode->m_pLeft == nullptr)
                {
                    pNode->m_pLeft = pNewNode;
                    pNewNode->m_pParent = pNode;
                    break;
                }
                //左孩子存在,继续比较
                else
                {
                    pNode = pNode->m_pLeft;
                }
            }
            //如果值比结点的值大,则取结点的右孩子
            else if (nVal > pNode->m_nVal)
            {
                //如果右孩子不存在,则新结点插入
                if (pNode->m_pRight == nullptr)
                {
                    pNode->m_pRight = pNewNode;
                    pNewNode->m_pParent = pNode;
                    break;
                }
                //继续比较
                else
                {
                    pNode = pNode->m_pRight;
                }
    
            }
            //如果相等,则不插入.
            else
            {
                return;
            }
    
        } while (true);
    
        AdjustHeight(pNewNode);
    }
    
    /*
    层序遍历: 一层一层遍历树
    
        8
     4     15
    2  5 10  19
    
    输出结果: 8 4 15 2 5 10 19 
    */
    void CAVLTree::Layer()
    {
        queue<TreeNode*> queNodes;
        queNodes.push(m_pRoot);
    
        while (!queNodes.empty())
        {
            //取队首的元素,
            TreeNode* pNode = queNodes.front(); 
    
            if (pNode == nullptr)
            {
                queNodes.pop();
                continue;
            }
    
            //左孩子和右孩子入队
            queNodes.push(pNode->m_pLeft);
            queNodes.push(pNode->m_pRight);
    
            //输出
            cout << pNode->m_nVal << " ";
    
            //结点出队
            queNodes.pop();
        }
    
        cout << endl;
    }
    
    /*
    中序遍历:先左孩子,再自己,再右孩子
         8
      4     15
    2  5   10  19
    
    输出结果: 2 4 5 8 10 15 19
    */
    
    void CAVLTree::LDR()
    {
        _LDR(m_pRoot);
    
        cout << endl;
    }
    
    
    /*
    中序遍历:先左孩子,再自己,再右孩子
         8
      4     15
    2  5   10  19
    
    输出结果: 2 4 5 8 10 15 19
    
    栈:(底 --> 顶)     输出:
    8 
    8  4
    8  4  2
    8  4              2 
    8  5              2  4
    8                 2  4  5
    15                2  4  5  8
    15 10             2  4  5  8
    15                2  4  5  8  10
    19                2  4  5  8  10  15
                      2  4  5  8  10  15  19
    */
    void CAVLTree::LDR_Loop()
    {
        stack<TreeNode*> stkTmp;
    
        TreeNode* pNode = m_pRoot;
        while (true)
        {
            //结点入栈
            while (pNode != nullptr)
            {
                stkTmp.push(pNode);
                pNode = pNode->m_pLeft;
            }
    
            //栈为空,结束
            if (stkTmp.empty())
            {
                break;
            }
    
            //从栈顶取出元素,处理自己
            pNode = stkTmp.top();
            cout << pNode->m_nVal << " ";
            pNode = pNode->m_pRight;
            stkTmp.pop();
        }
    
        cout << endl;
    }
    
    void CAVLTree::_LDR(TreeNode* pNode)
    {
        if (pNode == nullptr)
        {
            return;
        }
    
        _LDR(pNode->m_pLeft);
        cout << pNode->m_nVal << " ";
        _LDR(pNode->m_pRight);
    }
    
    
    /*
      前序遍历:先自己,再左孩子,再右孩子
      输出自己,右孩子入栈,处理左孩子
    */
    void CAVLTree::DLR_Loop()
    {
        stack<TreeNode*> stkTmp;
        TreeNode* pNode = m_pRoot;
    
        while (true)
        {
            //先处理自己
            while (pNode != nullptr)
            {
                cout << pNode->m_nVal << " ";
                stkTmp.push(pNode->m_pRight);
                pNode = pNode->m_pLeft;
            }
    
            //栈为空,处理完毕
            if (stkTmp.empty())
            {
                break;
            }
    
            //处理右孩子
            pNode = stkTmp.top();
            stkTmp.pop();
        }
        cout << endl;
    
    }
    
    /*
    后序遍历:先左孩子,再右孩子,再自己
    自己入栈, 处理左孩子,再右孩子入栈,再处理自己
    */
    
    void CAVLTree::LRD_Loop()
    {
        stack<TreeNode*> stkTmp;
        TreeNode* pNode = m_pRoot;
        TreeNode* pLastNode = nullptr;
        while (true)
        {
            while (pNode != nullptr)
            {
                stkTmp.push(pNode);
                pNode = pNode->m_pLeft;
            }
    
            //栈空则处理完毕
            if (stkTmp.empty())
            {
                break;
            }
    
            pNode = stkTmp.top();
            if (pNode->m_pRight == nullptr//叶子节点
                || pNode->m_pRight == pLastNode //上一次处理了此节点的右孩子
                ) 
            {
                cout << pNode->m_nVal << " ";
                pLastNode = pNode; 
                pNode = nullptr;
                stkTmp.pop();
            }
            else //上一次没有处理此节点的右孩子,所以此节点不处理,处理其右孩子
            {
                pNode = pNode->m_pRight;
            }
        }
    
        cout << endl;
    }
    
    CAVLTree::TreeNode* CAVLTree::Find(const int& nVal)
    {
        TreeNode* pNode = m_pRoot;
        while (true)
        {
            if (pNode == nullptr)
            {
                return nullptr;
            }
    
            if (nVal == pNode->m_nVal)
            {
                return pNode;
            }
            else if (nVal > pNode->m_nVal)
            {
                pNode = pNode->m_pRight;
            }
            else
            {
                pNode = pNode->m_pLeft;
            }
        }
    
        return nullptr;
    }
    
    /*
    删除的情况: 
      1. 叶子节点,直接删掉
      2. 只有左孩子
      3. 只有右孩子
      4. 有两个孩子,则在左子树中查找最大值的结点,
         将其拷贝到待删除节点,删除最大值节点
    */
    
    void CAVLTree::Delete(const int& nVal)
    {
        TreeNode* pNode = Find(nVal);
        DeleteNode(pNode);
    }
    
    
    /*
    删除的情况:
    1. 叶子节点,直接删掉
    2. 只有左孩子
    3. 只有右孩子
    4. 有两个孩子,则在左子树中查找最大值的结点,
    将其拷贝到待删除节点,删除最大值节点
    */
    void CAVLTree::DeleteNode(TreeNode* pNodeDel)
    {
        //没有左孩子和右孩子
        if (pNodeDel->m_pLeft == nullptr && pNodeDel->m_pRight == nullptr)
        {
            TreeNode* pParent = pNodeDel->m_pParent;
            if (pParent == nullptr)
            {
                m_pRoot = nullptr;
                delete pNodeDel;
                return;
            }
    
            //被删除结点是父结点的左孩子,父结点左孩子置空
            if (pParent->m_pLeft == pNodeDel)
            {
                pParent->m_pLeft = nullptr;
            }
            //被删除结点是父结点的右孩子,父结点右孩子置空
            else
            {
                pParent->m_pRight = nullptr;
            }
            delete pNodeDel;
            return;
        }
    
        //只有左孩子
        if (pNodeDel->m_pLeft != nullptr && pNodeDel->m_pRight == nullptr)
        {
            /* 删除B
                 C                 C
               B          -->     A
              A
    
                 C                C
                   B      -->       A 
                  A
            */
            TreeNode* pB = pNodeDel;
            TreeNode* pC = pB->m_pParent;
            TreeNode* pA = pB->m_pLeft;
    
            //删除结点为根结点
            if (pC == nullptr)
            {
                m_pRoot = pA;
                pA->m_pParent = nullptr;
                delete pB;
                return;
            }
    
            if (pB == pC->m_pLeft)
            {
                pC->m_pLeft = pA;
            }
            else
            {
                pC->m_pRight = pA;
            }
            pA->m_pParent = pC;
            delete pB;
            return;
        }
    
        //只有右孩子
        if (pNodeDel->m_pLeft == nullptr && pNodeDel->m_pRight != nullptr)
        {
            /* 删除B
             C                 C
              B          -->     A
               A
    
              C                C
            B      -->       A
              A
            */
            TreeNode* pB = pNodeDel;
            TreeNode* pC = pB->m_pParent;
            TreeNode* pA = pB->m_pRight;
    
    
            //删除结点为根结点
            if (pC == nullptr)
            {
                m_pRoot = pA;
                pA->m_pParent = nullptr;
                delete pB;
                return;
            }
    
            if (pB == pC->m_pRight)
            {
                pC->m_pRight = pA;
            }
            else
            {
                pC->m_pLeft = pA;
            }
            pA->m_pParent = pC;
            delete pB;
            return;
        }
    
        //同时有左孩子和右孩子
        //查找左子树中最大值的结点
        TreeNode* pMaxNode = pNodeDel->m_pLeft;
        while (pMaxNode->m_pRight != nullptr)
        {
            pMaxNode = pMaxNode->m_pRight;
        }
        pNodeDel->m_nVal = pMaxNode->m_nVal;
        DeleteNode(pMaxNode);
    }
    
    void CAVLTree::AdjustHeight(TreeNode* pNode)
    {
        TreeNode* pCurNode = pNode;
        while (pCurNode != nullptr)
        {
            //取左孩子和右孩子高度最大的值,然后+1
            pCurNode->m_hHeight =
                std::max(GetHeight(pCurNode->m_pLeft), GetHeight(pCurNode->m_pRight)) + 1;
    
            
            if (GetHeight(pCurNode->m_pLeft) - GetHeight(pCurNode->m_pRight) > 1)
            {
                TreeNode* pB = pCurNode->m_pLeft;
                if (GetHeight(pB->m_pLeft) > GetHeight(pB->m_pRight))
                {
                    /*   B的左孩子比右孩子高,对C右旋
                      C               B
                     B        -->    A  C
                    A
                    */
                    RotateRight(pCurNode);
                }
                else
                {
                    /*   B的右孩子比左孩子高,先对B进行左旋,再对C右旋
                      C               C              A
                    B        -->     A      -->     B  C 
                      A            B  
                    */
                    RotateLeft(pB);
                    RotateRight(pCurNode);
                }
            }
            else if (GetHeight(pCurNode->m_pRight) - GetHeight(pCurNode->m_pLeft) > 1)
            {
                TreeNode* pB = pCurNode->m_pRight;
                if (GetHeight(pB->m_pRight) > GetHeight(pB->m_pLeft))
                {
                    /*   B的右孩子比左孩子高,对C左旋
                    C                   B
                      B        -->    C   A
                        A
                    */
                    RotateLeft(pCurNode);
                }
                else
                {
                    /*  B的左孩子比右孩子高,先对B进行右旋,再对C左旋
                    C                    C               A
                        B        -->       A      -->   C   B
                      A                       B
                    */
                    RotateRight(pB);
                    RotateLeft(pCurNode);
                }
            }
    
    
    
            //继续遍历父结点
            pCurNode = pCurNode->m_pParent;
        }
    }
    
    int CAVLTree::GetHeight(TreeNode* pNode)
    {
        if (pNode == nullptr)
        {
            return 0;
        }
        return pNode->m_hHeight;
    }
    
    void CAVLTree::RotateRight(TreeNode* pNode)
    {
        /*   C的左孩子与右孩子的高度差大于1, 向右旋转
           P                   P   
             C                   B
           B   k1      -->    A       C
         A   k2                    k2   k1
        */
        TreeNode* pP = pNode->m_pParent;
        TreeNode* pC = pNode;
        TreeNode* pB = pC->m_pLeft;
        TreeNode* pA = pB->m_pLeft;
        TreeNode* pK1 = pC->m_pRight;
        TreeNode* pK2 = pB->m_pRight;
    
        if (pP == nullptr)
        {
            //C是根结点
            m_pRoot = pB;
        }
        else
        {
            //C不是根结点
            if (pP->m_pLeft == pC)
            {
                pP->m_pLeft = pB;
            }
            else
            {
                pP->m_pRight = pB;
            }
        }
    
        pC->m_pParent = pB;
        pC->m_pLeft = pK2;
    
        pB->m_pParent = pP;
        pB->m_pRight = pC;
    
        if (pK2 != nullptr)
        {
            pK2->m_pParent = pC;
        }
    
    
        //修改高度
        pC->m_hHeight = max(GetHeight(pC->m_pLeft), GetHeight(pC->m_pRight)) + 1;
        pB->m_hHeight = max(GetHeight(pB->m_pLeft), GetHeight(pB->m_pRight)) + 1;
    }
    
    void CAVLTree::RotateLeft(TreeNode* pNode)
    {
        /*   C的右孩子与做孩子的高度差大于1, 向右旋转
           P                       P
          C                       B
       k1   B        -->     C          A
          k2  A            k1  k2
        */
        TreeNode* pP = pNode->m_pParent;
        TreeNode* pC = pNode;
        TreeNode* pK1 = pC->m_pLeft;
        TreeNode* pB = pC->m_pRight;
        TreeNode* pK2 = pB->m_pLeft;
        TreeNode* pA = pB->m_pRight;
    
        pC->m_pRight = pK2;
        pC->m_pParent = pB;
    
        pB->m_pLeft = pC;
        pB->m_pParent = pP;
    
        if (pK2 != nullptr)
        {
            pK2->m_pParent = pC;
        }
    
        if (pP == nullptr)
        {
            m_pRoot = pB;
        }
        else
        {
            if (pP->m_pLeft == pC)
            {
                pP->m_pLeft = pB;
            }
            else
            {
                pP->m_pRight = pB;
            }
        }
    
        //修改高度
        pC->m_hHeight = max(GetHeight(pC->m_pLeft), GetHeight(pC->m_pRight)) + 1;
        pB->m_hHeight = max(GetHeight(pB->m_pLeft), GetHeight(pB->m_pRight)) + 1;
    }
    

      

    学如逆水行舟,不进则退。 博客园技术交流群 群 号:1073255314 (本群没人,刚刚建立 -_-!!! )
  • 相关阅读:
    nsmutableset
    数组建立 不可变数组 排序 遍历
    字符串截取 拼接 转换 长度 查询 比较
    字典排序
    数字字典结合
    可变字典
    字典
    可变字符串
    oc block排序
    oc中文首字母排序
  • 原文地址:https://www.cnblogs.com/Mj-NaijAm/p/13606833.html
Copyright © 2020-2023  润新知