每日一類封裝之AVL樹

思路學習博客https://www.cnblogs.com/coding-nerver-die/p/10975599.html

主要是理解其中維持其平衡進行的旋轉操作,分兩種情況
第一種情況只需要旋轉一次
在這裏插入圖片描述第二中情況需要先旋轉下不平衡子樹的子樹,使其滿足是一條遞減的線,再旋轉
在這裏插入圖片描述
直接上代碼

template  <typename T>
struct AVLTreeNode{

    AVLTreeNode(T val,AVLTreeNode<T>* left,AVLTreeNode<T>* right)
    :val(val),left(left),right(right){}
    T val;
    int height;
    AVLTreeNode<T>* left;
    AVLTreeNode<T>* right;
    AVLTreeNode<T>* parent;
};
template <typename T>
struct AVLTree
{
public:
    AVLTree();
    ~AVLTree();

    void insert(T key); //插入
    void remove(T key); //刪除某節點

    AVLTreeNode<T>* find1(AVLTreeNode<T>* pnode,T key);   //遞歸查找某節點
    AVLTreeNode<T>* find2(AVLTreeNode<T>* pnode,T key);   //非遞歸查找某節點

    int height(); //獲取樹的高度

    void preOrder();	//前序遍歷AVL樹
    void InOrder();		//中序遍歷AVL樹
    void postOrder();	//後序遍歷AVL樹

private:
    AVLTreeNode<T>* head;

    int height(AVLTreeNode<T>* pnode) ; //任意一節點的高度

    AVLTreeNode<T>* insert(AVLTreeNode<T>* &pnode, T key);
    AVLTreeNode<T>* remove(AVLTreeNode<T>* & pnode, T key);

    AVLTreeNode<T>* leftRotation(AVLTreeNode<T>* pnode);		//單旋:左旋操作
    AVLTreeNode<T>* rightRotation(AVLTreeNode<T>* pnode);		//單旋:右旋操作
    AVLTreeNode<T>* leftRightRotation(AVLTreeNode<T>* pnode);	//雙旋:先左旋後右旋操作
    AVLTreeNode<T>* rightLeftRotation(AVLTreeNode<T>* pnode);	//雙旋:先右旋後左旋操作
};

//構造函數
template <typename T>
AVLTree<T>::AVLTree(){
    head = NULL;
}
//銷燬每個節點
template <typename  T>
AVLTree<T>::~AVLTree(){

}

template <typename T>
int AVLTree<T>::height(AVLTreeNode<T>* pnode)   //返回任一節點子樹的高度
{
    if (pnode != NULL)
    {
        return pnode->height;
    }
    return 0;																//如果是空樹,高度爲0
};

template <typename T>
int AVLTree<T>::height()
{
    return height(head);
};

template <typename T>
AVLTreeNode<T>* AVLTree<T>::leftRotation(AVLTreeNode<T> *pnode) {
    AVLTreeNode<T>* p = pnode->right;
    pnode->right = p->left;
    p->left = pnode;

    pnode->height = max(height(pnode->left),height(pnode->right))+1;    //更新改變高度的兩個節點

    p->height = height(p)+1;
}

template <typename T>
AVLTreeNode<T>* AVLTree<T>::leftRightRotation(AVLTreeNode<T>* pnode)
{
    pnode->lchild= leftRotation(pnode->lchild); //先把根節點的子樹旋轉一下,在旋轉根節點
    return rightRotation(pnode);
}

template <typename T>
AVLTreeNode<T>* AVLTree<T>::insert(AVLTreeNode<T>* &pnode, T key){
    if(pnode== NULL){   //創建一個節點
        pnode = new AVLTreeNode<T>(key,NULL,NULL);
    }
    else if(key > pnode->val){  //如果Key大於當前根節點,就在根節點的右子樹上插入
        pnode->right = insert(pnode->right,key);    //遞歸插入
        if(height(pnode->right) - height(pnode->left) == 2){
            if(key > pnode->right->val)
                pnode = leftRotation(pnode);
            else
                pnode = rightRotation(pnode);
        }
    }
    else if(key < pnode->val){
        pnode->left = insert(pnode->left,key);
       if(height(pnode->left) - height(pnode->right) == 2){
                if(key > pnode->left->val)
                    pnode = leftRotation(pnode);
                else
                    pnode = rightRotation(pnode);
            }
    }
    pnode->height = max(height(pnode->left), height(pnode->right)) + 1;
    return pnode;
}

template <typename T>
void AVLTree<T>::insert(T key)  //從根節點開始插入
{
    insert(head, key);
};

template <typename  T>
AVLTreeNode<T>* AVLTree<T>::find1(AVLTreeNode<T>*root,T key) {
    if(head != NULL){
        if(key == root->val)
            return root;
        else if(key > root->val)
            return find1(root->right,key);
        else
            return find1(root->left,key);
    }
}

template <typename  T>
AVLTreeNode<T>* AVLTree<T>::find2(AVLTreeNode<T>*root,T key){
    while(root != NULL){
        if(key == root->val)
            return root;
        else if(key > root->val)
           root = root->right;
        else
            root = root->left;
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章