Programmazione Mod. B - Alberi - prof. E. Burattini CAPITOLO 18 Programmazione Mod. B - Alberi - prof. E. Burattini
Programmazione Mod. B - Alberi - prof. E. Burattini I GRAFI A B C D E F A B C D E F 5 3 15 2 1 20 Min(A-D) = {A,B,E,F,C,D} -->14 A B C D E F 5 3 15 2 1 20 A B C D E F 5 3 2 1 Min(A-F) = {A,B,E,F} -->11 A B C D E F 5 3 A B C D E F 5 3 15 2 1 20 Programmazione Mod. B - Alberi - prof. E. Burattini
Programmazione Mod. B - Alberi - prof. E. Burattini C D E F 5 3 15 2 1 20 DEF. Un albero è un grafo senza cicli o circuiti A B C D E F 5 15 1 20 3 Programmazione Mod. B - Alberi - prof. E. Burattini
Programmazione Mod. B - Alberi - prof. E. Burattini GLI ALBERI COME STRUTTURE DATI Search Tree - (Albero di ricerca) - Memorizza informazioni in maniera tale che possano essere ritrovate molto velocemente e le operazioni di inserimento e cancellazione nodi sono molto efficienti. Programmazione Mod. B - Alberi - prof. E. Burattini
Programmazione Mod. B - Alberi - prof. E. Burattini Ricorsione lineare: al più una chiamata ricorsiva nell’ambito di uno stesso processo ricorsivo. Ricorsione non lineare: più di una chiamata ricorsiva nell’ambito di uno stesso processo ricorsivo. FUNCTION Fibonacci(N:integer):integer; BEGIN IF N=0 THEN Fibonacci:=0 ELSE IF N=1 THEN Fibonacci:=1 ELSE Fibonacci:= Fibonacci(N-2) + Fibonacci(N-1) END. main F(3) F(1) F(2) F(4) Fibonacci(4) F(0) main F(3) F(1) F(2) F(0) Fibonacci(3) Programmazione Mod. B - Alberi - prof. E. Burattini
Programmazione Mod. B - Alberi - prof. E. Burattini + 1 + F(2) F(1) + 1 + F(0) F(1) + 1 + 1 F(3) + F(2) F(3) + 2 3 F(5) F(4) + F(6) fibon1 Programmazione Mod. B - Alberi - prof. E. Burattini Fibonacci(6)
Programmazione Mod. B - Alberi - prof. E. Burattini ALBERI BINARI Un albero è binario se ogni nodo è al più collegato ad altri due Un albero binario è: L’albero vuoto oppure è costituito da una radice e da un sottoalbero sinistro e da un sottoalbero destro L’albero è una struttura ricorsiva non lineare. I suoi elementi sono detti nodi Programmazione Mod. B - Alberi - prof. E. Burattini
Programmazione Mod. B - Alberi - prof. E. Burattini I due disegni rappresentano due alberi uguali ma due alberi binari diversi. L’ovvio modo di rappresentare un albero consiste nell’assegnare ad ogni nodo due puntatori uno che punta al sottoalbero sinistro ed uno che punta al sottoalbero destro. Programmazione Mod. B - Alberi - prof. E. Burattini
Programmazione Mod. B - Alberi - prof. E. Burattini Per gestire gli alberi introduciamo un elemento costituito da nodi non più con uno ma con due campi per i puntatori. Attraverso questa struttura potremo rappresentare gli alberi di ricerca binari. Albero Binario Radice (root) Sotto albero Programmazione Mod. B - Alberi - prof. E. Burattini
Programmazione Mod. B - Alberi - prof. E. Burattini Ugo Carlo Giulio Emma Guido Carla Maria Anna Peppe Angela Nicola Programmazione Mod. B - Alberi - prof. E. Burattini
Programmazione Mod. B - Alberi - prof. E. Burattini Definiamo sotto albero ogni nodo in cui almeno un puntatore non è uguale a NIL ma punta ad un altro nodo o sotto albero. Definiamo radice di un sotto albero quel nodo che punta ad almeno un altro nodo (NB Negli alberi binari si può al massimo puntare a due nodi (destro e sinistro). La variabile dinamica albero può essere definita attraverso la sua radice, il nodo a partire dal quale si possono raggiungere tutti gli altri nodi della struttura. Un albero (sotto albero), che punta a NIL e cioè non contiene nodi è detto albero (sotto albero) vuoto. XXX Tree Left Structure Right Structure Programmazione Mod. B - Alberi - prof. E. Burattini
Altezza dell’albero= Massimo numero di livelli H=3 Livello del nodo X = 3 Radice (root) X Genitore Figlio Albero Binario Cammino (path) Sotto albero Nodi fratelli Foglie Programmazione Mod. B - Alberi - prof. E. Burattini
Programmazione Mod. B - Alberi - prof. E. Burattini Un albero binario è ordinato quando il campo chiave di ogni nodo è minore del campo chiave di ogni nodo del suo sottoalbero destro ed è maggiore del campo chiave di ogni nodo del suo sottoalbero sinistro. Si parla in questo caso anche di binary search tree (BST). Programmazione Mod. B - Alberi - prof. E. Burattini
Programmazione Mod. B - Alberi - prof. E. Burattini Un albero binario di ricerca (BST) è tale se: - le foglie sinistre hanno un valore del campo chiave inferiore del nodo padre - le foglie destre hanno un valore del campo chiave maggiore del nodo padre Campo chiave Key Field Left Right Sergio Toni Luigi Ugo Anna Dora Giulio Riccardo Guido Maria Roberto Programmazione Mod. B - Alberi - prof. E. Burattini
Programmazione Mod. B - Alberi - prof. E. Burattini CONST NullKey= ’un simbolo o valore per indicare NIL ' ; NullInfo=‘quando possibile assegna un significato al nodo NIL’ TYPE KItemType= STRING[20] InfoType= un data type per le informazioni non key BSTP=^BSTNode {puntatore a un nodo} BSTNode = RECORD Key:KItemType; Info: InfoType; Left, Right: BSTP END; VAR TNode:BSTP; Left Key Info Right TNode Programmazione Mod. B - Alberi - prof. E. Burattini
Programmazione Mod. B - Alberi - prof. E. Burattini Left Key Info Right TNode Le operazioni che ci interessa definire sono: creazione di un nuovo nodo con un valore assegnato ai campi dati (Key e Info) e NIL ai campi link (Left e Right) dispose (dealloca) di un nodo supposto che esso esista come variabile dinamica selezionare un nodo data una chiave selezionare le Info collegate al nodo selezionare il figlio a sinistra di un dato nodo selezionare il figlio a destra di un dato nodo Programmazione Mod. B - Alberi - prof. E. Burattini
Programmazione Mod. B - Alberi - prof. E. Burattini INTERFACE PROCEDURE MakeTNode(KeyValue:KItemType; TheInfo:InfoType; VAR TNode:BSTP); { Crea un nuovo nodo, assegnando a KeyValue e TheInfo un valore e il valore NIL per i campi Left e Right } PROCEDURE KillTNode(VAR TNode: BSTP); {dispose la memoria allocata per il TNode e poi pone il TNode a NIL. } PROCEDURE GetNodesKey(TNode:BSTP; VAR TheKey:KItemType); {ritorna il key field del nodo puntato da Tnode, se Tnode è NIL allora ritorna il valore di NullKey} PROCEDURE GetNodesInfo(TNode:BSTP; VAR TheInfo:InfoType); {ritorna le informazioni del nodo puntato da Tnode, se Tnode è NIL allora ritorna il valore di NullInfo} Left Key Info Right TNode CONST NullKey= ’un simbolo o valore per indicare NIL ' ; NullInfo=‘quando possibile assegna un significato al nodo NIL’ TYPE KItemType= STRING[20] InfoType= un data type per le informazioni non key BSTP=^BSTNode {puntatore a un nodo} BSTNode = RECORD Key:KItemType; Info: InfoType; Left, Right: BSTP END; VAR TNode:BSTP; Programmazione Mod. B - Alberi - prof. E. Burattini
Programmazione Mod. B - Alberi - prof. E. Burattini FUNCTION NodesLeftTree(TNode:BSTP) : BSTP; {ritorna il puntatore al sotto albero sinistro di Tnode. Se T Node è NIL allora ritorna NIL } FUNCTION NodesRightTree(TNode:BSTP) : BSTP; {ritorna il puntatore al sotto albero destro di Tnode. Se T Node è NIL allora ritorna NIL } Left Key Info Right TNode CONST NullKey= ’un simbolo o valore per indicare NIL ' ; NullInfo=‘quando possibile assegna un significato al nodo NIL’ TYPE KItemType= STRING[20] InfoType= un data type per le informazioni non key BSTP=^BSTNode {puntatore a un nodo} BSTNode = RECORD Key:KItemType; Info: InfoType; Left, Right: BSTP END; VAR TNode:BSTP; Programmazione Mod. B - Alberi - prof. E. Burattini
Programmazione Mod. B - Alberi - prof. E. Burattini PROCEDURE MakeTNode(KeyValue:KItemType; TheInfo:InfoType; VAR TNode:BSTP); { Crea un nuovo nodo, assegnando a KeyValue e TheInfo un valore e il valore NIL per i campi Left e Right } BEGIN new(Tnode); WITH TNode^ DO Key:=KeyValue; Info:=TheInfo; Left:=NIL; Right:=NIL END END; CONST NullKey= ’un simbolo o valore per indicare NIL ' ; NullInfo=‘quando possibile assegna un significato al nodo NIL’ TYPE KItemType= STRING[20] InfoType= un data type per le informazioni non key BSTP=^BSTNode {puntatore a un nodo} BSTNode = RECORD Key:KItemType; Info: InfoType; Left, Right: BSTP END; Left Key Info Right TNode Programmazione Mod. B - Alberi - prof. E. Burattini
Programmazione Mod. B - Alberi - prof. E. Burattini PROCEDURE KillTNode(VAR TNode :BSTP); {dispose la memoria allocata per il TNode e poi pone il TNode a NIL. } BEGIN IF Tnode <> NIL THEN BEGIN dispose(TNode); Tnode:=NIL END END; CONST NullKey= ’un simbolo o valore per indicare NIL ' ; NullInfo=‘quando possibile assegna un significato al nodo NIL’ TYPE KItemType= STRING[20] InfoType= un data type per le informazioni non key BSTP=^BSTNode {puntatore a un nodo} BSTNode = RECORD Key:KItemType; Info: InfoType; Left, Right: BSTP END; Left Key Info Right TNode Programmazione Mod. B - Alberi - prof. E. Burattini
Programmazione Mod. B - Alberi - prof. E. Burattini PROCEDURE GetNodesKey(TNode:BSTP; VAR TheKey:KItemType); {ritorna il key field del nodo puntato da Tnode, se Tnode è NIL allora ritorna il valore di NullKey} BEGIN IF TNode <> NIL THEN TheKey:= TNode ^.Key ELSE TheKey:= NullKey END; CONST NullKey= ’un simbolo o valore per indicare NIL ' ; NullInfo=‘quando possibile assegna un significato al nodo NIL’ TYPE KItemType= STRING[20] InfoType= un data type per le informazioni non key BSTP=^BSTNode {puntatore a un nodo} BSTNode = RECORD Key:KItemType; Info: InfoType; Left, Right: BSTP END; Left Key Info Right TNode Programmazione Mod. B - Alberi - prof. E. Burattini
Programmazione Mod. B - Alberi - prof. E. Burattini PROCEDURE GetNodesInfo(TNode:BSTP; VAR TheInfo:InfoType); {ritorna le informazioni del nodo puntato da Tnode, se Tnode è NIL allora ritorna il valore di NullInfo} BEGIN IF TNode <> NIL THEN TheInfo:= TNode ^.Info ELSE TheKey:= NullInfo END; CONST NullKey= ’un simbolo o valore per indicare NIL ' ; NullInfo=‘quando possibile assegna un significato al nodo NIL’ TYPE KItemType= STRING[20] InfoType= un data type per le informazioni non key BSTP=^BSTNode {puntatore a un nodo} BSTNode = RECORD Key:KItemType; Info: InfoType; Left, Right: BSTP END; Left Key Info Right TNode Programmazione Mod. B - Alberi - prof. E. Burattini
Programmazione Mod. B - Alberi - prof. E. Burattini FUNCTION NodesLeftTree(TNode:BSTP) : BSTP; {ritorna il puntatore al sotto albero sinistro di Tnode. Se T Node è NIL allora ritorna NIL } BEGIN IF Tnode <> NIL THEN NodesLeftTree:=Tnode^.Left ELSE NodesLeftTree:=NIL END: CONST NullKey= ’un simbolo o valore per indicare NIL ' ; NullInfo=‘quando possibile assegna un significato al nodo NIL’ TYPE KItemType= STRING[20] InfoType= un data type per le informazioni non key BSTP=^BSTNode {puntatore a un nodo} BSTNode = RECORD Key:KItemType; Info: InfoType; Left, Right: BSTP END; Left Key Info Right TNode Programmazione Mod. B - Alberi - prof. E. Burattini
Programmazione Mod. B - Alberi - prof. E. Burattini FUNCTION NodesRightTree(TNode:BSTP) : BSTP; {ritorna il puntatore al sotto albero destro di Tnode. Se T Node è NIL allora ritorna NIL } BEGIN IF Tnode <> NIL THEN NodesRightTree:=Tnode^. Right ELSE NodesRightTree:=NIL END: CONST NullKey= ’un simbolo o valore per indicare NIL ' ; NullInfo=‘quando possibile assegna un significato al nodo NIL’ TYPE KItemType= STRING[20] InfoType= un data type per le informazioni non key BSTP=^BSTNode {puntatore a un nodo} BSTNode = RECORD Key:KItemType; Info: InfoType; Left, Right: BSTP END; Left Key Info Right TNode Programmazione Mod. B - Alberi - prof. E. Burattini
Programmazione Mod. B - Alberi - prof. E. Burattini Pseudo codice per un algoritmo generalizzato di selezione nodi PROCEDURE GetNodeField(ANode:NodeP; VAR FieldVar: FieldType) IF ANode <> NIL THEN FieldVar ANode^.identificatore della variabile di campo selezionata ELSE FieldVar NullValue Programmazione Mod. B - Alberi - prof. E. Burattini
Programmazione Mod. B - Alberi - prof. E. Burattini Gli stessi dati possono essere contenuti in alberi binari di forma diversa. Ugo Toni Maria Anna Dora Sergio Giulio Guido Luigi Riccardo Anna Dora Sergio Giulio Luigi Guido Maria Riccardo Toni Ugo Sergio Toni Luigi Ugo Anna Dora Giulio Riccardo Guido Maria Programmazione Mod. B - Alberi - prof. E. Burattini
Programmazione Mod. B - Alberi - prof. E. Burattini Un albero si dice bilanciato se il livello di tutte le foglie è uguale all’altezza dell’albero o a questa stessa altezza meno 1. H=3 L=3 Foglie H=3 L=3 L=2 Programmazione Mod. B - Alberi - prof. E. Burattini
Programmazione Mod. B - Alberi - prof. E. Burattini Foglie L=3 L=2 L=4 L=5 L=1 L=0 H=5 Programmazione Mod. B - Alberi - prof. E. Burattini
Programmazione Mod. B - Alberi - prof. E. Burattini Un albero bilanciato si esplora per fare una ricerca in un numero di passi inferiore a quello necessario per esplorare un albero non bilanciato. Nell’esempio supponiamo di cercare Riccardo: Ugo Toni Maria Anna Dora Sergio Giulio Guido Luigi Riccardo Anna Dora Sergio Giulio Luigi Guido Maria Riccardo Toni Ugo 4 passi di computazione 6 passi di computazione Sergio Toni Luigi Ugo Anna Dora Giulio Riccardo Guido Maria Roberto 2 passi di computazione Programmazione Mod. B - Alberi - prof. E. Burattini
Programmazione Mod. B - Alberi - prof. E. Burattini Se un albero bilanciato ha M livelli, il numero di nodi di cui è formato può variare tra 2M e 2(M+1) -1. In un albero bilanciato il tempo massimo di ricerca è di O(log2 (N)) dove N è il numero di nodi. Programmazione Mod. B - Alberi - prof. E. Burattini
ALBERO BILANCIATO CON M LIVELLI Totale Nodi N° NODI N° NODI 1 M Totale Nodi Programmazione Mod. B - Alberi - prof. E. Burattini
Programmazione Mod. B - Alberi - prof. E. Burattini Serie geometrica Programmazione Mod. B - Alberi - prof. E. Burattini
Programmazione Mod. B - Alberi - prof. E. Burattini Supponiamo sia assegnata una lista di N oggetti tra i quali esiste una relazione d’ordine. Se riusciamo a inserire questi oggetti in un albero di ricerca bilanciato allora il numero di passi per trovare un qualunque oggetto è limitato da O(log2(N)). Se questo non avviene il caso peggiore in cui possiamo trovarci è pari a O(N). Toni Maria Ugo Riccardo Anna Dora Sergio Giulio Luigi Guido Si può dimostrare che un albero di ricerca binario costruito in maniera casuale, quindi non necessariamente bilanciato, effettua in media un numero di passi per effettuare la ricerca pari a 1.36 * O(log2(N)). Programmazione Mod. B - Alberi - prof. E. Burattini
Programmazione Mod. B - Alberi - prof. E. Burattini ESEMPIO Supponiamo di avere un albero di tipo BST, chiamiamo con Root il primo nodo. Scrivere una funzione LeftMost che fornisca il puntatore del nodo più a sinistra che si incontra a partire da Root. Sergio Toni Anna Dora Giulio Riccardo Guido Maria Roberto CONST NullKey= ’un simbolo o valore per indicare NIL ' ; NullInfo=‘quando possibile assegna un significato al nodo NIL’ TYPE KItemType= STRING[20] InfoType= un data type per le informazioni non key BSTP=^BSTNode {puntatore a un nodo} BSTNode = RECORD Key:KItemType; Info: InfoType; Left, Right: BSTP END; VAR Root:BSTP; Root Left Key Info Right Programmazione Mod. B - Alberi - prof. E. Burattini
FUNCTION LeftMost(Root: BSTP): BSTP; Definizione della funzione VAR NodoEsaminato:BSTP; Definizione delle variabili BEGIN IF EmptyTree(Root) THEN NodoEsaminato = NIL; ELSE NodoEsaminato = Root; Verifica se l’albero è vuoto WHILE NodesLeftTree(NodoEsaminato) <> NIL DO NodoEsaminato = NodesLeftTree(NodoEsaminato) ; LeftMost: = NodoEsaminato END: Cerca il nodo CONST NullKey= ’un simbolo o valore per indicare NIL ' ; NullInfo=‘quando possibile assegna un significato al nodo NIL’ TYPE KItemType= STRING[20] InfoType= un data type per le informazioni non key BSTP=^BSTNode {puntatore a un nodo} BSTNode = RECORD Key:KItemType; Info: InfoType; Left, Right: BSTP END; VAR Root:BSTP; FUNCTION NodesLeftTree(TNode:BSTP) : BSTP; BEGIN IF Tnode <> NIL THEN NodesLeftTree:=Tnode^.Left ELSE NodesLeftTree:=NIL END: Programmazione Mod. B - Alberi - prof. E. Burattini
Programmazione Mod. B - Alberi - prof. E. Burattini { Dato un albero binario calcolare il puntatore dell'ultimo nodo a sinistra.} Program AlberoSin(input,output); uses Crt, Alberi0; CONST var Albero,: BSTP; FUNCTION ChiaveNodiSin(Tree:BSTP):BSTP; BEGIN IF EmptyTree(NodesLeftTree(Tree)) THEN ChiaveNodiSin:=Tree ELSE ChiaveNodiSin:=ChiaveNodiSin(NodesLeftTree(Tree)); END; {************** MAIN***********} begin writeln('Costruiamo un Albero. '); BuildNameTree(Albero); WriteAlbero(Albero); writeln(' La chiave e'' ', ChiaveNodiSin(Albero)^.Key); end. Programmazione Mod. B - Alberi - prof. E. Burattini
Programmazione Mod. B - Alberi - prof. E. Burattini OPERAZIONI SUI BST Ogni nodo di un BST punta ad altri due nodi, ciascuno dei quali è una variabile dinamica di tipo record. Quindi una variabile di tipo BSTType, cioè un puntatore alla radice di un BST, che è a sua volta una variabile BST, può essere passata da un blocco ad un altro. In altre parole dato un nodo di un BST, questo è radice per i suoi sottoalberi e i nodi a cui punta sono a loro volta radici di altri sottoalberi. Pertanto possiamo adoperare ricorsivamente queste variabili. Poiché una variabile BST può essere interpretata o come nodo di un BST o come un sotto albero di un BST, pur essendo variabili dello stesso tipo parleremo nel primo caso di un tipo BSTP (puntatore a un nodo) e nel secondo caso di un tipo BSTType (puntatore a un albero) CONST NullKey= ’un simbolo o valore per indicare NIL ' ; NullInfo=‘quando possibile assegna un significato al nodo NIL’ TYPE KItemType= STRING[20] InfoType= un data type per le informazioni non key BSTP=^BSTNode {puntatore a un nodo} BSTNode = RECORD Key:KItemType; Info: InfoType; Left, Right: BSTP END; BSTType=BSTP VAR NomeAlbero:BSTType Nodo:BSTP; Left Key Info Right NomeAlbero Programmazione Mod. B - Alberi - prof. E. Burattini
Programmazione Mod. B - Alberi - prof. E. Burattini INTERFACE PROCEDURE MakeTree(VAR Tree: BSTType); {inizializza a NIL l’albero, creando un albero vuoto} PROCEDURE AddTNode(KeyValue:KItemType; TheInfo:InfoType;VAR Tree: BSTType; VAR Done:boolean); {aggiunge un nodo all’albero rispettando la struttura di un BST, se il KeyValue è già presente nell’albero non fa nulla e Done risulta False} PROCEDURE DeleteTNode(KeyValue:KItemType;VAR Tree: BSTType; VAR Done:boolean); {elimina il nodo con chiave KeyValue, se esso non esiste Done risulta False} FUNCTION SearchTNode(Tree: BSTType; KeyValue:KItemType): BSTP; {cerca il nodo con chiave KeyValue, se esso non esiste ritorna NIL} FUNCTION EmptyTree(Tree: BSTType): boolean; {ritorna vero se l’albero è vuoto} Programmazione Mod. B - Alberi - prof. E. Burattini
Programmazione Mod. B - Alberi - prof. E. Burattini IMPLEMENTATION PROCEDURE MakeTree(VAR Tree: BSTType); {inizializza a NIL l’albero, creando un albero vuoto} BEGIN Tree:=NIL END; FUNCTION EmptyTree(Tree: BSTType): boolean; {ritorna vero se l’albero è vuoto} BEGIN EmptyTree:=Tree=NIL END; Programmazione Mod. B - Alberi - prof. E. Burattini
ESEMPIO: COSTRUZIONE DI UN BST DI NOMI Left Key Info Right TNode CONST NullKey= ’ ' ; NullInfo=‘ ’ TYPE KItemType= STRING[20] InfoType= STRING[20] BSTP=^BSTNode {puntatore a un nodo} BSTNode = RECORD {variabile dinamica per un nodo} Key:KItemType; Info: InfoType; Left, {radice del sottoalbero di sinistra} Right: BSTP {radice del sottoalbero di destra} END; BSTType=BSTP; {definizione per la variabile albero} VAR NameTree:BSTType; Programmazione Mod. B - Alberi - prof. E. Burattini
COSTRUZIONE DI UN BST DI NOMI Maria Giulio Sergio Dora Guido Riccardo Toni Anna Roberto Supponiamo che vengano introdotti da tastiera i seguenti nomi: Maria Giulio Sergio Dora Guido Riccardo Toni Anna Roberto return Programmazione Mod. B - Alberi - prof. E. Burattini
Programmazione Mod. B - Alberi - prof. E. Burattini Pseudo codice MakeTree(NameTree) introduci Nome WHILE Nome <> NullKey DO AddTNode(Nome, NullInfo, NameTree, Success) IF NOT Success THEN segnala che il Nome esiste già introduci il nome mostra il messaggio di fine lavoro Programmazione Mod. B - Alberi - prof. E. Burattini
Programmazione Mod. B - Alberi - prof. E. Burattini CONST NullKey= ’ ' ; NullInfo=‘ ’ TYPE KItemType= STRING[20] InfoType= STRING[20] BSTP=^BSTNode BSTNode = RECORD Key:KItemType; Info: InfoType; Left, Right: BSTP END; BSTType=BSTP; VAR NameTree:BSTTYpe; PROCEDURE BuildNameTree(VAR NameTree: BSTType); {costruisce un albero a cui assegna un Nome dato in input} Nome:KItemType; Success: boolean; BEGIN MakeTree(NameTree); write(‘ Dammi un nome : ‘); readln(Nome); WHILE Nome <> NullKey DO AddTNode(Nome, NullInfo, NameTree, Success); IF NOT Success THEN writeln( Nome, ‘ esiste già’); readln(Nome) writeln(‘ L’albero è stato piantato’); Programmazione Mod. B - Alberi - prof. E. Burattini
ATTRAVERSAMENTO DI UN BST DEFINIZIONE DI ATTRAVERSAMENTO DI UN BST Sergio Toni Anna Dora Giulio Riccardo Guido Maria Roberto Visitare tutti i nodi di un BST di nomi, a partire dalla radice, e elencare i nomi in ordine crescente (o decrescente). Anna Dora Giulio Guido Maria Riccardo Roberto Sergio Toni Programmazione Mod. B - Alberi - prof. E. Burattini
Programmazione Mod. B - Alberi - prof. E. Burattini MOSTRA IL CONTENUTO DI UN BST Pseudo codice Mostra le Chiavi (KeyItem) di tutti i nodi del sottoalbero sinistro di NameTree Mostra la Chiave (KeyItem) della radice di NameTree Mostra le Chiavi (KeyItem) di tutti i nodi del sottoalbero destro di NameTree Sergio Toni Anna Dora Giulio Riccardo Guido Maria Roberto ShowTree(NodesLeftTree(NameTree)); GetNodesKey(NameTree, Nome); Writeln(Nome) ShowTree(NodesRightTree(NameTree)); Programmazione Mod. B - Alberi - prof. E. Burattini
Programmazione Mod. B - Alberi - prof. E. Burattini La procedura ShowTree(NameTree) è una procedura ricorsiva il cui caso base è rappresentato dall’albero vuoto (EmptyTree). In altre parole il processo di pop inizia non appena l’argomento di ShowTree(NameTree) è un albero vuoto. PROCEDURE ShowTree(NameTree: BSTType); VAR NodesKey: KItemType; BEGIN IF NOT EmptyTree(NameTree) THEN ShowTree(NodesLeftTree(NameTree)); GetNodesKey(NameTree, Nome); writeln(Nome) ShowTree(NodesRightTree(NameTree)); END END; Programmazione Mod. B - Alberi - prof. E. Burattini
Programmazione Mod. B - Alberi - prof. E. Burattini Esercizio Analizzare la seguente procedure ricorsiva e descrivere il suo comportamento con un esempio PROGRAM WriteAlbero(Tree:BSTP); PROCEDURE Wa(Tree:BSTP;I:integer); VAR J:integer; BEGIN IF NOT EmptyTree(Tree) THEN Wa(NodesRightTree(Tree),I+1); FOR J:=1 TO I DO write(' '); write(Tree^.Key); writeln; Wa(NodesLeftTree(Tree),I+1); END; {************* MAIN***********} Wa(Tree,1) Programmazione Mod. B - Alberi - prof. E. Burattini
Programmazione Mod. B - Alberi - prof. E. Burattini Ricorsione lineare: al più una chiamata ricorsiva nell’ambito di uno stesso processo ricorsivo. Ricorsione non lineare: più di una chiamata ricorsiva nell’ambito di uno stesso processo ricorsivo. FUNCTION Fibonacci(N:integer):integer; BEGIN IF N=0 THEN Fibonacci:=0 ELSE IF N=1 THEN Fibonacci:=1 ELSE Fibonacci:= Fibonacci(N-2) + Fibonacci(N-1) END. main F(3) F(1) F(2) F(4) Fibonacci(4) F(0) main F(3) F(1) F(2) F(0) Fibonacci(3) Programmazione Mod. B - Alberi - prof. E. Burattini
Programmazione Mod. B - Alberi - prof. E. Burattini + 1 + F(2) F(1) + 1 + F(0) F(1) + 1 + 1 F(3) + F(2) F(3) + 2 3 F(5) F(4) + F(6) fibon1 Programmazione Mod. B - Alberi - prof. E. Burattini Fibonacci(6)
Programmazione Mod. B - Alberi - prof. E. Burattini RICERCA DI UN DATO SU UN BST Sergio Toni Anna Dora Giulio Riccardo Guido Maria Roberto Riccardo ????????? Programmazione Mod. B - Alberi - prof. E. Burattini
Programmazione Mod. B - Alberi - prof. E. Burattini FUNCTION Binary (VAR Studenti: StudenteRecord; MatrCercata:StringaNome; Lo, Hi :integer) :integer VAR Mid:integer; BEGIN IF Lo>Hi THEN Binary := 0 ELSE Mid (Lo+Hi) DIV 2 IF Studenti[Mid].Matr=MatrCercata THEN Binary := Mid IF Studenti[Mid].Matr<MatrCercata THEN Binary := Binary(Studenti, MatrCercata, Mid+1, Hi) Binary := Binary(Studenti, MatrCercata, Lo, Mid-1) END; CASE BASE 1 CASE BASE 2 ESPRESSIONE RICORSIVA Programmazione Mod. B - Alberi - prof. E. Burattini
NodesLeftRight:=Tnode^. Right FUNCTION SearchTNode(Tree: BSTType; KeyValue:KItemType): BSTP; {cerca il nodo con chiave KeyValue, se esso non esiste ritorna NIL} VAR TheKey: KItemType; BEGIN IF EmptyTree(Tree) THEN SearchTNode NIL ELSE GetNodesKey(Tree, TheKey) IF TheKey = KeyValue THEN SearchTNode Tree IF KeyValue < TheKey SearchTNode SearchTNode(NodesLeftTree(Tree), KeyValue) SearchTNode SearchTNode(NodesRightTree(Tree), KeyValue) END END; TheKey:= TNode ^.Key NodesLeftTree:=Tnode^.Left NodesLeftRight:=Tnode^. Right Programmazione Mod. B - Alberi - prof. E. Burattini
Programmazione Mod. B - Alberi - prof. E. Burattini ESERCIZIO Sia assegnato un albero binario, scrivere un algoritmo tale che sposti ogni figlio sinistro nel corrispondente figlio destro e viceversa. A B C D E F G H A C B F E D H G Programmazione Mod. B - Alberi - prof. E. Burattini
Programmazione Mod. B - Alberi - prof. E. Burattini { Scrivere un algoritmo che dato un albero binario lo trasformi invertendo i figli sinistro e destro di ogni nodo } Program AlberoScambio(input,output); uses Crt, Alberi0; CONST NKey=-100; var Albero,Temp : BSTP; Item: KItemType; Chiave:KItemType; Info:InfoType; Done:boolean; PROCEDURE ScambiaNodi(Tree:BSTP); BEGIN IF NOT EmptyTree(Tree) THEN ScambiaNodi(NodesLeftTree(Tree)); ScambiaNodi(NodesRightTree(Tree)); Temp:=Tree^.Left; Tree^.Left:= Tree^.Right; Tree^.Right:=Temp; END; {************** MAIN***********} begin clrscr; writeln('Costruiamo un Albero. '); BuildNameTree(Albero); WriteAlbero(Albero); readln; {scambia nodi} ScambiaNodi(Albero); writeln(' SCAMBIO '); writeln(' FINE'); end. Programmazione Mod. B - Alberi - prof. E. Burattini
Programmazione Mod. B - Alberi - prof. E. Burattini AGGIUNTA DI UN DATO SU UN BST Per aggiungere un nodo a un BST è necessario innanzitutto verificare che l’Item non esiste già, perché in tal caso il nodo non viene aggiunto. Se non esiste bisogna trovare la sua corretta posizione nell’albero, cioè il suo genitore e mettere poi i figli a NIL. Sergio Toni Anna Dora Giulio Riccardo Guido Maria Roberto Rolando Programmazione Mod. B - Alberi - prof. E. Burattini
Programmazione Mod. B - Alberi - prof. E. Burattini PROCEDURE AddTNode(KeyValue:KItemType; TheInfo:InfoType;VAR Tree: BSTType; VAR Done:boolean); {aggiunge una foglia all’albero rispettando la struttura di un BST, se il KeyValue è già presente nell’albero non fa nulla e Done risulta False} PROCEDURE DeleteTNode(KeyValue:KItemType;VAR Tree: BSTType; VAR Done:boolean); {elimina il nodo con chiave KeyValue ricostruendo la struttura BST. Se il Nodo non esiste Done risulta False} Programmazione Mod. B - Alberi - prof. E. Burattini
Programmazione Mod. B - Alberi - prof. E. Burattini Se il nodo che vogliamo inserire, avente un certo KeyValue, esiste, allora Tnode non è vuoto e quindi non lo aggiungiamo altrimenti lo aggiungiamo Pseudo Codice di AddTNode Search(Tree, KeyValue, TNode, Parent) IF NOT EmptyTree(TNode) THEN Done FALSE ELSE crea e aggiungi un nuovo nodo come figlio del nodo Parent Done TRUE . Cerca sull’albero Tree il puntatore (TNode) al nodo con KeyValue, se esiste ritorna anche il padre, Parent, del nodo cercato altrimenti TNode=NIL. Programmazione Mod. B - Alberi - prof. E. Burattini
Programmazione Mod. B - Alberi - prof. E. Burattini PROCEDURE AddTNode(KeyValue:KItemType; TheInfo:InfoType;VAR Tree: BSTType; VAR Done: boolean); VAR Tnode, Parent : BSTP; {deve valere NIL se il nodo esiste già} ParentsKey: KeyItemType; {genitore del nodo da aggiungere} BEGIN Search(Tree, KeyValue, TNode, Parent) IF NOT EmptyTree(TNode) THEN {il nodo esiste già} Done := FALSE ELSE {crea e aggiungi un nuovo nodo come figlio del nodo Parent} IF EmptyTree(Parent) THEN {il nuovo nodo sarà la radice} MakeTNode(KeyValue, TheInfo, Tree) ELSE GetNodesKey(Parent, ParentsKey); {puntatore di ParentsKey} IF ParentsKey > KeyValue THEN {il nuovo nodo va a left} MakeTNode(KeyValue, TheInfo, Parent^.Left) ELSE {il nuovo nodo va a right} MakeTNode(KeyValue, TheInfo, Parent^.Right) END; Done := TRUE END Programmazione Mod. B - Alberi - prof. E. Burattini
Il padre dell’ultimo nodo esaminato durante la ricerca di KeyValue Search Search(Tree, KeyValue, TNode, Parent) Obiettivo: cercare un cammino verso un determinato nodo dell’albero. Se il nodo non esiste ritorna NIL. Se esiste ritorna il puntatore al nodo individuato e quello di suo padre. Il padre dell’ultimo nodo esaminato durante la ricerca di KeyValue Pseudo Codice Parent NIL {la root non ha genitori} TNode Tree {la radice è il primo nodo esaminato} GetNodesKey(TNode, NodesKey) {estrai la chiave del nodo in esame} WHILE ci sono altri nodi da esaminare AND non si è ancora trovato il nodo DO Parent TNode Tnode il sottoalbero legato al KeyValue EmptyTree(TNode) NodesKey <> KeyValue IF NodesKey > KeyValue THEN TNode radice del sottoalbero sinistro ELSE TNode radice del sottoalbero destro Programmazione Mod. B - Alberi - prof. E. Burattini
Programmazione Mod. B - Alberi - prof. E. Burattini PROCEDURE Search(Tree: BSTT, KeyValue: KItemType, VAR TNode, Parent: BSTP); VAR NodesKey: KItemType; BEGIN Parent:= NIL; {la root non ha genitori} Tnode:= Tree; {la radice è il primo nodo esaminato} GetNodesKey(TNode, NodesKey); {estrai la chiave del primo nodo} WHILE NOT EmptyTree(TNode) AND (NodesKey <> KeyValue) DO Parent:= Tnode; IF NodesKey > KeyValue THEN Tnode:= NodesLeftTree(TNode) ELSE Tnode:= NodesRightTree(TNode); GetNodesKey(TNode, NodesKey) {estrai la chiave del nodo in esame} END END; Ricordarsi che GetNodesKey nel caso trovi NIL ritorna NullKey Programmazione Mod. B - Alberi - prof. E. Burattini
Programmazione Mod. B - Alberi - prof. E. Burattini Pseudo Codice Parent NIL {la root non ha genitori} TNode Tree {la radice è il primo nodo esaminato} GetNodesKey(TNode, NodesKey) {estrai la chiave del nodo in esame} WHILE ci sono altri nodi da esaminare AND non si è ancora trovato il nodo DO Parent TNode Tnode il sottoalbero legato al KeyValue Search 19 13 21 Aggiungi 17 Tnode NIL 12 15 20 Aggiungi 22 Tnode = NIL 24 BEGIN Search(Tree, KeyValue, TNode, Parent) IF NOT EmptyTree(TNode) THEN {il nodo esiste già} Done := FALSE ELSE {crea e aggiungi un nuovo nodo come figlio del nodo Parent} IF EmptyTree(Parent) THEN MakeTNode(KeyValue, TheInfo, Tree) {il nuovo nodo sarà la radice} ELSE GetNodesKey(Parent, ParentsKey); IF ParentsKey > KeyValue THEN {il nuovo nodo va a sinistra} MakeTNode(KeyValue, TheInfo, Parent^.Left) ELSE {il nuovo nodo va a destra} MakeTNode(KeyValue, TheInfo, Parent^.Right) END; Done := TRUE END 14 17 23 26 22 16 18 AddTNode Programmazione Mod. B - Alberi - prof. E. Burattini
Programmazione Mod. B - Alberi - prof. E. Burattini ESERCIZIO {Scrivere una procedura o funzione che assegnato un albero binario di interi e un livello Lev conti il numero num di tutti i nodi presenti in quel livello. } 19 13 21 12 15 14 17 16 18 20 24 23 26 22 lev riga Programmazione Mod. B - Alberi - prof. E. Burattini
Programmazione Mod. B - Alberi - prof. E. Burattini 19 13 21 12 15 14 17 16 18 20 24 23 26 22 lev riga procedure ContaLivello(Tree:BSTP; riga,lev:integer;VAR num:integer); BEGIN if not (emptytree(tree)) THEN IF riga=lev THEN num:=num+1; IF riga<lev THEN ContaLivello(NodesLeftTree(tree) riga+1,lev,num); ContaLivello(NodesRightTree(tree), riga+1,lev,num); END;END;END; T23, riga=3, lev=3, num= 3 T26, riga=3, lev=3, num= 4 T14, riga=3, lev=3, num= 1 T17, riga=3, lev=3, num= 2 T24, riga=2, lev=3, num= 2 T12, riga=2, lev=3, num= 0 T15, riga=2, lev=3, num= 0 T24, riga=2, lev=3, num=4 T15, riga=2, lev=3, num= 2 T15, riga=2, lev=3, num= 1 T20, riga=2, lev=3, num= 2 T21, riga=1, lev=3, num= 2 T21, riga=1, lev=3, num= 4 T13, riga=1, lev=3, num= 2 T13, riga=1, lev=3, num= 0 T19, riga=0, lev=3, num= 4 T19, riga=0, lev=3, num= 2 T19, riga=0, lev=3, num= 0 Programmazione Mod. B - Alberi - prof. E. Burattini
Realizzare una procedura che elimina il nodo con chiave KeyValue Problema Realizzare una procedura che elimina il nodo con chiave KeyValue Ritorna la chiave CandsKey puntata da Candidate Pseudo Codice Search(Tree, KeyValue, Candidate, Parent) GetNodesKey(Candidate, CandsKey) IF CandsKey <> KeyValue THEN Done FALSE ELSE riorganizza l’albero dopo aver rimosso Candidate KillTNode(Candidate) Done TRUE Implica che se cerco di nuovo un nodo con chiave CandsKey non lo trovo e che l’albero che resta, deallocando il nodo Candidate, è ancora un BST Programmazione Mod. B - Alberi - prof. E. Burattini
QQQ RRR left right Eliminare Riccardo Analizziamo il problema della riorganizzazione dell’albero una volta eliminato un nodo. Caso a- il nodo da eliminare ha il sotto albero sinistro vuoto. QQQ RRR Parent Candidate left right Eliminare Riccardo Sergio Toni Anna Dora Giulio Riccardo Guido Maria Roberto Sergio Toni Anna Dora Giulio Riccardo Guido Maria Roberto Caso b- il nodo da eliminare ha il sotto albero destro vuoto. La procedura è analoga alla precedente.
Programmazione Mod. B - Alberi - prof. E. Burattini Pseudo Codice IF EmptyTree(NodesLeftTree(Candidate)) THEN LinkParent(Candidate, NodesRightTree(Candidate), Parent, Tree) ELSE IF EmptyTree(NodesRightTree(Candidate)) THEN LinkParent(Candidate, NodesLeftTree(Candidate), Parent, Tree) continua a riorganizzare l’albero QQQ RRR Parent Candidate left right PROCEDURE LinkParent (OldChild, NewChild, Parent: BSTP;VAR Tree: BSTType); {riorganizza l’albero BST dopo l’eliminazione di un nodo} Programmazione Mod. B - Alberi - prof. E. Burattini
Programmazione Mod. B - Alberi - prof. E. Burattini Riassunto dei tipi di cancellazione New Old Parent Old New PROCEDURE DeleteTNode(KeyValue:KItemType;VAR Tree: BSTType; VAR Done:boolean); {elimina il nodo con chiave KeyValue ricostruendo la struttura BST. Se il Nodo non esiste Done risulta False} Programmazione Mod. B - Alberi - prof. E. Burattini
Programmazione Mod. B - Alberi - prof. E. Burattini Nel caso in cui il Nodo da cancellare ha sia il sotto albero di sinistra che quello di destra allora si procede come segue: si sostituisce al nodo da cancellare o il nodo di valore maggiore del suo sottoalbero di sinistra o quello di valore minore del suo sotto albero di destra. Se questo nodo ha a sua volta un sottoalbero di destra e uno di sinistra ci si comporta nei suoi confronti come se fosse un nodo da cancellare e quindi si esegue la stessa procedura sopra descritta. Nodo da cancellare 35 5 3 40 80 38 8 30 5 3 40 35 80 38 8 Programmazione Mod. B - Alberi - prof. E. Burattini
Candidate, {puntatore al nodo candidato per la cancellatura} PROCEDURE DeleteTNode(KeyValue: KItemType; VAR Tree:BSTType; VAR Done:boolean); VAR Candidate, {puntatore al nodo candidato per la cancellatura} Parent, {puntatore al genitore del nodo candidato} OldCandidate :BSTP; CandsKey: KItemType: BEGIN Done:= TRUE Search(Tree, KeyValue, Candidate, Parent); GetNodesKey(Candidate, CandsKey); IF CandsKey<> KeyValue THEN Done:=FALSE ELSE IF EmptyTree(NodesLeftTree(Candidate)) THEN LinkParent(Candidate, NodesRightTree(Candidate), Parent, Tree) IF EmptyTree(NodesRightTree(Candidate)) THEN LinkParent(Candidate, NodesLeftTree(Candidate), Parent, Tree) GetNewCandidate(KeyValue, Candidate, Tree); KillTNode(Candidate); END; Se il sottoalbero sinistro è vuoto collega il genitore di candidate con la radice del sotto albero destro. Se Parent=NIL, cioè si vuole cancellare la radice allora poni in Tree la radice del sotto albero destro. Se il sottoalbero destro è vuoto collega il genitore di candidate con la radice del sotto albero sinistro. Se Parent=NIL, cioè si vuole cancellare la radice allora poni in Tree la radice del sotto albero sinistro. Fornisce il puntatore della Key da eliminare e quello del suo genitore. Se Candidate=NIL significa che la Key non c’è. Fornisce la chiave CandsKey di Candidate Non c’è niente da cancellare Se nessuno dei sue sotto alberi è vuoto allora chiama GetNewCandidate Programmazione Mod. B - Alberi - prof. E. Burattini
Programmazione Mod. B - Alberi - prof. E. Burattini PROCEDURE LinkParent(OldChild, NewChild, Parent: BSTP; VAR Tree:BSTType); {collega il nodo genitore con il sottoalbero connesso al nodo da cancellare} BEGIN IF Parent=NIL THEN {sostituiamo la root} Tree:= NewChild ELSE IF OldChild = NodesLeftTree(Parent) THEN Parent^.Left:=NewChild {sostituiamo al genitore il figlio sinistro} Parent^.Right:=NewChild {sostituiamo al genitore il figlio destro} END; Old Parent New Old New Programmazione Mod. B - Alberi - prof. E. Burattini
Realizzare una procedura che elimina il nodo con chiave KeyValue Problema Realizzare una procedura che elimina il nodo con chiave KeyValue Ritorna la chiave CandsKey puntata da Candidate Pseudo Codice Search(Tree, KeyValue, Candidate, Parent) GetNodesKey(Candidate, CandsKey) IF CandsKey <> KeyValue THEN Done FALSE ELSE riorganizza l’albero dopo aver rimosso Candidate KillTNode(Candidate) Done TRUE Implica che se cerco di nuovo un nodo con chiave CandsKey non lo trovo e che l’albero che resta, deallocando il nodo Candidate, è ancora un BST Pseudo Codice IF EmptyTree(NodesLeftTree(Candidate)) THEN LinkParent(Candidate, NodesRightTree(Candidate), Parent, Tree) ELSE IF EmptyTree(NodesRightTree(Candidate)) THEN LinkParent(Candidate, NodesLeftTree(Candidate), Parent, Tree) continua a riorganizzare l’albero Programmazione Mod. B - Alberi - prof. E. Burattini
Search(Tree, Key, Candidate, Parent) RICAPITOLANDO Search(Tree, Key, Candidate, Parent) fornisce il puntatore Candidate del node che ha chiave Key e il puntatore Parent come padre a b Key=b Candidate=P(b) Parent=P(a) LinkParent(Old, New, Parent, Tree) collega New con Parent eliminando OLD, se Parent=NIL, cioè Old=Tree è la radice allora mette New al posto di Old e quindi di Tree Parent New Old Old New Programmazione Mod. B - Alberi - prof. E. Burattini
Pesudo codice di DeleteTNode(Key, Tree, Done) Search(Tree, Key, Candidate, Parent) Fornisce il puntatore della Key da eliminare e quello del suo genitore. Se Candidate=NIL significa che la Key non c’è. GetNodesKey(Candidate, CandsKey) Fornisce la chiave CandsKey di Candidate IF CandsKey<> Key Se la chiave trovata e quella di partenza non corrispondono CandsKey=NIL allora esci ELSE Se il sottoalbero sinistro è vuoto collega il genitore di candidate con la radice del sotto albero destro. Se Parent=NIL, cioè si vuole cancellare la radice allora poni in Tree la radice del sotto albero destro. Se il sottoalbero destro è vuoto collega il genitore di candidate con la radice del sotto albero sinistro. Se Parent=NIL, cioè si vuole cancellare la radice allora poni in Tree la radice del sotto albero sinistro. Se nessuno dei due sotto alberi è vuoto allora chiama GetNewCandidate
Programmazione Mod. B - Alberi - prof. E. Burattini Nodo da cancellare 30 5 3 40 35 80 38 8 old candidate parent 35 5 3 40 80 38 8 Programmazione Mod. B - Alberi - prof. E. Burattini
Programmazione Mod. B - Alberi - prof. E. Burattini Ricerca OldCandidate a partire dal suo nodo destro con la conseguenza che trova il più piccolo di questo sottoalbero (Candidate) (Dummy vale NIL) Pseudo Codice di GetNewCandidate OldCandidate Candidate Search(NodesRightTree(OldCandidate), KeyValue, Dummy, Candidate) OldCandidate^.Key Candidate^.Key CandsKey := Candidate^.Key; Search(NodesRightTree(OldCandidate), CandsKey, Dummy, Parent) IF Parent = NIL THEN LinkParent(Candidate,NodesRightTree(Candidate), OldCandidate, Tree) ELSE LinkParent(Candidate,NodesRightTree(Candidate), Parent, Tree) Sostituisci il nodo da cancellare con Candidate Riprendi la chiave del nodo spostato Cerca il più piccolo nodo del sottoalbero destro del nodo spostato a partire dalla sua primitiva posizione Se il nodo da cancellare è la root e segue immediatamente il padre allora collega il sottoalbero destro con la root Collega il sottoalbero destro con il padre del nodo spostato Programmazione Mod. B - Alberi - prof. E. Burattini
Programmazione Mod. B - Alberi - prof. E. Burattini PROCEDURE GetNewCandidate(KeyValue: KItemType; VAR Candidate:BSTP; VAR Tree:BSTType); VAR Dummy, {variabile ausiliare per la chiamata alla Search} Parent, OldCandidate :BSTP; CandsKey: KItemType: BEGIN OldCandidate := Candidate Search(NodesRightTree(OldCandidate), KeyValue, Dummy, Candidate) OldCandidate^.Info := Candidate^.Info ; OldCandidate^.Key := Candidate^.Key; CandsKey := Candidate^.Key; Search(NodesRightTree(OldCandidate), CandsKey, Dummy, Parent); IF Parent= NIL THEN LinkParent(Candidate,NodesRightTree(Candidate), OldCandidate, Tree) ELSE LinkParent(Candidate,NodesRightTree(Candidate), Parent, Tree) END; Programmazione Mod. B - Alberi - prof. E. Burattini
Cancellare il nodo 30 DeleteTNode(KeyValue, Tree, Done) 90 50 95 30 34 40 36 15 93 98 100 17 13 35 47 Search(Tree, KeyValue, Candidate, Parent) GetNodesKey(Candidate, CandsKey); IF CandsKey<> KeyValue THEN Done:=FALSE ELSE IF EmptyTree(NodesLeftTree(Candidate)) THEN LinkParent(Candidate, NodesRightTree(Candidate), Parent, Tree) IF EmptyRight(NodesRightTree(Candidate)) THEN LinkParent(Candidate, NodesLeftTree(Candidate), Parent, Tree) GetNewCandidate(KeyValue, Candidate, Tree); KillTNode(Candidate); Done:= TRUE 34 P30 GetNewCandidate(KeyValue, Candidate, Tree); NIL P34 OldCandidate := Candidate Search(NodesRightTree(OldCandidate), KeyValue, Dummy, Candidate) OldCandidate^.Key := Candidate^.Key; CandsKey := Candidate^.Key; Search(NodesRightTree(OldCandidate), CandsKey, Dummy, Parent); IF Parent = NIL THEN LinkParent(Candidate,NodesRightTree(Candidate), OldCandidate, Tree) ELSE LinkParent(Candidate,NodesRightTree(Candidate), Parent, Tree) END; 30 P34 P36 P40 P35 34 38 P40 34 P36 P34
Programmazione Mod. B - Alberi - prof. E. Burattini 45 30 60 25 35 55 65 23 27 33 37 53 57 63 67 21 24 26 28 31 34 36 38 51 54 56 58 61 64 66 68 cancella il nodo 45 51 30 60 25 35 55 65 23 27 33 37 53 57 63 67 21 24 26 28 31 34 36 38 54 56 58 61 64 66 68 45 60 30 25 35 55 65 23 27 33 37 53 57 63 67 21 24 26 28 31 34 36 38 51 54 56 58 61 64 66 68 51 Programmazione Mod. B - Alberi - prof. E. Burattini
Programmazione Mod. B - Alberi - prof. E. Burattini {cancella nodo} write(' cancella il nodo '); readln(chiave); DeleteTNode(Chiave , Albero,Done); IF DONE=FALSE THEN writeln(' il nodo', Chiave,' non è nell''albero'); WriteAlbero(Albero); readln; writeln; writeln(' FINE'); end. Program AlberoProva(input,output); uses Crt, Alberi0; CONST NKey=-100; var Albero : BSTP; Item: KItemType; Chiave:KItemType; Info:InfoType; Done:boolean; {************** MAIN***********} begin clrscr; writeln('Costruiamo un Albero. '); BuildNameTree(Albero); WriteAlbero(Albero); Info:=33; writeln(' inserisci il nodo - per finire -100'); readln(chiave); WHILE Chiave<>NKey DO BEGIN AddTNode(Chiave,Info, Albero,Done); write(' aggiungi il nodo - per finire -100 >>> '); END; readln; albpr6 Programmazione Mod. B - Alberi - prof. E. Burattini
Programmazione Mod. B - Alberi - prof. E. Burattini PROCEDURE StampaAlbero(Tree : BSTP; riga,inizio,fine:integer); var medio: integer; BEGIN if not(emptytree(tree)) then begin medio:=(inizio+fine) div 2; gotoxy(medio,riga); GetNodesKey(tree,Item); write(Item); StampaAlbero(NodesLeftTree(tree),riga+1,inizio,medio); StampaAlbero(NodesRightTree(tree),riga+1,medio,fine); END; 1 1 80 PROCEDURE WriteAlbero(Tree:BSTP); PROCEDURE Wa(Tree:BSTP;I:integer); VAR J:integer; BEGIN IF NOT EmptyTree(Tree) THEN Wa(NodesRightTree(Tree),I+1); FOR J:=1 TO I DO write(' '); write(Tree^.Key); writeln; Wa(NodesLeftTree(Tree),I+1); END; Programmazione Mod. B - Alberi - prof. E. Burattini
Programmazione Mod. B - Alberi - prof. E. Burattini ALGORITMI DI ATTRAVERSAMENTO DI BST Algoritmi di attraversamento di un albero: LNR - (LeftNodeRight) - Attraversamento inorder Per ogni nodo 1 - Visita il sottoalbero sinistro 2 - Visita il nodo root 3 - Visita il sottoalbero destro NLR - (NodeLeftRight) - Attraversamento pre-order Per ogni nodo 1 - Visita il nodo root 2 - Visita il sottoalbero sinistro 3 - Visita il sottoalbero destro LRN - (LeftRightNode) - Attraversamento post-order Per ogni nodo 1 - Visita il sottoalbero sinistro 2 - Visita il sottoalbero destro 3 - Visita il nodo root Programmazione Mod. B - Alberi - prof. E. Burattini
Programmazione Mod. B - Alberi - prof. E. Burattini LNR - (LeftNodeRight) - Attraversamento ordinato Per ogni nodo 1 - Visita il sottoalbero sinistro 2 - Visita il nodo 3 - Visita il sottoalbero destro PROCEDURE ShowTree(NameTree: BSTType); VAR NodesKey: KItemType; BEGIN IF NOT EmptyTree(NameTree) THEN ShowTree(NodesLeftTree(NameTree)); GetNodesKey(NameTree, Nome); writeln(Nome) ShowTree(NodesRightTree(NameTree)); END END; PROCEDURE Traverse(Root) IF root <> NIL THEN Traverse(Root^.Left) {visita tutti i nodi del sottoalbero sinistro} Visit(Root) Traverse(Root^.Right) {visita tutti i nodi del sottoalbero destro} Programmazione Mod. B - Alberi - prof. E. Burattini
Programmazione Mod. B - Alberi - prof. E. Burattini NLR - (NodeLeftRight) - Attraversamento pre-ordinato Per ogni nodo 1 - Visita il nodo root 2 - Visita il sottoalbero sinistro 3 - Visita il sottoalbero destro PROCEDURE StampaAlbero(Tree : BSTP; riga,inizio,fine:integer); var medio: integer; BEGIN if not(emptytree(tree)) then begin medio:=(inizio+fine) div 2; gotoxy(medio,riga); GetNodesKey(tree,Item); write(Item); StampaAlbero(NodesLeftTree(tree),riga+1,inizio,medio); StampaAlbero(NodesRightTree(tree),riga+1,medio,fine); END PROCEDURE Traverse(Root) IF root <> NIL THEN Visit(Root) Traverse(Root^.Left) {visita tutti i nodi del sottoalbero sinistro} Traverse(Root^.Right) {visita tutti i nodi del sottoalbero destro} Programmazione Mod. B - Alberi - prof. E. Burattini
Programmazione Mod. B - Alberi - prof. E. Burattini LRN - (LeftRightNode) - Attraversamento post-ordinato Per ogni nodo 1 - Visita il sottoalbero sinistro 2 - Visita il sottoalbero destro 3 - Visita il nodo root PROCEDURE Traverse(Root) IF root <> NIL THEN Traverse(Root^.Left) {visita tutti i nodi del sottoalbero sinistro} Traverse(Root^.Right) {visita tutti i nodi del sottoalbero destro} Visit(Root) Programmazione Mod. B - Alberi - prof. E. Burattini
Eliminare un BST senza lasciare spazzatura. Problema Eliminare un BST senza lasciare spazzatura. Soluzione Attraversa l’albero con un algoritmo LRN (post-order) e cancella ogni nodo incontrato. E’ utilizzato l’LRN perché la root è sempre l’ultima ad essere deallocata dopo aver deallocato i nodi figli, e quindi nessun link è eliminato prima del dovuto. PROCEDURE KillTree(VAR Tree:BSTType); BEGIN IF NOT EmptyTree(Tree) THEN KillTree(NodesLeftTree(Tree); KillTree(NodesRightTree(Tree); KillTNode(Tree) END END; Sergio Toni Anna Dora Giulio Riccardo Guido Maria Roberto
Espressioni aritmetiche. Problema Espressioni aritmetiche. Notazione infissa (5*3)/(4-1) Visita LNR inorder / * 5 3 - 4 1 PROCEDURE Traverse(Root) IF root <> NIL THEN Traverse(Root^.Left) Visit(Root) Traverse(Root^.Right) Notazione Polacca Inversa 5 3 * 4 1 - / Visita LRN post-order / * 5 3 - 4 1 PROCEDURE Traverse(Root) IF root <> NIL THEN Traverse(Root^.Left Traverse(Root^.Right) Visit(Root) Notazione Polacca Diretta / * 5 3 - 4 1 Visita NLR pre-order PROCEDURE Traverse(Root) IF root <> NIL THEN Visit(Root) Traverse(Root^.Left) Traverse(Root^.Right) / * 5 3 - 4 1 Programmazione Mod. B - Alberi - prof. E. Burattini
Programmazione Mod. B - Alberi - prof. E. Burattini ESERCIZIO { Dato un albero binario calcolare quanti nodi hanno il sottoalbero sinistro nullo.} Program AlberoConta(input,output); uses Alberi0; CONST NKey=-100; var Albero,Temp : BSTP; Item: KItemType; Chiave:KItemType; Info:InfoType; Done:boolean; Cont:integer; FUNCTION ContaNodiSinNul(Tree:BSTP):integer; VAR cont1:integer; BEGIN IF EmptyTree(Tree) THEN ContaNodiSinNul:= 0 else IF NOT EmptyTree(NodesRightTree(Tree)) THEN ContaNodiSinNul:=ContaNodiSinNul(NodesRightTree(Tree)); IF NOT EmptyTree(NodesLeftTree(Tree)) THEN ContaNodiSinNul:=ContaNodiSinNul(NodesLeftTree(Tree)) ELSE ContaNodiSinNul:=ContaNodiSinNul(NodesRightTree(Tree))+1; END; {************** MAIN***********} begin writeln('Costruiamo un Albero. '); BuildNameTree(Albero); WriteAlbero(Albero); writeln('Ci sono ', ContaNodiSinNul(Albero),' nodi con sotto albero sinistro nullo'); end. Programmazione Mod. B - Alberi - prof. E. Burattini ALBCONT2
Programmazione Mod. B - Alberi - prof. E. Burattini { Scrivere un algoritmo che dato un albero binario scriva le chiavi in ordine prima crescente e poi decrescente } Program ScriviAlbero (input,output); uses Alberi0; CONST NKey=-100; var Albero : BSTP; Item, Chiave : KItemType; Info:InfoType; Done:boolean; PROCEDURE Crescente(Tree:BSTP); BEGIN IF Not EmptyTree(Tree) THEN Crescente(NodesLeftTree(Tree)); write(' ',tree^.key); Crescente(NodesRightTree(Tree)); END; PROCEDURE DeCrescente(Tree:BSTP); DeCrescente(NodesRightTree(Tree)); DeCrescente(NodesLeftTree(Tree)); {************** MAIN***********} begin writeln('Costruiamo un Albero. '); BuildNameTree(Albero); WriteAlbero(Albero); writeln('crescente '); Crescente(Albero); writeln('decrescente '); DeCrescente(Albero); end. Programmazione Mod. B - Alberi - prof. E. Burattini
Programmazione Mod. B - Alberi - prof. E. Burattini ESERCIZI 1- Scrivere una procedura che assegnato un albero binario di interi positivi non ordinato restituisca un puntatore al valore massimo e quante volte questo valore massimo è contenuto nell'albero. ES2GEN04 2- Scrivere una procedura che assegnato un albero binario di interi positivi non ordinato e due numeri positivi N1 e N2 restituisca la quantità di numeri pari compresi tra N1 e N2. ES2FEB04 3- Assegnato un albero non ordinato di interi scrivere una procedura ricorsiva che trasformi l'albero non ordinato in un albero BST. Determinare l'altezza dell'albero non ordinato e dell'albero BST. ESN0N0R2 Programmazione Mod. B - Alberi - prof. E. Burattini
Programmazione Mod. B - Alberi - prof. E. Burattini uses Alberi0; CONST NKey=-100; VAR Albero: BSTP; Cont:integer; PROCEDURE ContaNodiNul(Tree:BSTP; VAR Conta:integer); BEGIN IF NOT EmptyTree(Tree) THEN ContaNodiNul(NodesLeftTree(Tree),Conta); ContaNodiNul(NodesRightTree(Tree),Conta); IF (Tree^.Right=NIL) AND (Tree^.key MOD 2 <>0) THEN Conta:=Conta+1; END; {************** MAIN***********} writeln('Costruiamo un Albero. '); BuildNameTree(Albero); WriteAlbero(Albero); cont:=0; ContaNodiNul(Albero,Cont); writeln(' Ci sono ',cont,' nodi con sotto albero destro nullo e padre dispari'); END. PROGRAM DispariNulli(input,output); { Assegnato un albero BST di numeri interi, fornire una procedura ricorsiva che dica quanti nodi, la cui chiave è un numero dispari, hanno sottoalbero destro nullo..} Programmazione Mod. B - Alberi - prof. E. Burattini
ALBERO BILANCIATO CON M LIVELLI Totale Nodi N° NODI N° NODI 1 M Totale Nodi Programmazione Mod. B - Alberi - prof. E. Burattini
Controllo bilanciamento ESERCIZIO { Dato un albero binario non bilanciato costruire un albero bilanciato.} Controllo bilanciamento Non bilanciato bilanciato Da Albero a Vettore Bilanciamento Stampa Programmazione Mod. B - Alberi - prof. E. Burattini
Controllo bilanciamento 1 2 5 3 7 8 9 Controllo bilanciamento Non bilanciato Da Albero a Vettore 1 2 3 5 7 8 9 bilanciato 1 2 5 3 7 8 9 Bilanciamento Stampa Programmazione Mod. B - Alberi - prof. E. Burattini 1 2 3 5 7 8 9
Programmazione Mod. B - Alberi - prof. E. Burattini FUNCTION UnisciAlberi(e:KItemType;a,b:BSTP) : BSTP; {crea un albero con chiave ‘e’ e sottoalbero sinistro ‘a’ e destro ‘b’ eventualmente anche vuoti } VAR c:BSTP; BEGIN new(c); c^.left:=a; c^.right:=b; c^.key:=e; UnisciAlberi:=c; END; e x a y z b w Programmazione Mod. B - Alberi - prof. E. Burattini
Programmazione Mod. B - Alberi - prof. E. Burattini {************** MAIN***********} BEGIN writeln('Costruiamo un Albero. '); BuildNameTree(Albero); IF not ControlloBilanciamento(Albero) THEN Vmax:=0; DaAlberoAVettore(Albero,V,Vmax); Bilanciato:=Vet2ALb(V,1,Vmax); writeln(ControlloBilanciamento(Bilanciato)); END ELSE writeln(' FINE'); END. Program Bilanciare(input,output); uses Alberi0; CONST NKey=-100; TYPE Vettore=ARRAY[1..40] OF integer; var Albero,Bilanciato : BSTP; Item: KItemType; Chiave:KItemType; Info:InfoType; Done:boolean; V:vettore; I,Vmax:integer; FUNCTION vet2alb(vx:vettore;i,j:integer):BSTP; {a partire dal vettore V ordinato genero l'albero vet2alb} PROCEDURE DaAlberoAVettore(A:BSTP;VAR V:vettore;VAR max:integer); {Dato un albero BST costruisce un vettore ordinato} FUNCTION Bilancia(A:BSTP):integer; {Dato un albero controlla se è bilanciato, quasi-bilanciato o non bilancitao} PROCEDURE ControllaBilanciamento(A:BSTP); Programmazione Mod. B - Alberi - prof. E. Burattini
Programmazione Mod. B - Alberi - prof. E. Burattini FUNCTION Bilancia(A:BSTP;VAR cmax,cmin:integer;livello:integer):integer; BEGIN IF not EmptyTree(A) THEN IF EmptyTree(NodesRightTree(A)) OR EmptyTree(NodesLeftTree(A)) THEN IF cmax<livello THEN cmax:=livello; IF cmin>livello THEN cmin:=livello; END; bilancia:=bilancia(NodesRightTree(A),cmax,cmin,livello+1); bilancia:=bilancia(NodesleftTree(A),cmax,cmin,livello+1); Bilancia:=cmax-cmin FUNCTION ControlloBilanciamento(A:BSTP):boolean; VAR cmx,cmn:integer; BEGIN cmx:=0;cmn:=maxint; IF Bilancia(A,cmx,cmn,0)=0 Then BEGIN ControlloBilanciamento:=TRUE;writeln(' L''albero è bilanciato') END ELSE IF Bilancia(A,cmx,cmn,0)=1 Then BEGIN ControlloBilanciamento :=TRUE;writeln(' L''albero è quasi bilanciato') ControlloBilanciamento:=FALSE;writeln(' L''albero non è bilanciato'); END; Programmazione Mod. B - Alberi - prof. E. Burattini
Programmazione Mod. B - Alberi - prof. E. Burattini PROCEDURE DaAlberoAVettore(A:BSTP;VAR V:vettore;VAR max:integer); VAR I:integer; BEGIN IF NOT EmptyTree(A) THEN DaAlberoAVettore(NodesLeftTree(A),V,max); Max:=max+1; V[max]:=Tree^.key; DaAlberoAVettore(NodesRightTree(A),V,max); END; {************** MAIN***********} begin writeln('Costruiamo un Albero. '); BuildNameTree(Albero); WriteAlbero(Albero); ControllaBilanciamento(Albero); Vmax:=0; DaAlberoAVettore(Albero,V,Vmax); Bilanciato:=Vet2ALb(V,1,Vmax); ControllaBilanciamento(Bilanciato); writeln; writeln(' FINE'); readln; end. Programmazione Mod. B - Alberi - prof. E. Burattini
Programmazione Mod. B - Alberi - prof. E. Burattini {************** MAIN***********} begin writeln('Costruiamo un Albero. '); BuildNameTree(Albero); WriteAlbero(Albero); ControllaBilanciamento(Albero); Vmax:=0; DaAlberoAVettore(Albero,V,Vmax); Bilanciato:=Vet2ALb(V,1,Vmax); ControllaBilanciamento(Bilanciato); writeln(' FINE'); end. FUNCTION vet2alb(vx:vettore;i,j:integer):BSTP; {a partire dal vettore V ordinato genero l'albero vet2alb} VAR K:integer; BEGIN IF I>J THEN Vet2alb:=NIL ELSE IF I=J THEN Vet2alb:=UnisciAlberi(Vx[I],NIL,NIL) K:=(I+J) DIV 2; Vet2alb:=UnisciAlberi(Vx[K],vet2alb(Vx,I,K-1),vet2alb(vx,K+1,j)) END; FUNCTION UnisciAlberi(e:KItemType;a,b:BSTP) : BSTP; {crea un albero con chiave ‘e’ e sottoalbero sinistro ‘a’ e destro ‘b’ eventualmente anche vuoti } VAR c:BSTP; BEGIN new(c); c^.left:=a; c^.right:=b; c^.key:=e; UnisciAlberi:=c; END; ALBBIL3 Programmazione Mod. B - Alberi - prof. E. Burattini
Programmazione Mod. B - Alberi - prof. E. Burattini Vet2ALb(V,1,Vmax); UnisciAlberi(Vx[K],vet2alb(Vx,I,K-1),vet2alb(vx,K+1,j)) g f e d c b a 7 6 5 4 3 2 1 d f e g c a b UnisciAlberi(Vx[4],vet2alb(Vx,1,3),vet2alb(vx, 5,7)) d Vet2ALb(V,1,7); K=4 Vet2ALb(V,1,3); K=2 b Vet2ALb(V,5,7); K=6 f UnisciAlberi(Vx[2],vet2alb(Vx,1,1),vet2alb(vx, 3,3)) UnisciAlberi(Vx[4],vet2alb(Vx,1,3),vet2alb(vx, 6,7)) Vet2ALb(V,1,1); K=1 a Vet2ALb(V,3,3); K=3 c Vet2ALb(V,5,5); K=5 e Vet2ALb(V,7,7); K=7 g Programmazione Mod. B - Alberi - prof. E. Burattini
{calcola le parentele } ESERCIZIO LA FAMIGLIA {calcola le parentele } Descritte le parentele secondo un albero non ordinato scrivere le funzioni FUNCTION Padre {dato un nome determinare se ha un padre e chi è} PROCEDURE Figlio {dato un nome determinare se ha uno o due figli e chi sono} FUNCTION Nonno {dato un nome determinare chi è il nonno} FUNCTION Fratello {dato un nome determinare se ha un fratello e chi è} FUNCTION Zio {dato un nome determinare se ha uno zio e chi è} END; Programmazione Mod. B - Alberi - prof. E. Burattini
Programmazione Mod. B - Alberi - prof. E. Burattini Esercizio . Dato un albero determinare quanti nonni hanno un solo nipote. Programmazione Mod. B - Alberi - prof. E. Burattini
Programmazione Mod. B - Alberi - prof. E. Burattini FINE Programmazione Mod. B - Alberi - prof. E. Burattini