簡體   English   中英

如何刪除特定節點是二叉搜索樹?

[英]How to remove Specific Node is Binary Search Tree?

我正在嘗試刪除特定的節點,但看不到問題出在哪里。

實際上,我是通過Find()獲取Node的,然后使用Remove()刪除它。

每當Delete()觸發時,程序就會崩潰。

bool RemoveNode(int key)
{
    if (IsEmpty())
        return false;
    Node* r = Find(key,root);
    if (r==nullptr)
        return false;
    return Remove(r);
}
bool Remove (Node* &r)
{
    if (r->left==nullptr && r->right ==nullptr)
    {
        delete r;
        r=nullptr;
        return true;
    }
    if (r->left==nullptr)
    {
        Node* temp = r->right;
        delete r;
        r=nullptr;
        r=temp;
        return true;
    }
    if (r->right==nullptr)
    {
        Node* temp = r->left;
        delete r;
        r=nullptr;
        r=temp;
        return true;
    }
    Node* Max = FindMax(r->left);
    r->data = Max->data;
    Remove(Max);

    return true;
}
Node* FindMax(Node* r)
{
    if(r->right==nullptr)
        return r;
    return FindMax(r->right);
}
Node* Find(int key, Node* &r)
{
    if (r==nullptr)
        return nullptr;

    if (r->data==key)
        return r;

    if (key < r->data)
        return Find(key,r->left);
    else
        return Find(key,r->right);
}

顯然,您的Remove()函數旨在修改指向節點的指針,而與節點的位置無關:您無需傳遞原始指針,而是傳遞對指針的引用。 這樣,您可以更新樹的root指針,將其leftright作為下一個的組成部分。 只要您在正確的引用中通過它,我認為代碼就應該起作用。

變量r實際上是在Remove()修改的,它是RemoveNode()定義的局部變量: Find()的結果是一個指針,而不是對相關指針的引用。 但是,您需要修改樹形結構中指向節點的指針,而不是任意的局部變量。

解決方法是使用Find()' which correctly returns a reference to the pointer rather than the pointer itself. Your recursive的特殊版本,該版本Find()' which correctly returns a reference to the pointer rather than the pointer itself. Your recursive Find()' which correctly returns a reference to the pointer rather than the pointer itself. Your recursive Find() would be up to the task if it returned a Node *& rather than a Node *`, would be up to the task if it returned a 由於您的樹似乎並不平衡並且堆棧空間相對有限,因此我寧願使用非遞歸函數。 與其返回對指針的引用,不如保留指向當前節點的指針而不是指向該節點的指針:

Node** InternFind(int key) {
    Node** n = &this->root;
    while (*n && (*n)->key != key) {
        n = &(key < (*n)->key? (*n)->left: (*n)->right);
    }
    return n;
}

該代碼未經測試,可能不太正確。 但是,一旦獲得指向該暫存器的指針,就可以對其進行更新,而無需處理其來源:

Node** r = InternFind(key);
if (*r) {
    Remove(*r);
    return true;
}
else {
    return false;
}

雖然我不知道“如果Delete()會觸發”的含義,但我假設您對相同的指針p重復使用delete p存在問題。 該代碼可能在訪問失效節點之前就出錯了。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM