繁体   English   中英

从二叉树错误中删除

[英]Deleting from Binary Tree error

我写了一个小代码来检测二叉树中的最大数字,它工作得很好,很简单,它可以深入到最后一个右节点(以防万一),然后我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();
  }

实际的删除功能在//注释中,因此我可以运行该编。

您正在删除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情况(因为如果子指针为null则总是返回):

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

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

您还需要确保父节点仍未指向已删除的子节点(由于您未发布太多代码,因此很难确切地了解正在发生的情况)。

您不能简单地delete不需要的对象-您还必须删除用于查找要删除的节点的引用。 而且,如果节点有任何子节点,则必须将子节点重新连接到树的其他位置,以使它们保持可访问性。

使它变得如此棘手的是,您必须正确更新:父级对要删除的节点的引用; 被删除节点之一的“子”指针之一; 以及来自已删除节点的两个子节点的父节点链接。 如果执行更新外的顺序,你会读到一个陈旧的指针,也许损坏内存,所以你必须等待,直到你不需要从节点内的任意多个引用删除节点,你已经删除引用其他地方的节点。

更新

不要忘记“最后一个正确的节点”实际上可以成为树的根:

    5
   4
  3
 2
1

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

除非您要进行一些重新平衡,否则我们不会在这里看到。 如果是这样,请确保您也处理这种情况:

 2
1

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

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

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

您可以发布整个程序,以便对其进行编译。 但是基本上的问题是,当theRoot-> rChildptr为NULL时,您将删除theRoot,然后您的return语句将尝试返回指向无处的theRoot-> data。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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