2010-07-24 220 views
0

我在C++實現二叉搜索樹二叉搜索樹

#include <iostream> 
#include <cstdlib> 
using namespace std; 
class binary{ 

private: 
    struct tree{ 

     tree *left; 
     tree *right; 
     int data; 
      }; 
    tree *root; 
public: 
    binary(){ 

     root=NULL; 
      } 
    bool empty() { return root=NULL;} 
    void print_inorder(); 
    void inorder(tree*); 
    void print_preorder(); 
    void pre_order(tree*); 
    void print_postorder(); 
    void post_order(tree *); 
    void insert(int); 
    void remove(int); 


}; 
void binary::insert(int d){ 

    tree *t=new tree; 
    tree *parent; 
    t->data=d; 
    t->left=NULL; 
    t->right=NULL; 
    parent=NULL; 
    //is new tree; 
     if (empty()) root=t; 
     else{ 

      tree *current; 
      current=root; 
      //find Nod's parent 
      while (current){ 

       parent=current; 
       if (t->data>current->data) current=current->right; 
       else current=current->left; 
      } 
      if (t->data<parent->data) 
       parent->left=t; 
      else 
       parent->right=t; 


     } 


} 
void binary::remove(int d){ 
    //locate the element 
    bool found=true; 
    if (empty()){ 

     cout<<"tree is empty"<<endl; 
      return ; 

      } 

     tree *current; 
     tree *parent; 
     current=root; 
     while (current!=NULL){ 
      if (current->data==d){ 
       found=true; 
       break; 
      } 
      else{ 
       parent=current; 
       if (d>current->data) current=current->right; 
       else current=current->left; 
      } 
     } 

     if (!found){ 
      cout<<"data not found "<<endl; 
      return ; 
     } 


     //three case 

     // 1. We're removing a leaf node 
    // 2. We're removing a node with a single child 
    // 3. we're removing a node with 2 children 
     // Node with single child 
     if ((current->left==NULL && current->right!=NULL )||(current->left!=NULL && current->right==NULL)){ 

      if (current->left==NULL && current->right!=NULL){ 
       if(parent->left==current){ 
        parent->left=current->right; 
        delete current; 
       } 

       else{ 
        parent->right=current->right; 
        delete current; 
       } 
     } 
      else // left child present, no right child 
      { 
       if (parent->left==current){ 

        parent->left=current->left; 

        delete current; 
           } 


       else{ 
        parent->right=current->left; 
        delete current; 
       } 
     } 
        return ; 
} 

       if (current->left==NULL && current->right==NULL){ 

        if (parent->left==current) parent->left=NULL; 
        else parent->right==NULL; 
        delete current; 
        return ; 

       } 

       //node with 2 children 
       //replace node with smalles value in right subtree 
       if ( current->left!=NULL && current->right!=NULL){ 

        tree *ch; 
        ch=current->right; 
        if ((ch->left==NULL) &&(ch->right==NULL)) 
        { 

          current=ch; 
          delete ch; 
          current->right=NULL; 

        } 

         else// right child has children 
     { 
      //if the node's right child has a left child 
      // Move all the way down left to locate smallest element 
      if ((current->right)->left!=NULL){ 

       tree * rr; 
       tree * lr; 
       lr=current->right; 
       rr=(current->right)->left; 
       while (rr->left!=NULL){ 

        lr=rr; 
        rr=rr->left; 

       } 
       current->data=rr->data; 
       delete rr; 
       lr->left=NULL; 




      } 
      else 
      { 
       tree *tmp; 
       tmp=current->right; 
       current->data=tmp->data; 
       current->right=tmp->right; 
       delete tmp; 

         } 


       } 

         return; 
     } 



} 

       void binary::print_inorder(){ 

        inorder(root); 
       } 
       void binary::inorder(tree *p){ 
        if (p!=NULL){ 
         if (p->left) inorder(p->left); 
         cout<<" "<<p->data<<" "; 
         if (p->right) inorder(p->right); 
        } 
        else return ; 



        } 


       void binary::print_preorder(){ 

        pre_order(root); 


       } 
       void binary::pre_order(tree *p){ 

        if (p!=NULL){ 
         cout<<" "<<p->data<<" "; 
         if (p->left) pre_order(p->left); 
         if (p->right) pre_order(p->right); 


       } 

        else return ; 
       } 

       void binary::print_postorder(){ 

        post_order(root); 
       } 


       void binary::post_order(tree *p){ 

        if (p!=NULL){ 

         if (p->left) post_order(p->left); 
         if (p->right) post_order(p->right); 
         cout<<" "<<p->data; 
        } 
        else return ; 
       } 


int main(){ 


binary b; 
int ch,tmp,tmp1; 
while (1){ 
    cout<<endl<<endl; 
    cout<<" Binary Search Tree Operations "<<endl; 
     cout<<" ----------------------------- "<<endl; 
     cout<<" 1. Insertion/Creation "<<endl; 
     cout<<" 2. In-Order Traversal "<<endl; 
     cout<<" 3. Pre-Order Traversal "<<endl; 
     cout<<" 4. Post-Order Traversal "<<endl; 
     cout<<" 5. Removal "<<endl; 
     cout<<" 6. Exit "<<endl; 
     cout<<" Enter your choice : "; 

     cin>>ch; 
     switch(ch) 
     { 
     case 1: cout<<"enter number to be inserted:"; 
      cin>>tmp; 
      b.insert(tmp); 
      break; 
     case 2: cout<<endl; 
      cout<<"in order traversal"<<endl; 
      cout<<"------------------"<<endl; 
      b.print_inorder(); 
      break; 
     case 3: cout<<endl; 
      cout<<"pre order traversal "<<endl; 
      cout<<"------------------"<<endl; 
      b.print_preorder(); 
      break; 
     case 4: cout<<endl; 
      cout<<"post order traversal"<<endl; 
      cout<<"---------------------"<<endl; 
      b.print_postorder(); 
      break; 
     case 5: cout<<"enter data to be deleted:"; 
      cin>>tmp1; 
      b.remove(tmp1); 
      break; 
     case 6: 

    return 0; 
     } 
     } 


return 0; 

} 

它編譯罰款,但問題是這樣的:當我輸入選擇1好說輸入數字要插入我的例子7和節目說進入:

binary_tree exe has stopped working 
windows can check online for a solution to the problem 
check online for a solution and close program 
close program 

爲什麼?這種問題發生的原因是什麼?

+2

這就是通過調試器來幫助你,而不是讓我們爲你修復你的代碼。 – Joe 2010-07-24 13:00:09

回答

4

運行在Linux系統上GDB的代碼,這是報告的錯誤:

Program received signal SIGSEGV, Segmentation fault. 
0x080488ac in binary::insert (this=0xbffff33c, d=7) at so.cpp:52 
52   if (t->data<parent->data) 

在你的情況,parent是NULL;這是因爲在您的empty()方法中,您正在使用root=NULL(設置rootNULL)而不是root==NULL(檢查root是否爲NULL)。

+0

davit-datuashvili:總是編寫NULL == root,這樣編譯器就會捕獲這個問題。 – 2010-07-24 13:10:28

+0

或者使用不接受非布爾值的強類型語言作爲布爾方法的返回類型。 – tvanfosson 2010-07-24 13:18:30

1

的問題是在這裏:

bool empty() { return root=NULL;} 

更改爲:

bool empty() { return root == NULL;} 
0

,我看到的最明顯的錯誤是,你的空實現實際上會刪除樹的根。它應該返回的root == NULL的結果,而不是NULL分配給rootroot=NULL)的結果。由於樹實際上是空的,並且NULL等於false,這會導致插入的「搜索」分支被採用。由於current(和root)爲NULL,parent永遠不會被設定,當你嘗試檢查parent的數據的價值你的內存訪問錯誤。

您可能遇到其他錯誤,但是這是據我看了。我建議你寫一個基於特定的場景來測試每個場景的條件下會發生什麼你個人的方法的一些單元測試。如果你在之前編寫測試會更好,你編寫了足夠的代碼來通過測試,這樣你就知道當你的代碼通過測試時它是正確的並且覆蓋了測試場景,但是你也可以在之後編寫它們。這是很難知道你有正是你需要(沒有更多),如果你寫出來之後的代碼。在調試器中運行這些測試時(在這種情況下非常有用)可以幫助您理解錯誤,但如果您使用測試作爲指導慢慢構建代碼,通常可以指出錯誤發生的位置沒有這個。