Alberi Binari di Ricerca

Documenti analoghi
Lezione 15. Algoritmi su gli alberi binari: visite

Struttura di dati che può essere usata sia come dizionario, sia come coda con priorità

Alberi. Se x è il genitore di y, allora y è un figlio di x. Un albero binario è un albero in cui ogni nodo ha al massimo due figli.

Alberi di ricerca binari

Algoritmi e Strutture Dati

Alberi binari di ricerca

Alberi binari di ricerca

Alberi Binari di Ricerca

Alberi binari di ricerca

Alberi binari di ricerca

Esercitazione 6. Alberi binari di ricerca

Algoritmi e Strutture di Dati I 1. Algoritmi e Strutture di Dati I Massimo Franceschet francesc

ricerca di un elemento, verifica dell appartenenza di un elemento

Alberi Binari di Ricerca. Vittorio Maniezzo Università di Bologna

Alberi Binari di Ricerca

Alberi Binari di Ricerca

Organigramma Gerarchia. (Tree) Nessuna persona può avere più di un superiore Ogni persona può essere superiore di altre

Strutture dati Alberi binari

LE STRUTTURE DATI DINAMICHE: GLI ALBERI. Cosimo Laneve

ALGORITMI E STRUTTURE DATI

Alberi. Alberi: Esempio di utilizzo

Per semplicità eliminiamo le ripetizioni nell'albero.

Alberi Binari di Ricerca e Alberi Rosso-Neri

In questa lezione Alberi binari di ricerca

Informatica 3. LEZIONE 17: Alberi generici. Modulo 1: Definizione e ADT Modulo 2: Implementazione Modulo 3: Alberi e classi di equivalenza

ALBERI BINARI DI RICERCA

Struttura dati Dizionario

Esempi. Albero di interi. Struttura che non è un albero!

In questa lezione Alberi binari di ricerca: la cancellazione

Sommario. Le strutture dati elementari per implementare sequenze: Vettori Liste

Alberi rosso neri. API a.a. 2013/2014 Gennaio 23, 2014 Flavio Mutti, PhD

Esercizio 1. E vero che in un AVL il minimo si trova in una foglia o nel penultimo livello? FB = -1. livello 0 FB = -1. livello 1 FB = -1.

Algoritmi e strutture dati

Laboratorio di Algoritmi e Strutture Dati. Alberi Binari

Alberi ed Alberi Binari di Ricerca

PROGRAMMAZIONE II canale A-D luglio 2008 TRACCIA DI SOLUZIONE

Alberi. Gli alberi sono una generalizzazione delle liste che consente di modellare delle strutture gerarchiche come questa: Largo. Fosco.

Prova di Algoritmi e s.d. (1o anno) 17 Settembre TESTO e RISPOSTE

ADT Coda con priorità

Laboratorio di Informatica

Informatica 3. Informatica 3. LEZIONE 17: Alberi generici. Lezione 17 - Modulo 1. Introduzione. ADT dell albero generico.

Esercizi su programmazione ricorsiva 3

Algoritmi e Strutture Dati. Capitolo 6 Il problema del dizionario

Informatica 3. Informatica 3. LEZIONE 14: Alberi binari: introduzione. Lezione 14 - Modulo 1. Definizioni. Introduzione. Definizioni e proprietà

Problemi di ordinamento

Algoritmi e Strutture Dati

Ripasso di programmazione ricorsiva

Laboratorio di Informatica. Lezione 8: Liste e alberi

Dipartimento di Elettronica, Informazione e Bioingegneria API 2013/4

Alberi. Gli alberi sono una generalizzazione delle liste che consente di modellare delle strutture gerarchiche come questa: Largo. Fosco.

Algoritmi e Strutture Dati

Prova di Algoritmi e s.d. (1o anno) 7 Febbraio TESTO e RISPOSTE

Algoritmi, Strutture Dati e Programmi. UD 3.d: Strutture Dati Dinamiche Alberi

Alberi Binario in Java

Algoritmo di ordinamento sul posto che ha tempo di esecuzione :

Esercizio Per quali valori di t l albero in figura è un B-Albero legale?

ALBERI : introduzione SOMMARIO ALBERI ALBERI. ALBERI: introduzione ALBERI BINARI: introduzione VISITE RICORSIVE DI ALBERI

Alberi rosso-neri. Le operazioni sugli alberi binari di ricerca hanno complessità proporzionale all altezza h dell albero.

Alberi Rosso-Neri: definizione

Algoritmi e Strutture Dati. Capitolo 3 Strutture dati elementari

Alberi binari e alberi binari di ricerca

Algoritmi e Strutture Dati. Lezione 3

Algoritmi e Strutture Dati

Liste concatenate. Violetta Lonati

Alberi binari e alberi binari di ricerca

Alberi ed Alberi Binari

Esercitazione 4 Algorithmi e Strutture Dati (Informatica) A.A 2015/2016

Esercizi su ABR. Prof. E. Fachini - Intr. Alg.!1

Alberi binari e alberi binari di ricerca

Lezione 12 Tabelle Hash

Implementazione ADT: Alberi

Alberi Binari di Ricerca: Definizione. Ricerca, inserimento, cancellazione, min, max, predecessore, successore.

Dizionari. Realizzazione con alberi binari di ricerca. Alberi rosso-neri. Ugo de' Liguoro - Algoritmi e Seprimentazioni 03/04 Lez.

Strutture dati dinamiche in C (II)

Informatica 3. LEZIONE 15: Implementazione di alberi binari - BST. Modulo 1: Implementazione degli alberi binari Modulo 2: BST

ricerca di un elemento, verifica dell appartenenza di un elemento

Esercitazione su Albero Binario

Algoritmi e Strutture Dati. Capitolo 3 Strutture dati elementari

QuickSort Università degli Studi di Milano

Introduzione Implementazione (1)

RICERCA BINARIA...1 ALBERO BINARIO DI RICERCA (ABR)...3 RICORSIONE...4 ESEMPI DI RICORSIONE IN VISUAL BASIC...5 ESEMPI DI RICORSIONE IN C / C++...

Alberi. Strutture dati: Alberi. Alberi: Alcuni concetti. Alberi: definizione ricorsiva. Alberi: Una prima realizzazione. Alberi: prima Realizzazione

Alberi e alberi binari I Un albero è un caso particolare di grafo

Esercizi BST - AVL. E. Fachini

Algoritmi e Strutture di Dati

Alberi e alberi binari I Un albero è un caso particolare di grafo

Esercizi parte 3. La classe ArrayBinTree dovra implementare, tra le altre, l operazione seguente: padre: dato un nodo, restituire l indice del padre.

Alberi. Definizione, realizzazione e algoritmi elementari. Ugo de' Liguoro - Algoritmi e Sperimentazioni 03/04 - Lez. 7

alberi binari di ricerca (BST)

Algoritmi e Strutture Dati. Lezione 4

Implementazione dell albero binario in linguaggio C++

L albero e un tipo astratto di dati usato per rappresentare relazioni gerarchiche.

Appunti Senza Pretese di Programmazione II: Alberi di Ricerca

Alberi. CORDA Informatica. A. Ferrari. Testi da. Marco Bernardo Edoardo Bontà. Dispense del Corso di. Algoritmi e Strutture Dati

type keytype: integer; Tree: "Node; record Node = key: keytype; parent: "Node ; left: Tree; right: Tree; Figure 1: Tipi di dato per rappresentare albe

Algoritmi e Strutture Dati. Lezione 5

Algoritmi e Strutture Dati

Alberi Binari Alberi Binari

Esercizi Capitolo 6 - Alberi binari di ricerca

Transcript:

Alberi Binari di Ricerca

Determinazione della chiave massima e minima La chiave massima in un albero binario dovrà trovarsi nel sottoalbero destro della radice e nel sottoalbero destro del figlio destro della radice e così via Analogamente per la chiave minima che dovrà essere nel sottoalbero sinistro Pertanto per determinare l elemento massimo è sufficiente discendere tutti i nodi da figlio destro in figlio destro fino ad arrivare alla foglia (e analogamente con i figli sinistri per il minimo)

Massimo 15 6 18 3 7 17 20 2 4 13 Massimo=20 9

Minimo 15 6 18 3 7 17 20 2 4 13 Minimo=20 9

Minimo e massimo Tree Minimum(x) 1 while left[x] NIL 2 do x left[x] 3 return x Tree Maximum(x) 1 while right[x] NIL 2 do x right[x] 3 return x

Successore e predecessore Dato un nodo nell albero di ricerca talvolta si richiede di determinare il suo successore (o predecessore) secondo l ordinamento fornito dalle chiavi. Se tutte le chiavi sono distinte, il successore di un nodo x è il nodo con la più piccola chiave maggiore della chiave di x Con gli alberi binari di ricerca è possibile determinare il successore (predecessore) di un nodo senza dover confrontare le chiavi

Successore: idea intuitiva Si considerano due casi: il nodo x ha un figlio destro il nodo x non ha un figlio destro Nel primo caso: si considera il sottoalbero destro che contiene sicuramente nodi con chiavi maggiori della chiave di x in questo sottoalbero il nodo con la chiave più piccola è la foglia alla estrema sinistra, cioè il nodo restituito dalla procedura Tree-Minimum

Successore di nodo con figlio dx 15 6 Successore di 15 18 sottoalbero destro 3 7 17 20 2 4 13 9 minimo

Successore di nodo senza figlio dx Nel caso in cui x non ha un figlio destro allora il predecessore deve essere un antenato p di x dal punto di vista di p, x deve essere un discendente appartenente ad un sottoalbero sinistro infatti le chiavi nel sottoalbero sx hanno chiave minore antenati ha x in sottoalbero dx? SI ha x in sottoalbero sx? NO 6 3 7 2 4 13 Successore di x = 4?

Successore di nodo senza figlio dx perché la chiave di p sia la più piccola possibile allora p deve essere l antenato più prossimo altrimenti se consideriamo un antenato lontano è vero che ha chiave maggiore, ma.. esisterà un antenato meno lontano e più piccolo! Antenati che hanno x in sottoalbero sx 6 15 18 3 7 17 20 2 4 Successore di x = 4

Idea intuitiva Per determinare questo nodo antenato è sufficiente risalire gli antenati di x fino a quando non si trova un nodo antenato che è un figlio sinistro di un nodo y. Il nodo y è il nodo cercato, il successore Si mantengono pertanto i puntatori a due generici antenati x e y e si risale fino a quando x=left[y]

Visualizzazione 15 6 18 3 7 17 20 2 4 13 Successore di 13 9

PseudoCodice Successore Tree Successore(x) 1 if right[x] NIL 2 thenreturn Tree Minimum(right[x]) 3 y p[x] 4 while y NIL e x = right[y] 5 do x y 6 y p[x] 7 return y

Predecessore La procedura per la determinazione del predecessore è simmetrica a quella vista per il successore il predecessore si troverà nel sottoalbero sinistro (se questo esiste), e sarà l elemento massimo di questo sottoalbero se non esiste sottoalbero sinistro il predecessore sarà l antenato più prossimo che ha un figlio destro che è antenato del nodo in questione

PseudoCodice Predecessore Tree Predecessore(x) 1 if left[x] NIL 2 thenreturn Tree Maximum(left[x]) 3 y p[x] 4 while y NIL e x = left[y] 5 do x y 6 y p[x] 7 return y

Inserzione Per inserire un nuovo valore k in un albero binario di ricerca, si prepara un nodo z tale che: possieda come chiave key[z]=k e non abbia collegamenti left[z]=right[z]=p[k]=nil si cerca la posizione in cui inserirlo si modificano i campi di z per allacciarlo all albero binario di ricerca

Inserzione Per trovare la posizione giusta ci si muove a partire dalla radice spostandosi sul sottoalbero destro o sinistro come in una ricerca si prosegue però fino ad arrivare ad un punto in cui fallirebbe la ricerca a questo punto si inserisce il nuovo nodo

Visualizzazione: inserzione di key 14 15 6 18 3 7 17 20 2 4 13 9 14

Pseudocodice Inserzione Tree-Insert(T,z) 1 y NIL 2 x root[t] 3 while x NIL 4 do y x 5 if key[z]<key[x] 6 then x left[x] 7 else x right[x] 8 p[z] y 9 if y=nil 10 then root[t] z 11 else if key[z] < key[y] 12 then left[y] z 13 else right[y] z ricerca della posizione

Pseudocodice Inserzione Tree-Insert(T,z) 1 y NIL 2 x root[t] 3 while x NIL 4 do y x 5 if key[z]<key[x] 6 then x left[x] 7 else x right[x] 8 p[z] y 9 if y=nil 10 then root[t] z 11 else if key[z] < key[y] 12 then left[y] z 13 else right[y] z Inserzione del nodo z caso: inserzione radice caso: inserzione elemento generico a dx o sx del nodo trovato

Cancellazione La procedura di cancellazione è più laboriosa in quanto si deve tenere conto di tre casi possibili dato un nodo z i casi sono: z non ha figli z ha un unico figlio z ha due figli

Caso 1: Nel caso in cui z non abbia figli si elimina direttamente il nodo z 15 15 5 16 5 16 3 12 20 3 12 20 10 13 18 23 10 18 23 6 6 7 7

Caso 2: Nel caso in cui z abbia un unico figlio si rimuove z e si collega il figlio al posto di z il secondo caso è identico al caso di eliminazione di un nodo da una lista concatenata 15 15 5 16 5 3 12 20 3 12 20 10 13 18 23 10 18 23 6 6 7 7

Caso 3: Se il nodo x da eliminare ha due figli si procede trovando un sostituto per x infatti non possiamo semplicemente eliminarlo e riconnettere i suoi figli perche' il padre di x potrebbe avere un altro figlio oltre a x ed avrebbe cosi' tre figli!! quale nodo e' un buon candidato per la sostituzione? deve essere un nodo che non obbliga a spendere molto sforzo per riaggiustare l'albero binario di ricerca il miglior candidato e' il successore: il figlio sx di X e' anche minore del successore di X il figlio dx di X e' anche maggiore del successore di X

Caso 3: Nel caso in cui z abbia 2 figli si determina il successore x di z si copia il contenuto di x al posto di quello di z infine si elimina il vecchio nodo x (caso 1 o 2) Nota: il successore di x non può avere 2 figli perché non può avere un figlio sx (altrimenti sarebbe questo il successore) 15 15 5 16 6 3 12 20 3 12 20 10 13 18 23 10 18 23 6 7 7

PseudoCodice Cancellazione Tree-Delete(T,z) 1 if left[z]=nil o right[z]=nil 2 then y z 3 else y Tree-Successor(z) 4 if left[y] NIL 5 then x left[y] 6 else x right[y] 7 if x NIL 8 then p[x] p[y] 9 if p[y] = NIL 10 then root[t] x 11 else if y=left[p[y]] 12 then left[p[y]] x 13 else right[p[y]] x 14 if y z 15 then key[z] key[y] 17 return y Determinazione del nodo da cancellare caso 1 o 2

PseudoCodice Cancellazione Tree-Delete(T,z) 1 if left[z]=nil o right[z]=nil 2 then y z 3 else y Tree-Successor(z) 4 if left[y] NIL 5 then x left[y] 6 else x right[y] 7 if x NIL 8 then p[x] p[y] 9 if p[y] = NIL 10 then root[t] x 11 else if y=left[p[y]] 12 then left[p[y]] x 13 else right[p[y]] x 14 if y z 15 then key[z] key[y] 17 return y Determinazione del nodo da cancellare caso 3 y contiene il nodo da cancellare

PseudoCodice Cancellazione Tree-Delete(T,z) 1 if left[z]=nil o right[z]=nil 2 then y z 3 else y Tree-Successor(z) 4 if left[y] NIL 5 then x left[y] 6 else x right[y] 7 if x NIL 8 then p[x] p[y] 9 if p[y] = NIL 10 then root[t] x 11 else if y=left[p[y]] 12 then left[p[y]] x 13 else right[p[y]] x 14 if y z 15 then key[z] key[y] 17 return y in x si memorizza l unico figlio del nodo da cancellare (può essere NIL)

PseudoCodice Cancellazione Tree-Delete(T,z) 1 if left[z]=nil o right[z]=nil 2 then y z 3 else y Tree-Successor(z) 4 if left[y] NIL 5 then x left[y] 6 else x right[y] 7 if x NIL 8 then p[x] p[y] 9 if p[y] = NIL 10 then root[t] x 11 else if y=left[p[y]] 12 then left[p[y]] x 13 else right[p[y]] x 14 if y z 15 then key[z] key[y] 17 return y Se x esiste si attacca all albero

PseudoCodice Cancellazione Tree-Delete(T,z) 1 if left[z]=nil o right[z]=nil 2 then y z 3 else y Tree-Successor(z) 4 if left[y] NIL 5 then x left[y] 6 else x right[y] 7 if x NIL 8 then p[x] p[y] 9 if p[y] = NIL 10 then root[t] x Se il nodo cancellato era la radice allora la nuova radice è x 11 else if y=left[p[y]] 12 then left[p[y]] x 13 else right[p[y]] x 14 if y z 15 then key[z] key[y] 17 return y

PseudoCodice Cancellazione Tree-Delete(T,z) 1 if left[z]=nil o right[z]=nil 2 then y z 3 else y Tree-Successor(z) 4 if left[y] NIL 5 then x left[y] 6 else x right[y] 7 if x NIL 8 then p[x] p[y] 9 if p[y] = NIL 10 then root[t] x 11 else if y=left[p[y]] 12 then left[p[y]] x 13 else right[p[y]] x 14 if y z 15 then key[z] key[y] 17 return y Se il nodo cancellato era un figlio sx allora si aggiorna il puntatore sx altrimenti dx

PseudoCodice Cancellazione Tree-Delete(T,z) 1 if left[z]=nil o right[z]=nil 2 then y z 3 else y Tree-Successor(z) 4 if left[y] NIL 5 then x left[y] 6 else x right[y] 7 if x NIL 8 then p[x] p[y] 9 if p[y] = NIL 10 then root[t] x 11 else if y=left[p[y]] 12 then left[p[y]] x 13 else right[p[y]] x 14 if y z 15 then key[z] key[y] 17 return y Se il nodo cancellato ha richiesto la determinazione del successore allora copia la chiave del successore

PseudoCodice Cancellazione Tree-Delete(T,z) 1 if left[z]=nil o right[z]=nil 2 then y z 3 else y Tree-Successor(z) 4 if left[y] NIL 5 then x left[y] 6 else x right[y] 7 if x NIL 8 then p[x] p[y] 9 if p[y] = NIL 10 then root[t] x 11 else if y=left[p[y]] 12 then left[p[y]] x 13 else right[p[y]] x 14 if y z 15 then key[z] key[y] 17 return y Restituisci il nodo cancellato per una eventuale deallocazione

Esercizio Implementare un albero binario di ricerca: Classe Nodo Classe Albero Ricerca Massimo/Minimo Inserzione/cancellazione Stampa

Implementazione C++ #include<iostream> #include<cassert> using namespace std; template<class T, class LessClass > class TreeClass{ friend ostream& operator<<(ostream& out, TreeClass<T,LessClass>& at); private: class Node{ public: Node(T akey):left(0),right(0),parent(0),key(akey){} Node *left, *right, * parent; T key; }; Node *root; public: TreeClass():root(0){} void insert(t); void print(ostream& out){p_print(root,out);} bool search(t user_key){return p_search(root, user_key);} T minimum(); T maximum(); private: void p_print(node *,ostream&); bool p_search(node * x, T user_key); };

Implementazione C++ template<class T, class LessClass > void TreeClass<T, LessClass>::p_print(Node *x, ostream& out){ if(x!=0){ p_print(x->left,out); out<<x->key<<" "; p_print(x->right,out); } } template<class T, class LessClass > bool TreeClass<T, LessClass>::p_search(Node * x, T usr_key){ LessClass less; if(x==0) return false; if(!less(x->key,usr_key) &&!less(usr_key,x->key)) return true; //ugualianza if(less(usr_key,x->key)) p_search(x->left, usr_key); else p_search(x->right, usr_key); }

template<class T, class LessClass > void TreeClass<T,LessClass>::insert(T usr_key){ LessClass less; //inizializzazione del nodo da aggingere Node* z=new Node; assert(z); z->key=usr_key; z->left=0; z->right=0; z->parent=0; //ricerca della giusta posizione di inserzione Node* y=0; Node* x=root; while(x!= 0){ y=x; if(less(z->key, x->key)) x=x->left; else x=x->right; } //settaggio dei puntatori z->parent=y; if(y==0) root=z; else if(less(z->key, y->key)) y->left=z; else y->right=z; }

Implementazione C++ template<class T, class LessClass > T TreeClass<T, LessClass>::minimum(){ assert(root); Node* x=root; while(x->left!=0) x=x->left; return x->key; } template<class T, class LessClass > T TreeClass<T, LessClass>::maximum(){ assert(root); Node* x=root; while(x->right!=0) x=x->right; return x->key; } template<class T, class LessClass > ostream& operator<<(ostream& out, TreeClass<T,LessClass>& at) { } at.print(out); return out;

Implementazione C++ template<class T> struct LessClass{ bool operator()(const T & a, const T & b)const{return a<b;} }; int main(){ //integer example int v[]={2,5,8,1,3,4,7,9,6,0}; TreeClass<int, LessClass<int> > T; for(int i=0;i<10;i++) T.insert(v[i]); cout<<t<<endl; cout<<"searching 5:"<< (T.search(5)? "Found":"Not found")<<endl; cout<<"searching 11:"<< (T.search(11)? "Found":"Not found")<<endl; cout<<"searching maximum:"<<t.maximum()<<endl; cout<<"searching minimum:"<<t.minimum()<<endl;

Implementazione C++ //char example char c[]="this_is_a."; TreeClass<char, LessClass<char> > Tc; for(int i=0;i<10;i++) Tc.insert(c[i]); cout<<tc<<endl; cout<<"searching s:"<< (Tc.search('s')? "Found":"Not found")<<endl; cout<<"searching v:"<< (Tc.search('v')? "Found":"Not found")<<endl; cout<<"searching maximum:"<<tc.maximum()<<endl; cout<<"searching minimum:"<<tc.minimum()<<endl; } cout<<endl; return 0;