平衡二叉树(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 (本群没人,刚刚建立 -_-!!! )
原文地址:https://www.cnblogs.com/Mj-NaijAm/p/13606833.html