从二叉树中删除错误

时间:2011-11-19 09:52:46

标签: c++ binary-tree

我写了一个小代码来检测二叉树中最大的数字,它工作得很好,很简单,它远远到最后一个节点(叶子以防)然后我只是cout<<它,现在我想删除它,我看起来通过一些类似的问题,但我只需要删除我从搜索返回的数字,但我的编程只是崩溃后我运行它列出树得到数字,删除和尝试再次列出它。

这是我的搜索:

    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;

    } 

以下是完整代码:

#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();
  }

实际删除功能在//注释中,所以我可以运行prog。

3 个答案:

答案 0 :(得分:3)

您正在删除theRoot,然后尝试取消引用它。如果要返回存储在节点中的值,则需要首先制作本地副本,如下所示:

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

return thetRoot->data;行是否属于else语句的一部分?如果是这样,你需要在它周围添加括号:

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

或者只是简单地删除else case(因为如果子指针为null,你总是返回):

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

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

您还需要确保父节点仍然没有指向已删除的子节点(很难确切地看到发生了什么,因为您没有发布太多代码)。

答案 1 :(得分:2)

您不能简单地delete您不想要的对象 - 您还必须删除用于查找您要删除的节点的参考。并且,如果节点有任何子节点,则必须将子节点重新附加到树的其他位置,以便它们保持可访问状态。

让它变得如此棘手的是你必须正确更新:父对被删除节点的引用;其中一个孩子&#39;已删除节点的一​​个子节点的指针;和来自已删除节点的两个子节点的父链接。如果您无序地执行更新,您将读取陈旧的指针并可能损坏内存,因此您必须等待删除节点,直到您不再需要节点内的任何其他引用,并且您已经从其他地方删除了节点的引用。

<强>更新

别忘了&#34;最后一个正确的节点&#34;实际上可以成为树的根源:

    5
   4
  3
 2
1

5是树中最大,最右边的节点,如果删除它,就会丢失整棵树。

除非你正在做一些我们在这里看不到的重新平衡;如果你是,请确保你也处理这种情况:

 2
1

我们Wikipedia的朋友非常友好地分析了如何从二叉搜索树中删除节点:

  
      
  • 删除一个叶子(没有子节点的节点):删除一个叶子很容易,因为我们可以简单地从树上删除它。
  •   
  • 删除包含一个子节点的节点:删除节点并将其替换为其子节点。
  •   
  • 删除具有两个子节点的节点:调用要删除的节点N.不要删除N.而是选择其有序后继节点   或者它的有序前导节点R.用N替换N的值   R的值,然后删除R.
  •   

您的删除代码必须处理所有这三种情况。不要忘记您正在删除的节点可能是树的根,而没有父节点。

答案 2 :(得分:0)

你可以发布整个程序,以便编译它。但基本上问题是,当theRoot-&gt; rChildptr为NULL时,你正在删除theRoot然后你的return语句试图返回指向无处的Root-&gt;数据。