二叉搜尋樹如何刪除節點

君莫呵呵笑發表於2020-11-24


一、怎麼刪除二叉搜尋樹節點

一般要分三種情況,一種是要被刪除的節點沒有子節點,這時直接刪除就可以了,第二種情況時有一個子節點,這時,如果左邊有節點就將左邊的節點給要被刪除的節點的父節點,如果右邊有節點就將右邊的節點給要被刪除的節點的父節點。其實可以看出,這兩種情況可以合併成一種,因為第一種情況可以當成有兩個空節點,選誰都沒事,可以相容第二種情況。

最主要的是第三種情況,當被刪除的節點有兩個子節點時,其實有兩個答案,一種是選擇右子樹中最小的節點來代替被刪除的節點,因為是右邊子樹最小的節點,那它必定沒有左子樹,直接簡化成了只有一個節點的情況。另一個答案是選擇左子樹中最大的節點,同理。

以下程式碼是選的右子樹最小節點來作為答案的

二、二叉搜尋樹刪除程式碼

程式碼如下:

#include <iostream>
#include<bits/stdc++.h>
using namespace std;
struct Node{
    int key;
    Node *right,*left,*parent;
};
Node *root,*NIL;
//尋找傳入節點右邊最小值節點
Node *treeMinimum(Node *x){
while(x->left!=NIL)x=x->left;
return x;
}
//尋找節點
Node *find(Node *u,int k){
while(u!=NIL&&k!=u->key){
    if(k<u->key) u=u->left;
    else u=u->right;
}
return  u;
}
//返回節點右邊最小節點
Node *treeSuccessor(Node *x){

    return treeMinimum(x->right);

}

void treeDelete(Node *z){
    Node *y;//要刪除的節點
    Node *x;//y的子節點
    if(z->left==NIL||z->right==NIL){
        y=z;//包括了需要刪除的節點沒有子節點和只有一個子節點的情況
    }else{
    y=treeSuccessor(z);
    //子節點有兩個時的情況
    }

    //當需要刪除的節點沒有子節點,預設選右邊空節點
    //當有一個子節點時,左邊有就存左邊進x,右邊有就存右邊進x
    //當有兩個節點時得到的y肯定左邊是空的。
    if(y->left!=NIL){
        x=y->left;
    }else{
    x=y->right;
    }

    //當沒有子節點的情況時,因為空節點不用管父母節點所以跳過
    //不為空時,x開始選新的父節點
    if(x!=NIL){
        x->parent=y->parent;
    }

    if(y->parent==NIL){
        root=x;
        //當需要被刪除的點為頭節點時
    }else{
    if(y==y->parent->left){
        y->parent->left=x;
        //刪掉的是左節點時
    }else{
    y->parent->right=x;
    //右節點時
    }
    }

    if(y!=z){
        z->key=y->key;
        //有兩個節點時的情況,將值付到該到的位置
    }
    free(y);
}
void insert(int k){
    Node *y=NIL;
    Node *x=root;
    Node *z;

    z=(Node *)malloc(sizeof(Node));
    z->key=k;
    z->left=NIL;
    z->right=NIL;
    while(x!=NIL){
        y=x;
        if(z->key>x->key){
            x=x->right;
        }else{
        x=x->left;
        }
    }
    z->parent=y;
    if(y==NIL){
        root=z;
    }else{
    if(z->key>y->key){
        y->right=z;
    }else{
    y->left=z;
    }
    }

}
void inorder(Node *u){
    if(u==NIL) return;
    inorder(u->left);
    printf(" %d",u->key);
    inorder(u->right);
}
void preorder(Node *u){
    if(u==NIL) return;
    printf(" %d",u->key);
    preorder(u->left);
    preorder(u->right);
}
int main()
{
    int n,i,x;
    string com;
    scanf("%d",&n);
    for(i=0;i<n;i++){
        cin>>com;
        if(com[0]=='f'){
            scanf("%d",&x);
            Node *t=find(root,x);
            if(t!=NIL) printf("yes\n");
            else printf("no\n");
        }else if(com=="insert"){
        scanf("%d",&x);
        insert(x);
        }else if(com=="print"){
        inorder(root);
        printf("\n");
        preorder(root);
        printf("\n");
        }else if(com=="delete"){
        scanf("%d",&x);
        treeDelete(find(root,x));
        }
    }
    return 0;
}

相關文章