Albero binario - Ricerca nodo

di Anonimizzato15378 il
15 risposte
Salve vorrei chiedere un aiuto.. abbastanza elementare.
Devo implementare una ricerca di un nodo in un albero binario che ritorni un puntatore al nodo quando l'ha trovato...
La mia idea non funzionante era qualcosa del genere
TIPONODO search (TIPONODO t, int k)
{
 if(condizione)
  return t;
 else
 t=search(t->sx,k)
 t=search(t->dx,k)
 }
dove TIPONODO lo intendo come un puntatore alla struct definito con un typedef.
Credo che l'errore sia chiaramente nel ritorno della funzione perchè perdo dei riferimenti e non vengono esplorati alcuni nodi.
Spero qualcuno mi aiuti, grazie

15 Risposte

  • Già l'avevo consultato, ma il mio problema è proprio che ho come struttura un albero binario, non un albero binario di ricerca.. E ho la necessità di cercare uno specifico nodo, visitandoli tutti
  • Qualcosa del genere (da adattare)
    
    btree *search(btree *t, int n){
        if (t == NULL) return(NULL) ;
        else if (t->val == n) return(t) ;
        else return(search(t->ltree,n) || search(t->rtree,n)) ;
    }
  • Non mi risolve il problema purtroppo
  • TIPONODO * search (TIPONODO *t, int k)
    {
     if(condizione)
      return NULL;
     else
     return search(t->sx,k)
     return search(t->dx,k)
     }
    Il problema così dovresti risolverlo, il problema sta nel passare un puntatore al nodo e ritornare quando trovi. Nella condizione devi mettere il caso in cui non trova nulla e ritornare un NULL.
  • SVNiko ha scritto:


    TIPONODO * search (TIPONODO *t, int k)
    {
     if(condizione)
      return NULL;
     else
     return search(t->sx,k)
     return search(t->dx,k)
     }
    Il problema così dovresti risolverlo, il problema sta nel passare un puntatore al nodo e ritornare quando trovi. Nella condizione devi mettere il caso in cui non trova nulla e ritornare un NULL.
    Ma anche così non mi risolve il mio problema che è quello di visitare e confrontare tutti i nodi.
    Per intenderci se ho un albero di questo tipo
                  20
         18                10
    4         6        8         2
    mi visita solo 20,18,10 e poi si blocca... Lo stesso succedeva con quello che avevo scritto io, anzi proseguiva senza bloccarsi ma visitava sempre solo questi tre... Non riesco a visitarli tutti, ecco perchè pensavo di tornare male il putatore in n e quindi perdevo i riferimenti. Non so se sono stata più chiara o più confusionaria ancora
  • Ti dispiace postare il codice con le definizioni dei dati.
  • In realtà dovresti scrivere qualcosa del tipo
    TIPONODO * search (TIPONODO *t, int k)
    {
     if(condizione)
      return t;
    
     if( t->sx )
     {
       t = search(t->sx,k);
       if( t != NULL )
          return t;
     }
    
     if( t->dx )
     {
       t = search(t->dx,k);
       if( t != NULL )
          return t;
     }
     return NULL;
    }
  • SVNiko ha scritto:


    Ti dispiace postare il codice con le definizioni dei dati.
    Eh è un bel po' complesso, perchè in realtà sto facendo un inserimento in heap che dev'essere implementato con un albero binario puntato (per l'implementazione con array c'è un altra libreria che ho già scritto).. La funzione di ricerca mi serve a trovare il padre a cui agganciare il nuovo nodo.
    ((i vari commenti e printf sono per fare le correzioni))

    dall'header file
    typedef struct binarytree * TREE;
    typedef struct node * NODE;
    typedef struct binarytree{
        int size;
        struct node * element;
        }binarytree;
    
    typedef struct node{
        void *data;
        int priority;
        struct node * parent;
        struct node * sx;
        struct node * dx;
    }node;
    
    void * treeInsert (void * T, void * k)
    {//il prototipo non può cambiare rispetto a quello dell'array altrimenti non va bene per le callback
        TREE t=(TREE)T;
    
        NODE last=t->element;
    
        NODE nuovo=(node*)malloc(sizeof(node));
        nuovo->data=k;
        nuovo->priority=t->size;
        nuovo->sx=NULL;
        nuovo->dx=NULL;
    
        if(last==NULL)
        {
            nuovo->parent=NULL;
            t->element=nuovo;
        }
        else
        {
         
            last=searchParent(last, t->size);
            printf("last=%d, key %d\n",(int)last->data,(int)k);
            nuovo->parent=last;
            if(last->sx==NULL)
                {last->sx=nuovo; last=last->sx;}
            else {last->dx=nuovo; last=last->sx;} //last diventa il nodo inserito
    
            while(last->data>last->parent->data)
            {//aggiornamento ordine heap
                last=treeSwap(last, last->parent);
                last=last->parent;
            }
    
        }
    
        t->size=t->size+1;
    
        return t;
    
    NODE searchParent (NODE n, int size)
    {
        if(((size-1)/2) == n->priority)
            {printf("TROVATO %d\n",(int)n->data);
            return n;}
    
        if(n->sx!=NULL)
        	 n=searchParent(n->sx,size);
            
        if(n->dx!=NULL)
        	n=searchParent(n->dx,size);
           
    }

    In effetti la ricerca deve andare per forza a buon fine, non può ritornare null perchè il nodo che cerco c'è per forza in quanto è un calcolo matematico sulla priorità, ma il problema resta sempre che la ricerca non va mai a destra. Nell'inserimento sicuramente ci sono altri errori ma ancora ci devo arrivare a correggerli in quanto la ricerca non va a buon fine, per cui mi aggiunge appunto solo a sinistra.
  • La funzione ricorsiva fermo restando la validità dei valori size e della condizione (size - 1)/2, per come è scritta dovrebbe funzionare. Prova a scriverti uno spike per provarla al di fuori del tuo progetto.
  • SVNiko ha scritto:


    La funzione ricorsiva fermo restando la validità dei valori size e della condizione (size - 1)/2, per come è scritta dovrebbe funzionare. Prova a scriverti uno spike per provarla al di fuori del tuo progetto.
    L'ho scritta iterativa con l'ausilio di una queue, e funziona, il che mi fa pensare che ci sia appunto qualche errore nella funzione scritta ricorsivamente. Cosi com'è si blocca in esecuzione non appena non ci sono più figli sx..
  • NODE searchParent (NODE n, int size)
    {
        if(((size-1)/2) == n->priority)
            {printf("TROVATO %d\n",(int)n->data);
            return n;}
    
        if(n->sx!=NULL)
            n=searchParent(n->sx,size);
           
        if(n->dx!=NULL)
           n=searchParent(n->dx,size);
           
           return n; /* Serve per chiudere le ricorsioni, senza dovresti avere un warning */
           
    }
  • SVNiko ha scritto:


    NODE searchParent (NODE n, int size)
    {
        if(((size-1)/2) == n->priority)
            {printf("TROVATO %d\n",(int)n->data);
            return n;}
    
        if(n->sx!=NULL)
            n=searchParent(n->sx,size);
           
        if(n->dx!=NULL)
           n=searchParent(n->dx,size);
           
           return n; /* Serve per chiudere le ricorsioni, senza dovresti avere un warning */
           
    }
    Ci sono un pò problemi:
    1) quando trovi l'elemento devi uscire con n (come fai giustamente all'inizio) ma quando non lo trovi non puoi ritornare n, devi ritornare NULL per dire "qui non c'è" altrimenti non puoi sapere se l'hai trovato oppure no
    2) dopo aver verificato il ramo sinistro devi verificare se questo ha trovato qualcosa, ovvero ha ritornato un valore diverso da NULL perchè in quel caso devi uscire e non devi verificare il ramo destro.
    3) il valore di ritorno di searchParent() non metterlo in n...
    Vedi lo pseudocodice che ho postato nel mio precedente intervento.
  • Ok grazie, ragiono un po' sui tuoi suggerimenti
Devi accedere o registrarti per scrivere nel forum
15 risposte