鍍金池/ 問(wèn)答/人工智能  C  C++/ 二叉查找樹刪除與遍歷沖突

二叉查找樹刪除與遍歷沖突

在刪除前,遍歷程序運(yùn)行正常。單獨(dú)運(yùn)行刪除程序也不報(bào)錯(cuò)。但是如果在刪除后遍歷,程序就會(huì)陷入無(wú)限循環(huán),報(bào)錯(cuò)退出。是否在Delete函數(shù)的最后的delete使用不當(dāng)?如果不用delete,直接把刪除節(jié)點(diǎn)置空,就無(wú)法刪除節(jié)點(diǎn)。應(yīng)該怎么處理?可能這個(gè)問(wèn)題有點(diǎn)簡(jiǎn)單,希望大家?guī)臀医鉀Q一下。接觸c語(yǔ)言時(shí)間不長(zhǎng),程序書寫過(guò)程中有哪些問(wèn)題,如果大家發(fā)現(xiàn)了也可以和我說(shuō)一下,感謝。

#include<stdio.h>
#include<stdlib.h>
typedef struct TreeNode{
    int data;
    struct TreeNode *left;
    struct TreeNode *right;
}ST,*PST;
void InitTree(PST &T)
{
    T = NULL;
}
PST Insert(PST &T,int e)
{
    if (T==NULL)
    {
        T = (PST)malloc(sizeof(ST));
        if(T==NULL)
            {printf("Wrong!");return NULL;}
        else
        {
            T->data = e;
            T->left = T->right = NULL;
        }
    }
    else if (e<T->data)
        T->left = Insert(T->left,e);
    else
        T->right = Insert(T->right,e);
    return T;
}
void CreateTree(PST &T){
    int i,num,elem;
    printf("Please enter the number of the nodes in your tree:");
    scanf("%d",&num);
    for(i=0;i<num;i++)
    {
        scanf("%d",&elem);
        T = Insert(T,elem);
    }
}
PST Find(PST T,int e)
{
    if(T==NULL) return NULL;
    if (T->data == e)
        return T;
    else if (e<T->data)
        return Find(T->left,e);
    else if (e>T->data)
        return Find(T->right,e);
    return NULL;
}
PST FindMax(PST T)
{
    while(T->right != NULL)
        T = T->right;
    return T;
}
PST FindMin(PST T)
{
    while(T->left != NULL)
        T = T->left;
    return T;
}
PST Delete(PST &T,int e)
{
    PST new_one;
    if (T==NULL) return NULL;
    else if (e<T->data)
        T->left = Delete(T->left,e);
    else if (e>T->data)
        T->right = Delete(T->right,e);
    else if (T->left&&T->right)
    {
        new_one = FindMin(T->right);
        T->data = new_one->data;
        T->right = Delete(T->right,T->data);
    }
    else
    {
        new_one = T;
        if(T->left) T=T->left;
        else if (T->right) T = T->right;
        delete new_one;
        new_one = NULL;
    }
    return T;
}
void PrintT(PST T){
    if(T!=NULL)
    {
        printf("%-3d",T->data);
        PrintT(T->left);
        PrintT(T->right);
    }
}
int main()
{
    PST BigTree;
    InitTree(BigTree);
    CreateTree(BigTree);
    PrintT(BigTree);
    Find(BigTree,7);
    Delete(BigTree,7);
    PrintT(BigTree);
    return 0;
}

這樣改也是無(wú)法刪除節(jié)點(diǎn),但能正常遍歷:

PST Delete(PST &T,int e)
{
    PST new_one;
    if (T==NULL) return NULL;
    else if (e<T->data)
        T->left = Delete(T->left,e);
    else if (e>T->data)
        T->right = Delete(T->right,e);
    else if (T->left&&T->right)
    {
        new_one = FindMin(T->right);
        T->data = new_one->data;
        T->right = Delete(T->right,T->data);
    }
    else
    {
        new_one = T;
        if(T->left) T=T->left;
        else if (T->right) T = T->right;
        new_one = NULL;
        delete new_one;
    }
    return T;
}
回答
編輯回答
巴扎嘿

delete的else分句里沒(méi)有考慮兩個(gè)子節(jié)點(diǎn)都是空的情況

2018年4月28日 22:01
編輯回答
局外人

上面的答案說(shuō)的沒(méi)錯(cuò),沒(méi)有考慮左右都是空的情況,可以參考下面的代碼:

template<typename T>
bool BTree<T>::deleteNode(const T &value, Node *&node) {
    if (node == nullptr) {
        return false;
    } else if (value < node->value) {
        return deleteNode(value, node->left);
    } else if (value > node->value) {
        return deleteNode(value, node->right);        
    } else {
        if (node->left == nullptr && node->right == nullptr) {
            delete node;
            node = nullptr;
        } else if (node->left == nullptr) {
            Node *t = node;
            node = node->right;
            delete t;
        } else if (node->right == nullptr) {
            Node *t = node;
            node = node->left;
            delete t;
        } else {
            Node *to_del = node->left, *before = node;
            while (to_del->right != nullptr) {
                before = to_del;
                to_del = to_del->right;
            }
            if (before == node) {
                delete node;                
                node = to_del;
            } else {
                node->value = to_del->value;
                before->right = to_del->left;
                delete to_del;
            }
        }
        return true;
    }
}

這是我以前寫的刪除二叉樹節(jié)點(diǎn)的的代碼。

2018年5月26日 23:35