2010-07-24 4 views
0

j'ai mettre en œuvre l'arbre de recherche binaire en C++arbre recherche binaire

#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; 

} 

il compile très bien mais problème est le suivant: quand j'entrer dans le choix 1 il dire entrer le numéro à insérer i entrer par exemple 7 et le programme dit :

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 

Pourquoi? Quelle est la raison de ce type de problème?

+2

C'est ce qui vous aidera à passer au travers d'un débogueur, au lieu de nous faire corriger votre code par des bogues. – Joe

Répondre

4

L'exécution du code sous gdb sur un système Linux, ceci est l'erreur signalée:

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

En votre cas, parent est NULL; C'est parce que dans votre empty() méthode, vous utilisez root=NULL (réglage root à NULL) au lieu de root==NULL (vérifiant si root est NULL).

+0

davit-datuashvili: toujours écrire NULL == root de cette façon le compilateur attraperait ce problème. –

+0

Ou utilisez un langage fortement typé qui n'accepte pas un non-booléen comme type de retour pour une méthode booléenne. – tvanfosson

1

Le problème est ici:

bool empty() { return root=NULL;} 

Modification:

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

L'erreur la plus évidente que je vois est que votre implémentation de vide supprime réellement la racine de votre arbre. Il devrait renvoyer le résultat de root == NULL plutôt que le résultat de l'affectation de NULL à root (root=NULL). Puisque l'arbre est réellement vide et que NULL est équivalent à false, cela provoque la prise de la branche "search" de l'insert. Comme current (et root) est NULL, parent n'est jamais défini et vous obtenez une erreur d'accès mémoire lorsque vous essayez de vérifier la valeur des données parent.

Vous avez probablement d'autres erreurs, mais c'est aussi loin que j'ai regardé. Je suggère que vous écrivez des tests unitaires pour vos méthodes individuelles basées sur des scénarios spécifiques pour tester ce qui se passe dans chacune des conditions de ce scénario. Il serait préférable que vous écriviez le test avant d'écrire que vous avez écrit juste assez de code pour réussir le test de sorte que vous saviez que lorsque votre code a passé le test, il était correct et couvrait le scénario de test, mais vous pouvez également les écrire ensuite. Il est plus difficile de savoir que vous avez exactement le code dont vous avez besoin (et pas plus) si vous les écrivez par la suite. Exécuter ces tests dans le débogueur quand il échoue (spectaculairement, dans ce cas) peut être utile pour comprendre ce qui ne va pas, mais si vous construisez le code lentement en utilisant vos tests comme guide, vous pouvez généralement déterminer où se situe l'erreur sans ça.