删除二叉树节点的正确方法

时间:2014-05-05 21:25:13

标签: c++ binary-tree

我有这个问题,当我尝试删除(使用选项5)具有id 101的节点并且想要打印剩余的两个节点(使用id 100,102)。我的程序打印(使用选项2)100正确,但其余的产生一些垃圾值和程序停止工作?

我怀疑某些内存管理问题,有人可以采取正确的方法来做到这一点。

#include<stdlib.h>
#include<stdio.h>
#include <iostream>
#include <iomanip> 
using namespace std;
struct bin_tree
{
    int Uid;
    int data;
    bool flag_add;
    bool flag_change;
    bool flag_delete;
    struct bin_tree * right, * left;

};
typedef struct bin_tree node;

void insert(node ** tree,int ID, int val,bool new_data, bool change_data, bool delete_data)
{
    node *temp = NULL;
    if(!(*tree))
    {
        temp = new node;
        temp->left =  NULL;
        temp->right = NULL;
        temp->Uid=ID;
        temp->data = val;
        temp->flag_add= new_data;
        temp->flag_change=change_data;
        temp->flag_delete=delete_data;
        *tree = temp;
        return;
    }else
    {

        if(val < (*tree)->data)
        {
            insert(&(*tree)->left, ID, val,new_data, change_data, delete_data);
        }
        else
        {
            insert(&(*tree)->right,ID, val,new_data, change_data, delete_data);
        }
    }
}

void print_preorder(node * tree, int indent=0)
{

    cout<<"GUID"<<tree->Uid <<"D"<< tree->data <<"NF"<<tree->flag_add<<"CF"<<tree->flag_change<<"DF"<<tree->flag_delete<< "\n ";


    if (tree!= NULL)
    {
        if(tree->left) print_preorder(tree->left, indent+2);

        if(tree->right) print_preorder(tree->right, indent+2);

        if (indent)
        {
            std::cout << std::setw(indent) << ' ';
        }

    }
}





node* search(node ** tree, int ID)
{
    if(!(*tree))
    {
        return NULL;
    }

    if(ID < (*tree)->Uid)
    {
        search(&((*tree)->left), ID);
    }
    else if(ID > (*tree)->Uid)
    {
        search(&((*tree)->right), ID);
    }
    else if(ID == (*tree)->Uid)
    {
        return *tree;
    }
}
node*  update(node ** tree,int ID, int val,bool new_data, bool change_data, bool delete_data)
{
    (*tree)->Uid = ID;
    (*tree)->data = val;
    (*tree)->flag_add= new_data;
    (*tree)->flag_change= change_data;
    (*tree)->flag_delete= delete_data;

    return *tree;


}


void change(node ** tree,int ID, int val,bool new_data, bool change_data, bool delete_data)
{

    node *temp;
    node* updt;

    temp = search(&(*tree), ID);

    if(temp)
    {
        cout<<"ID is found"<<endl;
        cout<<"Node current data is "<<temp->Uid<<temp->data<<temp->flag_add<<temp->flag_change<<temp->flag_delete<<endl;
        if(updt = update(&temp,ID, val, new_data, change_data, delete_data))
        {
            cout<<"Node updated data is "<<updt->Uid<<updt->data<<updt->flag_add<<updt->flag_change<<updt->flag_delete;
        }else
        {
            cout<<"data couldnt be updated"<<endl;
        }
    }else
    {
        cout<<"sorry data is not found"<<endl;

    }


}

int deltree(node ** tree, int id)
{
    node *del_node;
    del_node= search( &(*tree), id);
    if(del_node)
    {
        delete del_node;

    }
    return 0;
}

int main()
{
    node *root;
    node *tmp;
    int number;
    int id;



    root = NULL;
    int UID;
    int Data;
    bool n_flag;
    bool c_flag;
    bool d_flag;
    /* Inserting nodes into tree */

    while(1)
    {
        cout<<endl<<endl;
        cout<<" Binary Search Tree Operations "<<endl;
        cout<<" ----------------------------- "<<endl;
        cout<<" 1. Insertion/Creation "<<endl;
        cout<<" 2. Pre-Order Traversal "<<endl;
        cout<<" 3. Removal "<<endl;// actually its for searching not for removal
        cout<<" 4. change "<<endl;
        cout<<" 5. delete "<<endl;
        cout<<" 6. EXIT "<<endl;

        cout<<" Enter your choice : ";
        cin>>number;
        switch(number)
        {
        case 1:

            /*cout<<"enter the number GUID"<<endl;
            cin>>UID;
            cout<<"enter the Data you want"<<endl;
            cin>>Data;
            cout<<"is New data ?"<<endl;
            cin>>n_flag;
            cout<<"is changed data?"<<endl;
            cin>>c_flag;
            cout<<"is delete data ?"<<endl;
            cin>>d_flag;*/

            /*  insert(&root,UID, Data, n_flag, c_flag,d_flag);*/

            insert(&root,100, 700, 1, 0,0);
            insert(&root,101, 701, 1, 0,0);
            insert(&root,102, 702, 1, 0,0);
            break;

        case 2:
            /* Printing nodes of tree */
            cout<<"Pre Order tree Display";
            print_preorder(root);
            break;

        case 3:

            /* Search node into tree */
            tmp = search(&root, 4);
            if (tmp)
            {
                printf("Searched node=%d\n", tmp->data);
            }
            else
            {
                printf("Data Not found in tree.\n");
            }
            break;
        case 4:

            cout<<"enter the number GUID"<<endl;
            cin>>UID;
            cout<<"enter the Data you want"<<endl;
            cin>>Data;
            cout<<"is New data ?"<<endl;
            cin>>n_flag;
            cout<<"is changed data?"<<endl;
            cin>>c_flag;
            cout<<"is delete data ?"<<endl;
            cin>>d_flag;

            change (&root,UID, Data, n_flag, c_flag,d_flag);

            break;
        case 5:
            cout<<"enter the node id to be deleted";
            cin>>id;
            int m;
            m = deltree(&root, id);
            if(m) cout<<"Node_Deleted";
            break;
        case 6 :
            return 0;

        }

    }
}

输出

enter image description here

3 个答案:

答案 0 :(得分:2)

删除树中的节点时,必须正确管理其子节点。在这里,您将删除节点以及指向其子节点的指针。您需要找到一种方法将剩余的孩子添加回树中。

答案 1 :(得分:2)

使用delete运算符时,将释放为该对象(在本例中为节点)分配的内存。 在函数deleteTree中,您找到节点并处理它的内存,但指向该节点的指针(来自其父节点)未被重置为NULL 它&#34;挂起&#34; 指向除了NULL之外的其他内容。因此,当你使用递归打印树,你打印root,你检查左树(它不是NULL)和你调用递归打印没有意义的东西,你继续谁知道多少次递归

此外,当您删除子树时,您应该使用递归来删除该树中的所有节点,而不仅仅是树的根(如上所述,将指向该子树的指针设置为NULL),从而释放为该子树保留的整个内存。

答案 2 :(得分:0)

正如您所说,删除树中的节点可能会导致内存泄漏。 例如,如果你有这棵树: A-&GT;乙
A-&以及c
如果删除A,则对B和C的引用将丢失。

您可以使用valgrind(linux)或purify(windows)来检查它。

修复它的一种方法是在你的结构中实现析构函数: 递归将自动处理。

struct bin_tree
{
    int Uid;
    int data;
    bool flag_add;
    bool flag_change;
    bool flag_delete;
    struct bin_tree * right, * left;

    bin_tree() : right(nullptr), left(nullptr) {}
    ~bin_tree()
    {
        delete right;
        delete left;
    }
}

NB不要忘记初始化时的空指针。 另外,如果你想在现实生活中使用二叉树,不要忘记std :: map是二叉树。

度过美好的一天