简体   繁体   中英

Deleting from Binary Tree error

I wrote a small code to detect the largest number in the binary tree, it is working just fine, its simple, it goes far down to the last right node(leaf in case) and then i just cout<< it, now i would like to delete it, i looked trough some similar question, but i only need to delete the number i got back from the search, but my prog just crashes after i run it list the tree get the number, delete and try to list it again.

Here is my search:

    T Remove( Node* theRoot)
        {
        if ( root == NULL )
        {
             cout<<"There is no tree";
             return -1;
        }

        if (theRoot->rChildptr != NULL)
            return Largest(theRoot->rChildptr);
        else
             delete theRoot;
             return theRoot->data;

    } 

Here is the full code:

#include <iostream>
#include <string>
#include <cstdlib> 


using namespace std;


template<class T>
class BinaryTree
{

struct Node
    {
        T data;
        Node* lChildptr;
        Node* rChildptr;

        Node(T dataNew)
        {
            data = dataNew;
            lChildptr = NULL;
            rChildptr = NULL;

        }
    };
private:
    Node* root; 

        void Insert(T newData, Node* &theRoot)
        {
            if(theRoot == NULL) 
            {
                theRoot = new Node(newData);
                return;
            }

            if(newData < theRoot->data)  
                Insert(newData, theRoot->lChildptr);
            else
                Insert(newData, theRoot->rChildptr);
        }

        void PrintTree(Node* theRoot)
        {
            if(theRoot != NULL)
            {
                PrintTree(theRoot->lChildptr);
                cout<< theRoot->data<<" \n";
                PrintTree(theRoot->rChildptr);
            }
        }
        T Largest( Node* theRoot)
            {
            if ( root == NULL )
            {
                 cout<<"There is no tree";
                 return -1;
            }

            if (theRoot->rChildptr != NULL)
                return Largest(theRoot->rChildptr);
            else
                 delete theRoot;
                 return theRoot->data;

        }
        T Remove(Node* theRoot)
        {
            if ( root == NULL )
            {
                 cout<<"There is no tree";
                 return -1;
            }

            if (theRoot->rChildptr != NULL)
                return Largest(theRoot->rChildptr);
            else
                delete theRoot;
                 return ;
        };

    public:
        BinaryTree()
        {
            root = NULL;
        }

        void AddItem(T newData)
        {
            Insert(newData, root);
        }

        void PrintTree()
        {
            PrintTree(root);
        }
        T Largest()
        {
            return Largest(root);
        }
        //void Remove()
        //{
        //  Remove(root);
        //}

    };

    int main()
    {
        BinaryTree<int> *myBT = new BinaryTree<int>();
        myBT->AddItem(2);
        myBT->AddItem(20);
        myBT->AddItem(5);
        myBT->AddItem(1);
        myBT->AddItem(10);
        myBT->AddItem(15);
            //for(int i = 0; i < 10; i++)           //randommal tolti fel
                //myBT->AddItem(rand() % 100);
        cout << "BinaryTree:" << endl;              //kilistazaa a fat
        myBT->PrintTree();
        cout << "Largest element: " << myBT->Largest() << endl;  //visszaadja a legnagyobb elemet
        //myBT->Remove();
        myBT->PrintTree();
  }

the actual delete function is in // comments so i can run the prog.

You are deleting theRoot and then trying to dereference it. If you want to return the value stored in the node you need to make a local copy first like this:

T value = theRoot->data;
delete theRoot;
return value;

Is the return thetRoot->data; line intended to be part of the else statement? If so you need to add brackets around it like this:

if (theRoot->rChildptr != NULL)
{
    return Largest(theRoot->rChildptr);
}
else
{
    T value = theRoot->data;
    delete theRoot;
    return value;
}

Or simply remove the else case altogether (since you always return if the child pointer is null):

if (theRoot->rChildptr != NULL)
{
    return Largest(theRoot->rChildptr);
}

T value = theRoot->data;
delete theRoot;
return value;

You will also need to make sure that the parent node does not still point to a deleted child (hard to see exactly what is going on because you haven't posted much code).

You cannot simply delete the object you don't want -- you must also remove the reference you used to find the node that you are deleting. And, if the node has any children, you must reattach the child nodes elsewhere to the tree so that they remain reachable.

The thing that makes it so tricky is that you have to properly update: the parent's reference to the node being deleted; one of the 'child' pointers for one of the children of the deleted node; and the parent links from both children of the deleted node. If you perform the updates out-of-order, you'll read a stale pointer and perhaps corrupt memory, so you must wait to remove nodes until you do not need any more references from within the node and you've removed references to the node from elsewhere.

Update

Don't forget that "the last right node" can in fact be the root of your tree:

    5
   4
  3
 2
1

5 is the largest, right-most, node of your tree, and if you delete it, you've lost your entire tree.

Unless you're doing some re-balancing that we're not seeing here; if you are, be sure you also handle this case:

 2
1

Our friends at Wikipedia have been very kind to analyze how to delete a node from a binary search tree:

  • Deleting a leaf (node with no children): Deleting a leaf is easy, as we can simply remove it from the tree.
  • Deleting a node with one child: Remove the node and replace it with its child.
  • Deleting a node with two children: Call the node to be deleted N. Do not delete N. Instead, choose either its in-order successor node or its in-order predecessor node, R. Replace the value of N with the value of R, then delete R.

Your delete code must handle all three of these cases. Don't forget that the node you're deleting might be the root of the tree and not have a parent node.

Can you post the entire program so that it can be compiled. But basically the problem is that when theRoot->rChildptr is NULL you are deleting theRoot and then your return statement tries to return theRoot->data which is pointing to nowhere.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM