【數據結構】搜索結構之AVL樹

AVL樹———又稱平衡二叉樹
二插搜索樹雖然可以縮短查找效率,但如果數據有序或接近有序二插搜索樹將退化爲單支樹,查找元素相當於在順序表中搜索元素,效率低下。

AVL樹概念:

平衡化旋轉
如果在一棵原本是平衡的二插搜索樹中插入一個新節點,可能造成不平衡,此時必須調整輸的結構,使之平衡化。

1.左單旋:
插入點位於ptr的右子結點的右子樹—-右右
這裏寫圖片描述
2.右單旋:
插入點位於ptr的左子結點的左子樹—-左左
這裏寫圖片描述
3.先左後右雙旋:
插入點位於ptr左子節點的右子樹—-左右
這裏寫圖片描述
4.先右後左雙旋:
插入點位於ptr右子節點的左子樹—-右左
這裏寫圖片描述

AVL樹的插入
這裏寫圖片描述
AVL樹的刪除
這裏寫圖片描述

AVL樹代碼:
【AVLTree.h】

#pragma once
#include<iostream>
using namespace std;

template<class K,class V>
struct AVLNode
{
    AVLNode(K key,V value)
    :_Lchild(NULL)
    , _Rchild(NULL)
    , _parent(NULL)
    , _key(key)
    , _value(value)
    , _bf(0)
    {}

    AVLNode<K, V>* _Lchild;
    AVLNode<K, V>* _Rchild;
    AVLNode<K, V>* _parent;
    K _key;
    V _value;
    int _bf;
};

template<class K,class V>
class AVLTree
{
    typedef AVLNode<K, V>* pNode;
    typedef AVLNode<K, V> Node;
public:
    AVLTree()
        :Root(NULL)
    {}
    bool Insert(K& k,V& v)   //插入元素
    {
        return _Insert(k, v);
    }

    void InOrder()   //中序遍歷
    {
        _InOrder(Root);
    }
    bool CheckAVLT()   //判斷是否是AVL樹
    {
        return _CheckAVLT(Root);
    }
/////////////////////////////////////////////////////////////
private:
    bool _CheckAVLT(pNode pRoot)
    {
        if (pRoot)
        {
            int len = _Height(pRoot->_Rchild) - _Height(pRoot->_Lchild);
            if (len<-1 || len>1)
                return false;
                   _CheckAVLT(pRoot->_Lchild);
                   _CheckAVLT(pRoot->_Rchild);
        }
        return true;
    }
    int _Height(pNode pRoot)
    {
        if (pRoot == NULL)
            return 0;
        return  _Height(pRoot->_Lchild) > _Height(pRoot->_Rchild) ? _Height(pRoot->_Lchild) + 1 : _Height(pRoot->_Rchild) + 1;

    }
    void _InOrder(pNode pRoot)
    {
        if (pRoot != NULL)
        {
            _InOrder(pRoot->_Lchild);
            cout << "<" << pRoot->_key << "," << pRoot->_value << ">" << endl;
            _InOrder(pRoot->_Rchild);
        }
    }
    bool _Insert(K& k, V& v)
    {
        pNode newNode = new Node(k, v);
        if (Root == NULL)
        {
            Root = newNode;
            return true;
        }
        pNode cur = Root;
        pNode pParent = NULL;
        while (cur)                  //查找要插入的位置
        {
            pParent = cur;
            if (cur->_key > k)
                cur = cur->_Lchild;

            else if (cur->_key < k)
                cur = cur->_Rchild;
            else
                return false;
        }

        if (pParent->_key>k)
        {
            pParent->_Lchild = newNode;
            newNode->_parent = pParent;
        }

        else if (pParent->_key < k)
        {
            pParent->_Rchild = newNode;
            newNode->_parent = pParent;
        }
        cur = newNode;       //cur標記雙親節點的孩子
        while (pParent)
        {
            if (pParent->_Lchild == cur)
                    pParent->_bf--;
            else if (pParent->_Rchild == cur)
                    pParent->_bf++;

                if (pParent->_bf == 1 || pParent->_bf == -1)
                {
                    cur = pParent;
                    pParent = pParent->_parent;
                }
                else if (pParent->_bf == 2 || pParent->_bf == -2)   //旋轉
                {
                    if (pParent->_bf == 2)       
                    {
                        if (pParent->_Rchild->_bf==1)
                            RotateL(pParent);          //左單旋
                        else
                            RotateRL(pParent);           //右左雙旋
                    }
                    else                        
                    {
                        if (pParent->_Lchild->_bf == -1)
                            RotateR(pParent);          //右單旋
                        else
                            RotateLR(pParent);         //左右雙旋
                    }
                }
                else
                    break;
        }
        return true;
    }
    void RotateL(pNode pParent)         //左單旋
    {
        pNode pSubR = pParent->_Rchild;
        pNode pSubRL = pSubR->_Lchild;
        pNode _pParent = pParent->_parent;

        pParent->_Rchild = pSubRL;
        if (pSubRL!=NULL)
        pSubRL->_parent = pParent;

        pSubR->_Lchild = pParent;
        pParent->_parent = pSubR;
        if (_pParent == NULL)
        {
            Root = pSubR;
            pSubR->_parent = _pParent;
        }
        else if (_pParent != NULL&&_pParent->_Lchild == pParent)
        {
            _pParent->_Lchild = pSubR;
            pSubR->_parent = _pParent;
        }
        else if (_pParent != NULL&&_pParent->_Rchild == pParent)
        {
            _pParent->_Rchild = pSubR;
            pSubR->_parent = _pParent;
        }
        pSubR->_bf = 0;
        pParent->_bf = 0;
    }
    void RotateR(pNode pParent)   //右單旋
    {
        pNode pSubL = pParent->_Lchild;
        pNode pSubLR = pSubL->_Rchild;
        pNode _pParent = pParent->_parent;

        pParent->_Lchild = pSubLR;
        if (pSubLR!=NULL)
        pSubLR->_parent = pParent;

        pSubL->_Rchild = pParent;
        pParent->_parent = pSubL;

        if (_pParent == NULL)
        {
            Root = pSubL;
            pSubL->_parent = _pParent;
        }
        else if (_pParent != NULL&&_pParent->_Lchild == pParent)
        {
            _pParent->_Lchild = pSubL;
            pSubL->_parent = _pParent;
        }
        else if (_pParent != NULL&&_pParent->_Rchild == pParent)
        {
            _pParent->_Rchild = pSubL;
            pSubL->_parent = _pParent;
        }
        pSubL->_bf = 0;
        pParent->_bf = 0;
    }
    void RotateRL(pNode pnode)      //右左雙旋
    {
        pNode pParent = pnode;
        pNode pSubR = pnode->_Rchild;
        RotateR(pnode->_Rchild);
        RotateL(pnode);

        if (pSubR->_Lchild->_bf== 1)
        {
            pParent->_bf = -1;
        }
        else if (pSubR->_Lchild->_bf == -1)
        {
            pSubR->_bf = 1;
        }

    }
    void RotateLR(pNode pnode)    //左右雙旋
    {
        pNode pParent = pnode;
        pNode pSubL= pnode->_Lchild;
        RotateL(pnode->_Lchild);
        RotateR(pnode);

        if (pSubL->_Rchild->_bf == -1)
        {
            pParent->_bf = 1;
        }
        else if (pSubL->_Rchild->_bf == 1)
        {
            pSubL->_bf = -1;
        }
    }

private:
    pNode Root;
};

void test()
{
    //int arr[] = {5,3,4,1,7,8,2,6,0,9};   //普通版
    //int arr[] = {30,20,50,40,60,70};     //左單旋
    //int arr[] = {60,40,70,30,50,20};       //右單旋
    //int arr[] = { 3, 2, 6, 5, 4, 7 };      //右左雙旋
    int arr[] = {4,2,6,1,3,5,15,7,16,14};   //左右雙旋

    int size = sizeof(arr) / sizeof(arr[0]);
    AVLTree<int, int> t;
    for (int i = 0; i < size; i++)
    {
        t.Insert(arr[i], i);
    }
    t.InOrder();
    if (t.CheckAVLT())
        cout << "是平衡二叉樹" << endl;
    else
        cout << "不是平衡二叉樹" << endl;

}

【test.cpp】

#include"AVLTree.h"

int main()
{
    test();
    system("pause");
    return 0;

}
發佈了70 篇原創文章 · 獲贊 92 · 訪問量 6萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章