2010-07-24 240 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的数据的价值你的内存访问错误。

您可能遇到其他错误,但是这是据我看了。我建议你写一个基于特定的场景来测试每个场景的条件下会发生什么你个人的方法的一些单元测试。如果你在之前编写测试会更好,你编写了足够的代码来通过测试,这样你就知道当你的代码通过测试时它是正确的并且覆盖了测试场景,但是你也可以在之后编写它们。这是很难知道你有正是你需要(没有更多),如果你写出来之后的代码。在调试器中运行这些测试时(在这种情况下非常有用)可以帮助您理解错误,但如果您使用测试作为指导慢慢构建代码,通常可以指出错误发生的位置没有这个。