Albero binario - Ricerca nodo

di il
15 risposte

Albero binario - Ricerca nodo

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

  • Re: Albero binario - Ricerca nodo

    Vedi search in

    http://www.cprogramming.com/tutorial/lesson18.htm
  • Re: Albero binario - Ricerca nodo

    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
  • Re: Albero binario - Ricerca nodo

    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)) ;
    }
  • Re: Albero binario - Ricerca nodo

    Non mi risolve il problema purtroppo
  • Re: Albero binario - Ricerca nodo

    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.
  • Re: Albero binario - Ricerca nodo

    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
  • Re: Albero binario - Ricerca nodo

    Ti dispiace postare il codice con le definizioni dei dati.
  • Re: Albero binario - Ricerca nodo

    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;
    }
  • Re: Albero binario - Ricerca nodo

    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.
  • Re: Albero binario - Ricerca nodo

    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.
  • Re: Albero binario - Ricerca nodo

    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..
  • Re: Albero binario - Ricerca nodo

    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 */
           
    }
  • Re: Albero binario - Ricerca nodo

    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.
  • Re: Albero binario - Ricerca nodo

    Ok grazie, ragiono un po' sui tuoi suggerimenti
Devi accedere o registrarti per scrivere nel forum
15 risposte