平衡二叉樹

                  二叉樹的查找,插入和刪除操做的時間與樹的高度有關,若是樹儘可能的矮胖,那麼時間就短,那就要是滿二叉樹,或者說滿N叉樹,對於一顆M個節點的滿N叉樹時間複雜度爲,可是維護滿叉樹,難度是很大的。因此AVL樹(平衡樹)放寬了條件,容許左右子樹的高度差在必定的範圍以內,avl樹平衡條件是左右子樹高度相差不能爲2,而不是滿叉樹左右子樹高度相同。AVL是以提出它的兩位蘇聯數學家的名字頭字母命名的。一棵N個節點的AVL樹,高度最高爲1.44logx(N+1)-0.328,比滿二叉樹高度增長44%。node

                  在avl樹中經過對不知足限制條件的子樹就行旋轉規格來確保av樹的平衡條件一直成立。在AVL樹中有LL,LR,RR和RL四種旋轉方式。.net

                  下面給出幾個示例:code

                  依次插入3,5,6,2,1,4blog

                  按照和二叉樹插入的方式同樣,插入3,5,6:rem

                  如今不平橫了,3節點左子樹的高度爲-1(空樹爲-1),右子樹爲1,相差爲2,不平衡,插入在3節點的右子樹的右子樹,這種狀況稱爲RR,轉換爲,這樣就平衡了。繼續插入2和1,狀況以下:節點3失去平衡,1插在3的左子樹的左子樹,LL狀況,須要旋轉,以下:樹從新平衡,如今繼續插入4,以下:,節點5失去平衡,4插在它的左子樹的右子樹上,這種狀況爲LR,須要兩次旋轉,第一次爲RR,5的左子樹,而後LL5這棵樹。變換後以下:數學

就不一一分析了,下面是實現代碼。it

/************************************************
*
*author:周翔
*e-mail:604487178@qq.com
*blog:http://blog.csdn.net/zhx6044
*
*
*************************************************/

#ifndef AVLTREE_HPP
#define AVLTREE_HPP

#include "linkQueue.hpp"

template <typename T>
T max(const T &t1, const T &t2)
{
    return (t1 < t2) ? t2 : t1 ;
}

template <typename T>
class AvlTree
{
public:
    AvlTree();
    ~AvlTree();
    bool find(const T& t) const;
    bool insert(const T &t);
    void remove(const T &t);
    bool isEmpty() const;
    void clear();
    int height(typename AvlTree::node *n);
    /**
     * @brief levelTraverse 層虛遍歷
     * @param os
     */
    void levelTraverse(std::ostream &os = std::cout) const;
private:

    typedef enum {LEFT, RIGHT} TreeType;
    struct node {
        T data;
        node *lc,*rc;
        int height;//高度
        node():lc(0),rc(0),height(0){

        }
        node(const T &t,node *_lc = 0, node *_rc = 0,int _hei = 0):
            data(t),
            lc(_lc),
            rc(_rc),
            height(_hei){

        }
    };

    node *root;

    bool insert(const T &t, node *&n);
    bool remove(const T &t, node *&n);
    void clear(node *n);
    //四種旋轉,
    void LL(node *&n);
    void RR(node *&n);
    void LR(node *&n);
    void RL(node *&n);
};

template <typename T>
inline
AvlTree<T>::AvlTree():root(0)
{

}


template <typename T>
AvlTree<T>::~AvlTree()
{
    clear();
}

template <typename T>
void AvlTree<T>::clear(node *n)
{
    if (n->lc != 0) {
        clear(n->lc);
    }
    if (n->rc != 0) {
        clear(n->rc);
    }
    delete n;
}

template <typename T>
void AvlTree<T>::clear()
{

    if (!isEmpty())
        clear(root);
}


template <typename T>
inline
bool AvlTree<T>::isEmpty() const
{
    return root == 0;
}

template <typename T>
inline
int AvlTree<T>::height(node *n)
{
    return (n == 0) ? -1 : n->height;
}

template <typename T>
void AvlTree<T>::LL(node *&n)
{
    node *p = n;//暫存n
    n = n->lc;//左子樹做爲根節點
    p->lc = n->rc;//右子樹做爲原來根的左子樹
    n->rc = p;//原來根節點做爲新節點的右子樹
    p->height = max(height(p->lc),height(p->rc)) + 1;//先作子樹的高度
    n->height = max(height(n->lc),height(n->rc)) + 1;

}

template <typename T>
void AvlTree<T>::RR(node *&n)
{
    node *p = n;
    n = n->rc;
    p->rc = n->lc;
    n->lc = p;
    p->height = max(height(p->lc),height(p->rc)) + 1;
    n->height = max(height(n->lc),height(n->rc)) + 1;
}

template <typename T>
void AvlTree<T>::LR(node *&n)
{
    RR(n->lc);
    LL(n);
}

template <typename T>
void AvlTree<T>::RL(node *&n)
{
    LL(n->rc);
    RR(n);

}

template <typename T>
bool AvlTree<T>::find(const T &t) const
{
    node *p = root;
    while (p != 0 && p->data != t) {
        if (p->data < t) {
            p = p->rc;
        } else {
            p = p->lc;
        }
    }
    return ((p == 0) ? false:true);
}

template <typename T>
bool AvlTree<T>::insert(const T &t)
{
    return insert(t,root);
}

template <typename T>
bool AvlTree<T>::insert(const T &t, node *&n)
{
    bool re = false;
    if (n == 0) {
        n = new node(t);
        re = true;
    } else {
        if (t < n->data) {
            re = insert(t,n->lc);//插入到左子樹
            if (height(n->lc) - height(n->rc) == 2) {//子樹高度差超過1
                if (t < n->lc->data) {//插入的值小於左子樹的值,說明還要插在左子樹的左子樹
                    LL(n);//作LL旋轉
                } else {
                    LR(n);//作LR旋轉
                }
            }
        } else {
            re = insert(t,n->rc);
            if (height(n->rc) - height(n->lc) == 2) {
                if (t < n->rc->data) {
                    RL(n);
                } else {
                    RR(n);
                }
            }
        }
    }
    n->height = max(height(n->lc),height(n->rc)) + 1;
    return re;
}

template <typename T>
void AvlTree<T>::remove(const T &t)
{
    remove(t,root);
}

template <typename T>
/**
 * @brief AvlTree<T>::remove
 * @param t
 * @param n
 * @return
 * 只討論左子樹,右子樹狀況對稱,刪除的節點都在P的左子樹上
 * 1.P節點平衡因子爲0,刪除節點x,使其某棵子樹變矮,p的平衡因子變爲-1或1,樹的高度不變,整棵樹也不變
 * 2.P節點平衡因子爲-1或1,刪除P較高子樹的節點,P平衡因子爲0,樹高發生了變化,須要繼續向上規格
 * 3.P節點平衡因子爲-1或1,刪除P較矮子樹的節點,P不平橫,須要規格,樹高若是變化,須要繼續向上規格
 * 3.1P的右子樹的平衡因子爲0,作RR,子樹高度不變,不準要規格
 * 3.2P的右子樹的平衡因子與P相同,作一個RR,子樹高度變化,須要繼續規格
 * 3.2P的右子樹的平衡因子與P相反,RL,子樹高度變化,須要貴徐規格
 */
bool AvlTree<T>::remove(const T &t, node *&n)
{
    bool re = true;//是否須要規格
    TreeType flag;//標識是左子樹仍是右子樹
    if (n == 0) {
        re = false;
    } else {
        if (t < n->data) {
            re = remove(t,n->lc);
            flag = LEFT;
        } else {
            if (t > n->data) {
                re = remove(t,n->rc);
                flag = RIGHT;
            } else {
                //t = n->data
                if (n->lc != 0 && n->rc != 0) {
                    node *p = n->rc;
                    while (p->lc != 0) p = p->lc;
                    n->data = p->data;
                    re = remove(p->data,n->rc);
                    flag = RIGHT;
                    } else {
                    node *p = n;
                    n = (n->rc == 0) ? n->lc : n->rc;
                    delete p;
                    re = false;
                }
            }
        }
    }
    if (re) {
        int t;
        switch (flag) {
        case LEFT://左子樹
            t = height(n->lc) + 1 - height(n->rc);//左子樹刪除一個節點,如今的+1原來的
            if (t == 0) {//
                re = false;
            } else {
                if (re == 1) {//說明左子樹較高
                    re = true;
                } else {
                    int t2 = height(n->rc->lc) - height(n->rc->rc);
                    switch (t2) {
                    case 0:
                        RR(n);
                        re = false;
                        break;
                    case -1://左子樹矮,連個平衡因子相同,爲-1
                        RR(n);
                        re = true;
                        break;
                    default:
                        RL(n);
                        re = true;
                        break;
                    }
                }

            }
            break;
        case RIGHT://右子樹
            t = height(n->lc)  - (height(n->rc)+1);//右子樹刪除一個節點,如今的+1原來的
            if (t == 0) {//
                re = false;
            } else {
                if (re == -1) {//說明右子樹較高
                    re = true;
                } else {//較矮的樹
                    int t2 = height(n->lc->lc) - height(n->lc->rc);
                    switch (t2) {
                    case 0:
                        LL(n);
                        re = false;
                        break;
                    case 1://右子樹矮,連個平衡因子相同,爲1
                        LL(n);
                        re = true;
                        break;
                    default:
                        LR(n);
                        re = true;
                        break;
                    }
                }

            }
            break;
        default:
            break;
        }
    }

    return re;


}

template <typename T>
void AvlTree<T>::levelTraverse(std::ostream &os) const
{
    LinkQueue<node*> queue;
    queue.enqueue(root);
    while(!queue.isEmpty()) {
        node *t = queue.dequeue();
        if (t != NULL) {
            os << t->data << "  ";
            queue.enqueue(t->lc);
            queue.enqueue(t->rc);
        }
    }
}





#endif // AVLTREE_HPP


#include "avlTree.hpp"



int main()
{
    AvlTree<int> avlt;
    int arr[]={3,5,6};
    for(int i = 0;i < 3;++i) {
        avlt.insert(arr[i]);
    }
    avlt.levelTraverse();
    avlt.insert(2);
    std::cout << '\n';
    avlt.levelTraverse();
    avlt.insert(1);
    std::cout << '\n';
    avlt.levelTraverse();
    avlt.insert(4);
    std::cout << '\n';
    avlt.levelTraverse();
}

相關文章
相關標籤/搜索
本站公眾號
   歡迎關注本站公眾號,獲取更多信息