中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

AVL樹之刪除算法

發布時間:2020-04-21 21:55:00 來源:網絡 閱讀:1709 作者:匯天下豪杰 欄目:編程語言

1、AVL樹刪除

  思路:

  (1)、首先找到要刪除的結點;沒找到,直接false返回退出即可;

  (2)、將其轉化為只有一個分支的結點,前面的路徑都要入棧,

  (3)、其父節點(parent)的平衡因子(根據父的左/右=p(要刪除的結點),修改父的bf),有幾種情況,i>父節點的bf=1/-1,代表原先有兩個結點,現在剩下一個了,直接退出循環,不用再往上尋找更改bf了;ii>父節點的bf=0;代表此時的往上更改爺爺結點(在此出棧即可,棧中保存了路徑信息)的bf,看情況(bf=2/-2)是否進行旋轉,和要進行相應的旋轉方式。

  (4)、判斷棧空,進行相應的連接操作;

  (5)、最后刪除這個結點;

相應部分情況:

AVL樹之刪除算法

AVL樹之刪除算法

2、AVL樹刪除代碼

template<typename Type>
bool AVLTree<Type>::remove(AVLNode<Type> *&t, const Type &x){
    AVLNode<Type> *p = t;
    AVLNode<Type> *parent = NULL;  //父結點
    AVLNode<Type> *q = NULL;  //刪除結點的輔助結點
    stack<AVLNode<Type> *> st;

    AVLNode<Type> *ppr; //爺爺結點

    int flag = 0;
    while(p != NULL){
        if(p->data == x){
            break;
        }
        parent = p;
        st.push(parent);
        if(x < p->data){
            p = p->leftChild;
        }else{
            p = p->rightChild;
        }
    } //以上是:查找刪除點
    if(p == NULL){  //沒有要刪除的結點
        return false;
    }
    if(p->leftChild!= NULL && p->rightChild!=NULL){
        parent = p;
        st.push(parent);

        q = p->leftChild;
        while(q->rightChild != NULL){
            parent = q;
            st.push(parent);
            q = q->rightChild;
        }

        p->data = q->data;
        p = q;
    }
    
    if(p->leftChild != NULL){
        q = p->leftChild;
    }else{
        q = p->rightChild;
    }
//以上是:使其要刪除的轉化為只有一個分支的
    if(parent == NULL){  //刪除的是根結點,并且無入棧,代表只有一個分支,并沒有尋找
        t = q;  
    }else{
        if(parent->leftChild == p){
            flag = 0;
            parent->leftChild = q;
        }else{
            flag = 1;
            parent->rightChild = q;
        }

        while(!st.empty()){
            parent = st.top();
            st.pop();
            if(parent->leftChild==q){ //對要刪除的父節點更改bf;
                parent->bf++;
            }else{
                parent->bf--;
            }
            if(!st.empty()){
                ppr = st.top();
                if(ppr->leftChild == parent){
                    flag = 0;
                }else{
                    flag = 1;
                }
            }
            if(parent->bf==-1 || parent->bf==1 ){
                break; //刪除前的平衡因子為0,此時不用再調整其它平衡因子,直接退出循環;
            }

            if(parent->bf == 0){  //原先只有左孩子/右孩子
                q = parent; //往上回溯更改爺爺結點的bf;
            }else{  //此時到達2,已經不平衡了,的進行旋轉化的調整
                if(parent->bf < 0){
                    flag = -1;
                    q = parent->leftChild;
                }else{
                    flag = 1;
                    q = parent->rightChild;
                }
                if(q->bf == 0){
                    if(flag == -1){
                        
                    }
                }
                if(parent->bf > 0){
                    q = parent->rightChild;
                    if(q->bf == 0){
                        RotateL(parent);
                    }else if(q->bf > 0){
                        RotateL(parent);
                    }else{
                        RotateRL(parent);
                    }
                }else{
                    q = parent->leftChild;
                    if(q->bf == 0){
                        RotateR(parent);
                    }else if(q->bf < 0){
                        RotateR(parent);
                    }else{
                        RotateLR(parent);
                    }
                }
            }
        }
        if(st.empty()){
            t = parent;  //直接更改root
        }else{
            AVLNode<Type> *tmp = st.top();  //當前的棧頂結點使其的左/右指向parent(是旋轉化后的根);
            if(parent->data < tmp->data){  
                tmp->leftChild = parent;
            }else{
                tmp->rightChild = parent;
            }
        }

    }

    delete p;  //刪除結點;
    return true;
}

3、完整代碼、測試代碼、測試結果

  (1)完整代碼

#ifndef _AVL_TREE_H_
#define _AVL_TREE_H_

#include<iostream>  //引入頭文件
#include<stack>    //要用棧保存路徑信息
using namespace std;

template<typename Type>
class AVLTree;

template<typename Type>
class AVLNode{   //AVL樹的結點
    friend class AVLTree<Type>;
public:
    AVLNode() : data(Type()), leftChild(NULL), rightChild(NULL), bf(0){}
    AVLNode(Type d, AVLNode *left = NULL, AVLNode *right = NULL) 
        : data(d), leftChild(left), rightChild(right), bf(0){}
    ~AVLNode(){}
private:
    Type data;
    AVLNode *leftChild;
    AVLNode *rightChild;
    int bf;  //多了一個平衡因子
};

template<typename Type>
class AVLTree{   //AVL樹的類型
public:
    AVLTree() : root(NULL){}
public:
    bool insert(const Type &x){
        return insert(root, x);
    }
    bool remove(const Type &x){
        return remove(root, x);
    }
    void inOrder()const{
        inOrder(root);
    }
protected:
    void inOrder(AVLNode<Type> *t)const{
        if(t != NULL){
            inOrder(t->leftChild);
            cout<<t->data<<" : "<<t->bf<<endl;;
            inOrder(t->rightChild);
        }
    }
    bool insert(AVLNode<Type> *&t, const Type &x); //插入函數
    bool remove(AVLNode<Type> *&t, const Type &x);
    void RotateR(AVLNode<Type> *&ptr){  //右旋
        AVLNode<Type> *subR = ptr;
        ptr = ptr->leftChild;
        subR->leftChild = ptr->rightChild;
        ptr->rightChild = subR;
        ptr->bf = subR->bf = 0;
    }
    void RotateL(AVLNode<Type> *&ptr){  //左旋
        AVLNode<Type> *subL = ptr;
        ptr = subL->rightChild;
        subL->rightChild = ptr->leftChild;
        ptr->leftChild = subL;
        subL->bf = ptr->bf = 0;
    }
    void RotateLR(AVLNode<Type> *&ptr){  //先左后右旋轉
        AVLNode<Type> *subR = ptr;
        AVLNode<Type> *subL = ptr->leftChild;
        ptr = subL->rightChild;

        subL->rightChild = ptr->leftChild;
        ptr->leftChild = subL;
        if(ptr->bf <= 0){
            subL->bf = 0;
        }else{
            subL->bf = -1;
        }

        subR->leftChild = ptr->rightChild;
        ptr->rightChild = subR;
        if(ptr->bf == -1){
            subR->bf = 1;
        }else{
            subR->bf = 0;
        }

        ptr->bf = 0;
    }
    void RotateRL(AVLNode<Type> *&ptr){  //先右后左旋轉
        AVLNode<Type> *subL = ptr;
        AVLNode<Type> *subR = ptr->rightChild;
        ptr = subR->leftChild;

        subR->leftChild = ptr->rightChild;
        ptr->rightChild = subR;
        if(ptr->bf >=0){
            subR->bf = 0;
        }else{
            subR->bf = 1;
        }

        subL->rightChild = ptr->leftChild;
        ptr->leftChild = subL;
        if(ptr->bf == 1){
            subL->bf = -1;
        }else{
            subL->bf = 0;
        }
        ptr->bf = 0;
    }
private:
    AVLNode<Type> *root;
};

template<typename Type>
bool AVLTree<Type>::insert(AVLNode<Type> *&t, const Type &x){
    AVLNode<Type> *p = t;
    AVLNode<Type> *parent = NULL; // 記錄前驅結點,方便連接和調整平衡因子
    stack<AVLNode<Type> *> st; //用棧記錄插入的路徑,方便調整棧中結點的平衡因子;
    int sign;

    while(p != NULL){
        if(x == p->data){ //要插入的數據和AVL樹中的數字相同,則返回失敗!
            return false;
        }

        parent = p;
        st.push(parent); //找過的入棧
        if(x < p->data){
            p = p->leftChild;
        }else if(x > p->data){
            p = p->rightChild;
        }
    } // 找插入位置,不用遞歸,就是為了記錄路徑信息
    
    p = new AVLNode<Type>(x);
    if(parent == NULL){
        t = p;    //判斷是不是第一個結點,進行root的連接;
        return true;
    }

    if(x < parent->data){ //此時通過父節點的數據判斷插入的是左還是右
        parent->leftChild = p;
    }else{
        parent->rightChild = p;
    }
    //新插入點的bf為0,關鍵是棧中的平衡因子的調整
/////////////////////////////////////////////////////// 以上完成插入工作
    while(!st.empty()){  //棧不空,出棧頂元素
        parent = st.top();
        st.pop();

        if(p == parent->leftChild){   //判斷插入的是父節點的左/右孩子,
            parent->bf--;           //讓其bf++/--;
        }else{
            parent->bf++;
        }

        //以下判斷棧中的平衡因子,看是否需要進行旋轉調整
        if(parent->bf == 0){  //bf=0,直接跳出循環
            break;
        }
        if(parent->bf==1 || parent->bf==-1){ 
            p = parent;  //此時在向上走,判斷bf;
        }else{  //以下的bf為2/-2;利用標志判斷左右旋;
            sign = parent->bf > 0 ? 1 : -1;
            if(p->bf == sign){  //符號相同為單旋
                if(sign == 1){  //為1左旋
                    RotateL(parent);  
                }else{
                    RotateR(parent); //右旋
                }
            }else{  //符號不同,為雙旋
                if(sign == 1){  
                    RotateRL(parent); //為1右左
                }else{
                    RotateLR(parent);
                }
            }
/*
    以下方法也可以判斷左右旋
        else
        {
            if(parent->bf < 0)  //左邊
            {
                if(p->bf<0 && p==parent->leftChild)    //    / 只能是左孩子
                {
                    //RotateR(parent);
                }
                else if(p->bf>0 && p == parent->leftChild)  //   <
                {
                    //RotateLR(parent);
                }
            }
            else
            {
                if(p->bf>0 && p==parent->rightChild)   //   \ 
                {
                    //RotateL(parent);
                }
                else if(p->pf<0 && p==parent->rightChild)  //      >
                {
                    //RotateRL(parent);
                }
            }
        }

*/
    break;
        }
    }

    if(st.empty()){  //通過旋轉函數,此時parent指向根節點;
        t = parent;  //此時調到棧底了,旋轉后將更改root的指向
    }else{
        AVLNode<Type> *tmp = st.top();  //當前的棧頂結點
        if(parent->data < tmp->data){  
            tmp->leftChild = parent;
        }else{
            tmp->rightChild = parent;
        }
    }

    return true;
}

template<typename Type>
bool AVLTree<Type>::remove(AVLNode<Type> *&t, const Type &x){
    AVLNode<Type> *p = t;
    AVLNode<Type> *parent = NULL;  //父結點
    AVLNode<Type> *q = NULL;  //刪除結點的輔助結點
    stack<AVLNode<Type> *> st;

    AVLNode<Type> *ppr; //爺爺結點

    int flag = 0;
    while(p != NULL){
        if(p->data == x){
            break;
        }
        parent = p;
        st.push(parent);
        if(x < p->data){
            p = p->leftChild;
        }else{
            p = p->rightChild;
        }
    } //以上是:查找刪除點
    if(p == NULL){  //沒有要刪除的結點
        return false;
    }
    if(p->leftChild!= NULL && p->rightChild!=NULL){
        parent = p;
        st.push(parent);

        q = p->leftChild;
        while(q->rightChild != NULL){
            parent = q;
            st.push(parent);
            q = q->rightChild;
        }

        p->data = q->data;
        p = q;
    }
    
    if(p->leftChild != NULL){
        q = p->leftChild;
    }else{
        q = p->rightChild;
    }
//以上是:使其要刪除的轉化為只有一個分支的
    if(parent == NULL){  //刪除的是根結點,并且無入棧,代表只有一個分支,并沒有尋找
        t = q;  
    }else{
        if(parent->leftChild == p){
            flag = 0;
            parent->leftChild = q;
        }else{
            flag = 1;
            parent->rightChild = q;
        }

        while(!st.empty()){
            parent = st.top();
            st.pop();
            if(parent->leftChild==q){ //對要刪除的父節點更改bf;
                parent->bf++;
            }else{
                parent->bf--;
            }
            if(!st.empty()){
                ppr = st.top();
                if(ppr->leftChild == parent){
                    flag = 0;
                }else{
                    flag = 1;
                }
            }
            if(parent->bf==-1 || parent->bf==1 ){
                break; //刪除前的平衡因子為0,此時不用再調整其它平衡因子
            }

            if(parent->bf == 0){  //原先只有左孩子/右孩子
                q = parent; //往上回溯更改爺爺結點的bf;
            }else{  //此時到達2,已經不平衡了,的進行旋轉化的調整
                if(parent->bf < 0){
                    flag = -1;
                    q = parent->leftChild;
                }else{
                    flag = 1;
                    q = parent->rightChild;
                }
                if(q->bf == 0){
                    if(flag == -1){
                        
                    }
                }
                if(parent->bf > 0){
                    q = parent->rightChild;
                    if(q->bf == 0){
                        RotateL(parent);
                    }else if(q->bf > 0){
                        RotateL(parent);
                    }else{
                        RotateRL(parent);
                    }
                }else{
                    q = parent->leftChild;
                    if(q->bf == 0){
                        RotateR(parent);
                    }else if(q->bf < 0){
                        RotateR(parent);
                    }else{
                        RotateLR(parent);
                    }
                }
            }
        }
        if(st.empty()){
            t = parent;  //直接更改root
        }else{
            AVLNode<Type> *tmp = st.top();  //當前的棧頂結點使其的左/右指向parent(是旋轉化后的根);
            if(parent->data < tmp->data){  
                tmp->leftChild = parent;
            }else{
                tmp->rightChild = parent;
            }
        }

    }

    delete p;  //刪除結點;
    return true;
}
#endif

  (2)、測試代碼

#include"avlTree.h"

int main(void){
    int ar[] = {16, 3, 7, 11, 9, 26, 18, 14, 15,};
    int n = sizeof(ar) / sizeof(int);
    AVLTree<int> avl;

    for(int i = 0; i < n; i++){
        avl.insert(ar[i]);
    }

    cout<<"刪除前: "<<endl;
    avl.inOrder();
    avl.remove(16);
    cout<<"刪除后: "<<endl;
    avl.inOrder();
    return 0;
}

  (3)、測試結果

AVL樹之刪除算法

AVL樹之刪除算法




向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

赫章县| 咸阳市| 汉阴县| 梨树县| 安新县| 扶绥县| 门头沟区| 正阳县| 安顺市| 山阴县| 新泰市| 通江县| 乐亭县| 如东县| 济宁市| 儋州市| 淄博市| 丰城市| 方正县| 高阳县| 格尔木市| 泸溪县| 光泽县| 乌海市| 宣武区| 北海市| 太原市| 华池县| 东阳市| 柯坪县| 乐清市| 乡城县| 北京市| 丹阳市| 玉溪市| 满城县| 金寨县| 会宁县| 无为县| 浦县| 龙口市|