|
|
|
![]() |
|
Strumenti |
![]() |
#21 | |
Member
Iscritto dal: Oct 2009
Città: In una città
Messaggi: 67
|
Quote:
![]() inoltre il fatto che non abbia senso non impedisce che lo si faccia. edit: inoltre non è per nulla essenziale. la cancellazione si fa arrivando al valore precedente e verificando che il valore figlio contenga i parametri del nodo ricercato, se sì si sostituisce il puntatore al figlio col figlio del figlio. ![]() Ultima modifica di Fibrizio : 02-06-2010 alle 22:57. |
|
![]() |
![]() |
![]() |
#22 | |
Senior Member
Iscritto dal: Jun 2002
Città: Dublin
Messaggi: 5989
|
Io ho l'edizione americana, tu quale hai? Magari è solo su un'altra pagina, è l'algoritmo "Tree-Successor", lo descrive nel capitolo riguardante gli alberi binari di ricerca.
Quote:
ciao ![]()
__________________
C'ho certi cazzi Mafa' che manco tu che sei pratica li hai visti mai! |
|
![]() |
![]() |
![]() |
#23 | |
Senior Member
Iscritto dal: Jun 2002
Città: Dublin
Messaggi: 5989
|
Quote:
![]() Hmm. Come arrivi al "valore precedente"? Diciamo che ci arrivo: se è una foglia funziona. Se il nodo ha un solo figlio, funziona. Se il nodo ha due figli, quale dei due prenderebbe il suo posto secondo la tua tecnica? ![]() ciao ![]()
__________________
C'ho certi cazzi Mafa' che manco tu che sei pratica li hai visti mai! |
|
![]() |
![]() |
![]() |
#24 | |
Senior Member
Iscritto dal: Apr 2001
Città: Milano
Messaggi: 3736
|
Quote:
ciao, grazie come sempre. Quello che osservi è codice già pronto che sto utilizzando senza reinventare l'acqua calda, come dice il docente, ed in alcuni suoi punti lo trovo un C piuttosto complicato. ciao |
|
![]() |
![]() |
![]() |
#25 |
Member
Iscritto dal: Oct 2009
Città: In una città
Messaggi: 67
|
E' irrilevante se ha uno o due figli, il problema si ripresenta anche se il nodo ha un riferimento al genitore e si risolve ordinando i due figli secondo il criterio di ordinamento dell'albero. Nel caso specifico del tuo esempio se togliamo il nodo con valore 2 possiamo tranquillamente reinserire sia l'1 che il 3, visto che l'ordinamento non dipende dall'ordine di inserimento.
|
![]() |
![]() |
![]() |
#26 | |||
Member
Iscritto dal: Oct 2009
Città: In una città
Messaggi: 67
|
Quote:
Quote:
Da cui deriva anche il teorema Quote:
Che seppure sia possibile fare è tutt'altro che essenziale. |
|||
![]() |
![]() |
![]() |
#27 | |
Senior Member
Iscritto dal: Apr 2000
Città: Vicino a Montecatini(Pistoia) Moto:Kawasaki Ninja ZX-9R Scudetti: 29
Messaggi: 53971
|
Quote:
|
|
![]() |
![]() |
![]() |
#28 |
Senior Member
Iscritto dal: Apr 2001
Città: Milano
Messaggi: 3736
|
ciao,
non ho ancora ben chiaro questo codice per la visita in-ordine di un albero RB. Codice:
void inord(rbnode *p, rbnode *nil, void (*op)(rbnode *)) { if(p != nil) { inord(p->left,nil,op); printf("%d ", p->v); inord(p->right,nil,op); } } /****************************************************************************/ void inorder(rbtree *p, void (*op)(rbnode *)) { inord(p->root, p->nil, op); } rbtree *MioLberoRB; MioLberoRB = creaAlberoRB(); e poi inserisco un pò di dati; inserisci(MioLberoRB, 18 , 2, 3 ,4); inserisci(MioLberoRB, 20 , 20, 30 ,40); inserisci(MioLberoRB, 5 , 22, 32 ,42); ora chiamo la inorder con: inord(MioLberoRB, treemin(MioLberoRB)); note: la treemin() mi ritorna la chiave minima dell'albero e che io passo come tipo nodo |
![]() |
![]() |
![]() |
#29 | |
Member
Iscritto dal: Oct 2009
Città: In una città
Messaggi: 67
|
Quote:
|
|
![]() |
![]() |
![]() |
#30 |
Member
Iscritto dal: Oct 2009
Città: In una città
Messaggi: 67
|
Non ti cambia nulla, dal momento che devi effettuare lo scorrimento fino al nodo in ogni caso per leggerlo.
|
![]() |
![]() |
![]() |
#31 |
Senior Member
Iscritto dal: Apr 2001
Città: Milano
Messaggi: 3736
|
ciao,
nel frattempo ho modificato il codice e quello che non mi è chiaro è come funziona questa parte di codice: Codice:
void inord(rbnode *p, rbnode *nil) { if(p != nil) { inord(p->left,nil); printf("%d ",p->v); inord(p->right,nil); } } void inorder(rbtree *p) { inord(p->root, p->nil); } |
![]() |
![]() |
![]() |
#32 | |
Member
Iscritto dal: Oct 2009
Città: In una città
Messaggi: 67
|
Quote:
Quando cominci a leggere l'albero il codice dice: if(p != nil) { se p è diverso da nil, ossia se quello che segue è un nodo allora inord(p->left,nil); richiama la funzione stessa sul ramo di sinistra Ora immagina che l'albero sia quello proposto prima da DanieleC88 Codice:
4 / \ 2 5 / \ / \ 1 3 6 7 Prendo 4, il ramo di sinistra ha un valore, è 2, prendo 2, il ramo di sinistra ha un valore, è 1, prendo 1, il ramo di sinistra non ha alcun valore, la funzione inord sul ramo di sinistra di 1 non fa niente, segue printf("%d ",p->v); che stampa 1 segue inord sul ramo di destra di 1, non stampa nulla, la funzione finisce. erano rimaste in pausa le funzioni inord su 2 e 4. torniamo a 2, stampa 2 su schermo con printf, poi esegue il controllo sul ramo di destra, è 3, prende 3. esegue il controllo sul ramo di sinistra, non c'è nulla, stampa 3, esegue il controllo a destra, non c'è nulla. la funzione finisce, si torna a 2. Anche su 2 non c'è altro da fare, si torna su 4 e si stampa, si prende la funzione sul ramo di destra. ecc ecc Alla fine come vedi abbiamo stampato 1, 2, 3, 4 ...e così via, in ordine. Se vuoi invertire l'ordine fai inord prima sul ramo di destra e poi su quello di sinistra. |
|
![]() |
![]() |
![]() |
#33 |
Senior Member
Iscritto dal: Apr 2001
Città: Milano
Messaggi: 3736
|
ciao e grazie,
ho notato che per capire si dovrebbe scoprire come funzionala insertRB ma è piuttosto complessa e richiederebbe troppo tempo per essere compresa; importante è sapere che i dati vengono messi ordinati come negli ABR in quanto gli RB sono ABR con in aggiunta la colorazione in aggiunta alle funzioni per mantenerlo tale giusto ? Codice:
rbnode *simpleinsert(rbtree *tree, int k) { rbnode *q = malloc(sizeof(rbnode)); rbnode *r = tree->root; rbnode *s = tree->nil; if(!q) { fprintf(stderr,"Errore di allocazione C\n"); exit(-4); } q->v = k; q->left = q->right = tree->nil; q->c = red; while(r != tree->nil) { s = r; r = k < r->v ? r->left : r->right; } q->up = s; if(s == tree->nil) return tree->root = q; if(k < s->v) s->left = q; else s->right = q; return q; } /****************************************************************************/ void rbinsert(rbtree *tree, int k) { rbnode *x = simpleinsert(tree, k); rbnode *y; while(x != tree->root && x->up->c == red) { if(x->up == x->up->up->left) { /* caso L */ y = x->up->up->right; if(y->c == red) { x->up->c = black; /* caso 1L */ y->c = black; /* caso 1L */ x->up->up->c = red; /* caso 1L */ x = x->up->up; /* caso 1L */ } else { if(x == x->up->right) /* caso 2L */ leftrotate(tree,x = x->up); /* caso 2L */ x->up->c = black; /* caso 3L */ x->up->up->c = red; /* caso 3L */ rightrotate(tree,x->up->up); /* caso 3L */ } } else { /* caso R */ y = x->up->up->left; if(y->c == red) { x->up->c = black; /* caso 1R */ y->c = black; /* caso 1R */ x->up->up->c = red; /* caso 1R */ x = x->up->up; /* caso 1R */ } else { if(x == x->up->left) /* caso 2R */ rightrotate(tree,x = x->up); /* caso 2R */ x->up->c = black; /* caso 3R */ x->up->up->c = red; /* caso 3R */ leftrotate(tree,x->up->up); /* caso 3R */ } } } tree->root->c = black; } |
![]() |
![]() |
![]() |
#34 | |
Senior Member
Iscritto dal: Apr 2000
Città: Vicino a Montecatini(Pistoia) Moto:Kawasaki Ninja ZX-9R Scudetti: 29
Messaggi: 53971
|
Quote:
Caso in cui si ritornano nodi: struct node * find_first_greater_than(int x); //ritorna un nodo se presente o NULL void delete(struct node * n); //elimina il nodo Caso in cui si ritornano valori: bool find_first_greater_than(int x, int * v); //ritorna true se l'ha trovato, mette il valore in *v void delete(int v); //elimina il valore v Prima di tutto i due approcci non sono equivalenti. Con la seconda delete non siamo sicuri di elminare proprio quel v, visto che nel frattempo l'albero potrebbe essere stato ribilanciato. La prima funzione in entrambi i casi ha un tempo di esecuzione proporzionale alla profondità dell'albero. La seconda invece: - nel primo caso ha un tempo di esecuzione costante o al proporzionale al tempo necessario a ribilanciare l'albero - nel secondo caso ha un tempo di esecuzione proporzionale al tempo necessario a ribilanciare l'albero + il tempo di ricerca Nel caso di alberi di dimensione molto grande questa differenza è tutt'altro che trascurabile. |
|
![]() |
![]() |
![]() |
#35 | |
Senior Member
Iscritto dal: Apr 2000
Città: Vicino a Montecatini(Pistoia) Moto:Kawasaki Ninja ZX-9R Scudetti: 29
Messaggi: 53971
|
Quote:
Stranamente wikipedia è fatta veramente bene in questo caso: http://it.wikipedia.org/wiki/RB-Albero |
|
![]() |
![]() |
![]() |
#36 | ||||
Senior Member
Iscritto dal: Jun 2002
Città: Dublin
Messaggi: 5989
|
Quote:
Quote:
![]() Il testo ti sta appunto dicendo che nel caso peggiore possibile hai l'invocazione dell'algoritmo in un albero completo, sulla foglia che contiene il valore massimo nel sottoalbero sinistro della radice, e che dovrà quindi risalire lungo tutta l'altezza dell'albero fino a raggiungere la radice (che è il suo successore), è da lì che viene il tempo O(h) = O(log(n)) che mi hai addirittura citato (con h = altezza dell'albero, n = numero di nodi). Quote:
Che vogliamo fare a questo punto? Possiamo continuare ad oltranza, decidi tu. ![]() Se poi non sei convinto di ciò che dico, puoi anche leggere l'ultima risposta di cionci e valutare da te. La sua parola è sicuramente più autorevole della mia, se non ti fidi né di me né del Cormen. ciao ![]()
__________________
C'ho certi cazzi Mafa' che manco tu che sei pratica li hai visti mai! |
||||
![]() |
![]() |
![]() |
#37 | |
Senior Member
Iscritto dal: Apr 2001
Città: Milano
Messaggi: 3736
|
Quote:
effettivamente interessa maggiormente come lavora concettualmente un RB invece di conoscere a fondo l'implentazione finale. Approfitto per una dritta visto il mio digiuno di C. Devo leggere da standard input una stringa del tipo: 12 20 45 90 ......... e così via avevo pensato ad una cosa del tipo int cifra; while((cifra = getchar()) != '\n') ma credo di essere in parte sulla strada sbagliata ciao |
|
![]() |
![]() |
![]() |
#38 |
Senior Member
Iscritto dal: Jun 2002
Città: Dublin
Messaggi: 5989
|
Non andava bene scanf()?
![]()
__________________
C'ho certi cazzi Mafa' che manco tu che sei pratica li hai visti mai! |
![]() |
![]() |
![]() |
#39 |
Senior Member
Iscritto dal: Apr 2001
Città: Milano
Messaggi: 3736
|
|
![]() |
![]() |
![]() |
#40 |
Senior Member
Iscritto dal: Jun 2002
Città: Dublin
Messaggi: 5989
|
Ma scanf() non ti restituisce l'ultimo carattere letto, ti restituisce il numero di elementi letti dall'input.
![]()
__________________
C'ho certi cazzi Mafa' che manco tu che sei pratica li hai visti mai! |
![]() |
![]() |
![]() |
Strumenti | |
|
|
Tutti gli orari sono GMT +1. Ora sono le: 05:25.