我有这个问题,当我尝试删除(使用选项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;
}
}
}
输出
答案 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是二叉树。
度过美好的一天