2014-05-05 52 views
0

我有這個問題,當我嘗試刪除(使用選擇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

要求人們發現代碼中的錯誤並不是特別有效。您應該使用調試器(或者添加打印語句)來分析問題,追蹤程序的進度,並將其與預期發生的情況進行比較。只要兩者發生分歧,那麼你就發現了你的問題。 (然後,如果有必要,你應該構建一個[最小測試用例](http://stackoverflow.com/help/mcve)。) –

+0

@OliCharlesworth你可以看看輸出! – User

回答

2

當刪除在樹上的一個節點,你必須正確地管理它的孩子。在這裏,您正在刪除節點以及指向其子節點的指針。您需要找到一種方法將剩餘的孩子添加回樹中。

2

當您使用刪除操作符時,爲該對象(本例中爲節點)分配的內存正在釋放。 在功能deleteTree找到節點和dealocate它的內存,但指針指向節點(從它的父節點)是不是被重新設置爲NULL它「掛起」指向其他的東西,然後空。所以,當你使用遞歸來打印樹時,你打印根,你檢查左樹(它不是NULL),你調用遞歸來打印沒有意義的東西,然後繼續遞歸,知道多少次。

此外,當您刪除子樹,你應該使用遞歸來刪除所有節點在樹,不只是樹的根(和上面一樣,指針設置爲子樹爲NULL) ,從而釋放爲該子樹保留的整個內存。

0

正如你所說,刪除樹中的節點可能會導致內存泄漏。 例如,如果您有這棵樹: A-> B
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; 
    } 
} 

注意初始化時不要忘記空指針。另外,如果你想在現實生活中使用二叉樹,不要忘記std :: map是一棵二叉樹。

祝您有個愉快的日子