• AVL树->图解1


    Balance Binary Tree

         是一种二叉排序树,其中每个节点的左子树跟右子树的高度至多为1;因为发现解决平衡二叉树算法的两个人名字命名为AVL树;我们将二叉树节点的左子树深度减去右子树深度的值(Hleft-Hright)=>平衡因子BF(Balance Factor) -1,0,1; 平衡的引入就是为了最大化实现查找为O(logN)

        距离插入节点距离最近,且平衡因子的绝对值大于1的节点为根的子树,我们称为最小不平衡子树

    BBT 实现原理就是在构造二叉排序树时,每当插入一个节点时,先检查是否因插入而破坏了树的平衡性。若是则找到最小不平衡子树,调制最小不平衡子树的链接关系,进行相应旋转,成为新的平衡子树。

    typedef struct tree_node
    {
    	int data;
    	int bf;//Balance Factor 平衡因子
    	struct tree_node* left;
    	struct tree_node* right;
    }TREE_NODE;
    

    不平衡可能出现4种

    1.LL左左

           其中D是新插入的节点,红色节点K2是失去平衡的节点。需要对K1和K2进行左旋调整即将K1作为根,将K2作为K1的左子树,K1的右子树调整为K2的左子树。如下图所示

      进行左旋变换    

    //左边高L
    void SingleRotateWithLeft(TREE_NODE** root)
    {
    	TREE_NODE* temp;
    	temp =(*root)->left;
    	(*root)->left = temp->right;
    	temp->right = *root;
    	*root = temp;
    }
    2.LR左右

          先对K1和K2进行右旋,然后再对K3和K2进行左旋,最终实现平衡。如下图所示

    一次右旋转->一次左旋

    //左边过高LR
    void DoubleRotateWithLeft(TREE_NODE** root)
    {
    	SingleRotateWithRight(&(*root)->left);
    	SingleRotateWithLeft(root);
    }

    3.RR右右

        将K2的右子树更改为K1的左子树,K1的左子树更改为K2即完成的右旋,如下图所示

    一次右旋

    //右边高的时L
    void SingleRotateWithRight(TREE_NODE** root)
    {
    	TREE_NODE* temp;
    	temp = (*root)->right;
    	(*root)->right = temp->left;
    	temp->left = *root;
    	*root = temp;
    }

    4.RL右左

       右左双旋:先对K1和K2进行左旋,然后在对K2和K3进行右旋,最终实现平衡。如下图所示

    一次左旋一次右旋

          上面是AVL树四种旋转情况,下面来实现一下AVL树。AVL树的实现跟上一章讲的二叉查找树相似,区别在于在插入和删除节点是需要对树进行调整以满足平衡条件

    #include "Queue.h"
    #include <iostream>
    using namespace std;
    #include <vector>
    typedef struct avlnode
    {
        int key;
        int height;
        struct avlnode* left;
        struct avlnode* right;
    }AVLNode;
    
    typedef struct avltree
    {
        AVLNode* root;
    }AVLTree;
    
    typedef struct   stack
    {
        AVLNode*  base;    //在栈构造前和销毁后,base的值为NULL
        AVLNode*  top;       //栈顶指针
        int    StackSize;       //当前已分配的存储空间,以元素为单位
    }Stack;
    
    AVLTree* CreateAVLTree()
    {
        AVLTree* tree = new AVLTree;
        tree->root = NULL;
        return tree;
    }
    
    int RootHeight(const AVLNode* root)
    {
        if(root)
        {
            return root->height;
        }
        else
        {
            return 0;
        }
    }
    
    int Max(const int& a, const int& b)
    {
        return a > b ? a : b;
    }
    /*
                          100                              85
                         /                 右旋         /    
                       85   120         ------ ->       60    100
                      /                                     /   
                    60    90                             80  90   120
                      
                       80
    */
    void SingleRotateWithLeft(AVLNode* &root)
    {
        AVLNode* temp;
        temp =root->left;
       root->left = temp->right;
        temp->right = root;
       root->height = Max(RootHeight(root->left), RootHeight(root->right))+1;
        temp->height = Max(RootHeight(temp->left), RootHeight(temp->right))+1;
        root = temp;
    }
    /*
                          80                                   90
                         /                左旋               /  
                       60    90          ---- ->            80    120
                              /                          /      /
                           85  120                      60   85  100
                                /
                             100
    */
    void SingleRotateWithRight(AVLNode* & root)
    {
        AVLNode* temp;
        temp =root->right;
        root->right = temp->left;
        temp->left = root;
        root->height = Max(RootHeight(root->left), RootHeight(root->right))+1;
        temp->height = Max(RootHeight(temp->left), RootHeight(temp->right))+1;
        root = temp;
    }
    /*
                      100                          100                       90
                     /           左旋            /         右旋           / 
                    80  120     ------>          90  120    ------>        80 100
                   /                            /                       /     
                  60 90                         80                      60  85   120
                      /                         / 
                    85                         60 85
    */
    void DoubleRotateWithLeft(AVLNode* & root)
    {
        SingleRotateWithRight(root->left);
        SingleRotateWithLeft(root);
    }
    /*
                  80                              80                                   85
                /                右 旋          /                 左 旋             / 
               60   100          ------>        60   85            ------->          80 100
                    /                                                             /  /  
                   85  120                            100                         60  90  120
                                                     /  
                          90                         90  120
    */
    void DoubleRotateWithRight(AVLNode*& root)
    {
        SingleRotateWithLeft(root->right);
        SingleRotateWithRight(root);
    }
    AVLNode* FindNode(int data, AVLNode* root) //FindNode
    {
        if(NULL == root)
        {
            return NULL;
        }
        else if(data < root->key)
        {
            return FindNode(data, root->left);
        }
        else if(data > root->key)
        {
            return FindNode(data, root->right);
        }
        else
        {
            return root;
        }
    }
    AVLNode* FindMin(AVLNode* root) //FindMin
    {
        if(NULL == root)
        {
            return NULL;
        }
        else if( NULL== root->left)
        {
            return root;
        }
        else return FindMin(root->left);
    }
    
    AVLNode* FindMax(AVLNode* root) //FindMax
    {
        if(NULL == root)
        {
            return NULL;
        }
        else if( NULL== root->right)
        {
            return root;
        }
        else return FindMax(root->right);
    }
    bool AVLInsert(AVLNode* &root, int data)
    {
        if(NULL == root)
        {
            root = new AVLNode;
            if(NULL == root)
            {
                return false;
            }
            root->key = data;
            root->height = 0;
            root->left = NULL;
            root->right = NULL;
        }
        else if(NULL != FindNode(data,root))
        {
            cout<<data<<" has been insert ! ";
        }
        else if(data < root->key)
        {
            AVLInsert(root->left, data);
            if(2 == RootHeight(root->left) - RootHeight(root->right))
            {
                if(data < root->left->key)
                {
                    SingleRotateWithLeft(root);
                }
                else
                {
                    DoubleRotateWithLeft(root);
                }
            }
        }
        else if(data > root->key)
        {
            AVLInsert(root->right, data);
            if(2 == RootHeight(root->right) - RootHeight(root->left))
            {
                if(data > root->right->key)
                {
                    SingleRotateWithRight(root);
                }
                else
                {
                    DoubleRotateWithRight(root);
                }
            }
        }
        root->height = Max(RootHeight(root->left), RootHeight(root->right))+1;
        return true;
    }
    
    bool AVLDelete(AVLNode* &root, int data) // 删除
    {
        AVLNode* temp;
        if(NULL == root)
        {
            return false;
        }
        else if(data < root->key)
        {
            AVLDelete(root->left, data);
        }
        else if(data > root->key)
        {
            AVLDelete(root->right, data);
        }
        else
        {
            if((root->left != NULL) && (root->right != NULL))
            {
                temp = FindMin(root->right); //右边找最小值
                root->key = temp->key; //将找到的值赋给当前root
                AVLDelete(root->right, root->key); //删除在右边找到的值
            }
            else
            {
                temp = root;
                if(NULL == root->left )
                {
                    root = root->right;
                }
                else if(NULL == root->right)
                {
                    root = root->left;
                }
                delete temp;
                temp = NULL;
            }
            return true;
        }
    }
    int TotalNodeNum(AVLNode* root) //节点总数
    {
        if(root)
        {
            int LNodeNum = TotalNodeNum(root->left);
            int RNodeNum = TotalNodeNum(root->right);
            return LNodeNum + RNodeNum +1;
        }
        return 0;
    }
    
    int LeafNodeNum(AVLNode* root)//叶子节点数
    {
        int leaf = 0;
        int LNodeNum = 0;
        int RNodeNum = 0;
        if(root)
        {
            if(NULL==root->left && NULL == root->right)
            {
                leaf =1;
            }
            else
            {
                LNodeNum = LeafNodeNum(root->left);
                RNodeNum = LeafNodeNum(root->right);
                leaf = LNodeNum + RNodeNum;
            }
        }
        else
        {
                return 0;
        }
       return leaf;
    }
    
    int RootDepth(AVLNode* root)//这个节点的深度
    {
        if(root)
        {
            int LHigh = RootDepth(root->left);
            int RHigh = RootDepth(root->right);
            return LHigh > RHigh ? LHigh+1 : RHigh+1;
        }
        return 0;
    }
    void SwapRootLeftRight(AVLNode * root)//实现交换每个节点的左右节点
    {
        AVLNode* temp;
        if(root)
        {
            temp = root->left;
            root->left = root->right;
            root->right = temp;
            SwapRootLeftRight(root->left);
            SwapRootLeftRight(root->right);
        }
    }
    void PreOrderTraverse(const AVLNode* root)
    {
        if(root)
        {
            cout << root->key << " ";
            PreOrderTraverse(root->left);
            PreOrderTraverse(root->right);
        }
    }
    
    void InOrderTraverse(const AVLNode* root)
    {
        if(root)
        {
            InOrderTraverse(root->left);
            cout << root->key << " ";
            InOrderTraverse(root->right);
        }
    }
    
    void PostOrderTraverse(const AVLNode* root)
    {
        if(root)
        {
            PostOrderTraverse(root->left);
            PostOrderTraverse(root->right);
            cout << root->key << " ";
        }
    }
    void LevelTraverse( AVLNode* root)
    {
        if(NULL == root)
        {
            return;
        }
        vector<AVLNode*>vec;
        vec.push_back(root);
        int cur = 0;
        while(cur < vec.size())
        {
            cout<<vec[cur]->key<<" ";
            if(NULL != vec[cur]->left)
            {
                vec.push_back(vec[cur]->left);
            }
            if(NULL != vec[cur]->right)
            {
                vec.push_back(vec[cur]->right);
            }
            cur++;
        }
    }
    void AllOrderTraverse( AVLNode* root)
    {
        cout << "PreOrder: ";
        PreOrderTraverse(root);
        cout << endl;
        cout << "InOrder: ";
        InOrderTraverse(root);
        cout << endl;
        cout << "PostOrder: ";
        PostOrderTraverse(root);
        cout << endl;
        cout << "LevelOrder: ";
        LevelTraverse(root);
        cout << endl;
    }
    int main()
    {
        AVLTree* tree = CreateAVLTree();
        for(int i = 1; i <= 7; i++)
        {
            AVLInsert(tree->root, i);
        }
        for(int i = 16; i >= 10; i--)
        {
            AVLInsert(tree->root, i);
        }
        AVLInsert(tree->root, 8);
        AVLInsert(tree->root, 9);
        AllOrderTraverse(tree->root);
        cout<<endl;
    
        int total = TotalNodeNum(tree->root);
        int leaf = LeafNodeNum(tree->root);
        int node2 = leaf-1;//前提是leaf > 1
        int node1 = total - leaf - node2;
    
        return 0;
    }
    


    关注公众号 海量干货等你
  • 相关阅读:
    vue如何将单页面改造成多页面应用
    css3动画基础详解(@keyframes和animation)
    《css揭秘》下(伪元素,文字背景,垂直居中技巧,文字环绕)
    Wavesurfer.js音频播放器插件的使用教程
    《CSS3揭秘》上(边框,投影,渐变,条纹效果,蚂蚁行军)
    复活hexo静态博客的方法
    基于svg.js实现对图形的拖拽、选择和编辑操作
    js 常用的工具函数
    linux 新机器的配置(git + nodejs+ mongodb)
    vue 不常见操作
  • 原文地址:https://www.cnblogs.com/sowhat1412/p/12734455.html
Copyright © 2020-2023  润新知