C++入门教程(13)平衡二叉树

说来惭愧,数据结构学了10年了,直到今天才弄明白这个平衡二叉树的代码实现(之前只是知道原理,现在也可以自己造轮子用C++实现了)。

平衡二叉树其实就是二叉树,它是二叉树的一种特殊结构,主要是为了提高查找效率

假如有1023个节点,那么最多只需要10次就能找到目标节点。

转换成平衡二叉树的左旋和右旋的实现,其实就是为了使树平衡,将这棵树做最少的改动。并且前提条件是插入节点之前,这颗树是平衡的,所以只有4种情况会导致树的不平衡

1)依次插入3,2,1 需要右旋

2)依次插入1,2,3  需要左旋

3)依次插入1,3,2 需要先右旋再左旋

4)依次插入3,1,2 需要先左旋再右旋

以上4种情况都会导致根节点的不平衡,经过旋转以后,最终都会得到一颗以2为根节点的平衡的二叉树



#include <iostream>
using namespace std;
 
 
//树上的节点 我们只用一个value来存值 可以自行扩展存储其他数据
class TreeNode {
public:
    int _value;
    int _balance;   //平衡因子 0表示左右平衡 左边深度减右边的深度
    TreeNode *_lc;
    TreeNode *_rc;
    TreeNode()
    {
        _value = 0;
        _lc = NULL;
        _rc = NULL;
    }
};
 
//平衡二叉树
class AVLTree {
public:
 
    //每棵树都有一个根节点
    TreeNode * _root;
    
 
    //向一个树中插入一个元素
    TreeNode* insertValue(TreeNode * &node,int value)
    {
        if (node == NULL)
        {
            //如果节点为空,直接创建一个节点
            node = new TreeNode();
            node->_value = value;
            node->_balance = 0;
            
        }
        //如果当前插入的值比根节点大
        else if (value > node->_value )
        {
            //如果有右子树 , 往右子树里面插入
            node->_rc = insertValue(node->_rc, value);
            if(getTreeDepth(node->_rc)-getTreeDepth(node->_lc)==2)//插入后失衡
            {
                
                if( value > node->_rc->_value )
                {
                    //       N                         NR
                    //         \                     /    \
                    //          NR            =>    N      NRR
                    //           \
                    //            NRR
                    node = LeftRotate(node);
                }
                else
                {
                    //       N                    N                         NRL
                    //         \                    \                      /  \
                    //          NR        =>         NRL        =>       N     NR
                    //          /                       \
                    //         NRL
                    node = RightLeftRotate(node);
                }
            }
            
            
        }
        //如果有左子树 , 往左子树里面插入
        else
        {
            
            node->_lc = insertValue(node->_lc, value);
            
            if(getTreeDepth(node->_lc)-getTreeDepth(node->_rc)==2)//插入后失衡
            {
                if( value > node->_lc->_value )
                {
                    //       N                        N                  NLR
                    //      /                       /                   /  \
                    //    NL            =>        NLR           =>    NL    N
                    //      \                    /
                    //      NLR                 NL
                    
                    node=LeftRightRotate(node);//左右的旋转
                    
                }
                else
                {
                    
                    //       N                        NL
                    //      /                        /    \
                    //    NL            =>        NLL      N
                    //    /
                    //  NLL
                    node=RightRotate(node);//右旋
                }
            }
            
        }
            
            
        //更新节点的高度
        _root->_balance = getTreeDepth(_root->_lc ) - getTreeDepth(_root->_rc );
    
        return node;
    }
    
    
    //右旋一棵二叉树
    TreeNode * RightRotate(TreeNode *&node)
    {
        int balanceFactor = getTreeDepth(node->_lc) - getTreeDepth(node->_rc);
        if (balanceFactor != 2)
        {
            cout << "不符合右旋条件" << endl;
            return node;
        }
        
        //旋转前 二叉树是平衡的
        
        //       N                        NL
        //      /                        /    \
        //    NL            =>        NLL      N
        //    /
        //  NLL
        
        
        //         N                            NL
        //       /   \                     /        \
        //      NL     NR            =>   NLL        N
        //    /  \                          \       / \
        //   NLL  NLR                       NLLR   NLR NR
        //     \
        //      NLLR
        
        
        
        TreeNode *NL = node->_lc;
        node->_lc = NL->_rc;
        NL->_rc = node;
        return NL;
    }

    
    
    
    
    //左旋一棵二叉树
    TreeNode * LeftRotate(TreeNode *&node)
    {
        int balanceFactor = getTreeDepth(node->_lc) - getTreeDepth(node->_rc);
        if (balanceFactor != -2)
        {
            cout << "不符合左旋条件" << endl;
            return node;
        }
        
        //       N                         NR
        //         \                     /    \
        //          NR            =>    N      NRR
        //           \
        //            NRR
        
        //         N                            NR
        //       /   \                     /        \
        //      NL     NR            =>   N        NRR
        //             / \               /  \         \
        //           NRL   NRR          NL   NRL        NRRR
        //                  \
        //                  NRRR
        
        TreeNode *NR = node->_rc;
        node->_rc = NR->_lc;
        NR->_lc = node;
        return NR;
    }
    
    
    //先右旋再左旋
    TreeNode * RightLeftRotate(TreeNode *&node)
    {
        
        //       N                    N                         NRL
        //         \                    \                      /  \
        //          NR        =>         NRL        =>       N     NR
        //          /                       \
        //         NRL                      NR
        
        RightRotate(node->_rc);
        return LeftRotate(node);
        
    }
    
    //先右旋再左旋
    TreeNode * LeftRightRotate(TreeNode *&node)
    {
        
        //       N                        N                  NLR
        //      /                       /                   /  \
        //    NL            =>        NLR           =>    NL    N
        //      \                    /
        //      NLR                 NL
        
        LeftRotate(node->_lc);
        return RightRotate(node);
        
    }
    
    
    
    //获取二叉树的深度(左右子树的最大深度+1)
    int getTreeDepth(TreeNode * root)
    {
         if (root == NULL)
         {
             return 0;
         }
        
         int leftTreeDepth = getTreeDepth(root->_lc);
         int rightTreeDepth = getTreeDepth(root->_rc);
         return leftTreeDepth > rightTreeDepth ? leftTreeDepth + 1 : rightTreeDepth + 1;

    }
    

    //获取最大节点(一直向右边找节点)
    TreeNode * getMaxNode(TreeNode * root)
    {
         if (root!= NULL )
         {
              if (root->_rc != NULL)
              {
                  return getMaxNode(root->_rc);

              }
              else
              {
                  return root;
              }
         }
        else
        {
            return NULL;
        }
    }

    //获取最小节点(一直向左边找节点)
    TreeNode * getMinNode(TreeNode * root)
    {
        if (root!= NULL )
        {
             if (root->_lc != NULL)
             {
                 return getMinNode(root->_lc);

             }
             else
             {
                 return root;
             }
        }
       else
       {
           return NULL;
       }
    }


    //中序遍历
    void printTreeMid(TreeNode * root)
    {
        if (root!= NULL) {
            printTreeMid(root->_lc);
            std::cout << root->_value << "," ;
            printTreeMid(root->_rc);
        }
    }


    //前序遍历
    void printTreeFront(TreeNode * root)
    {
        if (root != NULL) {
            std::cout << root->_value << "," ;
            printTreeFront(root->_lc);
            printTreeFront(root->_rc);
        }
    }

    //后序遍历
    void printTreeBack(TreeNode * root)
    {
        if (root != NULL) {
            printTreeBack(root->_lc);
            printTreeBack(root->_rc);
            std::cout << root->_value << "," ;
        }
    }
};
 
void testFun(TreeNode * node)
{
    
}


int main()
{
    // 创建一个平衡二叉树
    AVLTree * avlTree = new AVLTree();
    for (int i = 1 ; i < 1024 ; i++)
    {
        avlTree->insertValue(avlTree->_root, i);
    }
    
    cout << "树的深度为 :" << avlTree->getTreeDepth(avlTree->_root) <<endl;
    
    avlTree->printTreeFront(avlTree->_root);
    
    cout<<endl;
}

运行:

树的深度为 :10

可以看到树的深度为10,如果按照上一节的插入操作不做平衡处理的话,这棵树的深度达到最坏的情况1023,也就会导致1023这个节点在查找的时候会找1023次才能找到

特殊的:当平衡二叉树是一颗满二叉树的时候,根节点刚好是最中间的那个值

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

爱我呦呦

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值