CAPITOLO 18
description
Transcript of CAPITOLO 18
Programmazione Mod. B - Alberi - prof. E. Burattini
1
Programmazione Mod. B - Alberi - prof. E. Burattini
2
A
B C
D
EF
5 3
15
2
1
20
3
A
B C
D
EF
5 3 2
1
3
Min(A-F) = {A,B,E,F} -->11 A
B C
D
EF
5 3
3
Min(A-D) = {A,B,E,F,C,D} -->14 A
B C
D
EF
5 3
15
2
1
20
3
A
B C
D
EF
5 3
15
2
1
20
3
I GRAFI
A
B C
D
EF
Programmazione Mod. B - Alberi - prof. E. Burattini
3
A
B C
D
EF
5 3
15
2
1
20
3
A B C D E FA 5 20 15B 5 3 C 2 1D 20 2E 3 3F 15 1 3
DEF. Un albero è un grafo senza cicli o circuiti
A
B C
D
EF
5
151
20
3
A B C D E FA 5 20 15B 5 C 1D 20 E 3F 15 1 3
Programmazione Mod. B - Alberi - prof. E. Burattini
4
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
5
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.
main
F(3)
F(1) F(2)
F(4)
F(2)
Fibonacci(4)
F(1) F(0)
F(1) F(0)
main
F(3)
F(1) F(2)
F(1) F(0)
Fibonacci(3)
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.
Programmazione Mod. B - Alberi - prof. E. Burattini
6
Fibonacci(6)F(6)
F(5)F(4) +
F(2) F(3)+
F(2) F(1)+F(0)F(1) + 01 +
1 F(3)+
F(0)F(1) + 01 +
2
1 1+
3
F(3)
F(1)
F(2)
F(4)
F(5)
F(3)
F(6)
F(1) F(2)
F(3)
F(4)
F(2)
F(2)F(0)F(1)
F(0)
F(1)
F(0)F(1) F(1) F(0)F(0)F(1)
fibon1
Programmazione Mod. B - Alberi - prof. E. Burattini
7
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
8
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
9
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
10
Ugo
CarloGiulio
Emma Guido Carla Maria
Anna Peppe Angela Nicola
Programmazione Mod. B - Alberi - prof. E. Burattini
11
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.
XXX
Tree
Left Structure Right Structure
Un albero (sotto albero), che punta a NIL e cioè non contiene nodi è detto albero (sotto albero) vuoto.
Programmazione Mod. B - Alberi - prof. E. Burattini
12
Albero Binario
Radice (root)
Sotto albero
Cammino(path)
X
Genitore
Figlio
Livello del nodo X = 3
Nodi fratelli
Altezza dell’albero= Massimo numero di livelliH=3
Foglie
Programmazione Mod. B - Alberi - prof. E. Burattini
13
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
14
Sergio
Toni
Luigi UgoAnna
Dora
Giulio
RiccardoGuido
Maria
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 chiaveKey FieldLeft Right
Roberto
Programmazione Mod. B - Alberi - prof. E. Burattini
15
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
16
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
Left Key Info Right
TNode
Programmazione Mod. B - Alberi - prof. E. Burattini
17
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}
CONSTNullKey= ’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 keyBSTP=^BSTNode {puntatore a un nodo}
BSTNode = RECORD Key:KItemType;
Info: InfoType; Left, Right: BSTP END;
VARTNode:BSTP;
Left Key Info Right
TNode
Programmazione Mod. B - Alberi - prof. E. Burattini
18
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
CONSTNullKey= ’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 keyBSTP=^BSTNode {puntatore a un nodo}
BSTNode = RECORD Key:KItemType;
Info: InfoType; Left, Right: BSTP END;
VARTNode:BSTP;
Programmazione Mod. B - Alberi - prof. E. Burattini
19
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 BEGIN
Key:=KeyValue;Info:=TheInfo;Left:=NIL;Right:=NIL
ENDEND;
CONSTNullKey= ’un simbolo o valore per indicare NIL ' ;NullInfo=‘quando possibile assegna un significato al nodo NIL’TYPEKItemType= STRING[20]InfoType= un data type per le informazioni non keyBSTP=^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
20
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
ENDEND;
CONSTNullKey= ’un simbolo o valore per indicare NIL ' ;NullInfo=‘quando possibile assegna un significato al nodo NIL’TYPEKItemType= STRING[20]InfoType= un data type per le informazioni non keyBSTP=^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
21
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 ^.KeyELSE TheKey:= NullKey
END;
CONSTNullKey= ’un simbolo o valore per indicare NIL ' ;NullInfo=‘quando possibile assegna un significato al nodo NIL’TYPEKItemType= STRING[20]InfoType= un data type per le informazioni non keyBSTP=^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
22
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 ^.InfoELSE TheKey:= NullInfo
END;
CONSTNullKey= ’un simbolo o valore per indicare NIL ' ;NullInfo=‘quando possibile assegna un significato al nodo NIL’TYPEKItemType= STRING[20]InfoType= un data type per le informazioni non keyBSTP=^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
23
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^.LeftELSE NodesLeftTree:=NIL
END:
CONSTNullKey= ’un simbolo o valore per indicare NIL ' ;NullInfo=‘quando possibile assegna un significato al nodo NIL’TYPEKItemType= STRING[20]InfoType= un data type per le informazioni non keyBSTP=^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
24
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^. RightELSE NodesRightTree:=NIL
END:
CONSTNullKey= ’un simbolo o valore per indicare NIL ' ;NullInfo=‘quando possibile assegna un significato al nodo NIL’TYPEKItemType= STRING[20]InfoType= un data type per le informazioni non keyBSTP=^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
25
Pseudo codice per un algoritmo generalizzato di selezione nodi
PROCEDURE GetNodeField(ANode:NodeP; VAR FieldVar: FieldType)
IF ANode <> NIL THENFieldVar ANode^.identificatore della variabile di campo selezionata
ELSE FieldVar NullValue
Programmazione Mod. B - Alberi - prof. E. Burattini
26
Gli stessi dati possono essere contenuti in alberi binari di forma diversa.
Ugo
ToniMaria
Anna
Dora
SergioGiulio
Guido
Luigi Riccardo
Anna
Dora
Sergio
Giulio
Luigi
Guido
Maria
Riccardo
Toni
Ugo
Sergio
Toni
Luigi UgoAnna
Dora
Giulio
RiccardoGuido
Maria
Programmazione Mod. B - Alberi - prof. E. Burattini
27
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
28
H=5
FoglieL=3
L=2
L=4
L=5
L=1
L=0
Programmazione Mod. B - Alberi - prof. E. Burattini
29
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
ToniMaria
Anna
Dora
SergioGiulio
Guido
Luigi Riccardo
Anna
Dora
Sergio
Giulio
Luigi
Guido
Maria
Riccardo
Toni
Ugo
Sergio
Toni
Luigi UgoAnna
Dora
Giulio
RiccardoGuido
Maria
Roberto
4 passi di computazione
2 passi di computazione
6 passi di computazione
Programmazione Mod. B - Alberi - prof. E. Burattini
30
In un albero bilanciato il tempo massimo di ricerca è di O(log2 (N))
dove N è il numero di nodi.
Se un albero bilanciato ha M livelli, il numero di nodi di cui è
formato può variare tra
2M e 2(M+1) -1.
Programmazione Mod. B - Alberi - prof. E. Burattini
31
ALBERO BILANCIATO CON M LIVELLI
Totale Nodi
N°NODI
1M2
02
12
1
1
0
21M
i
i
N°NODI
0
1
MM2
02
12
Totale Nodi
M
i
i
0
2
Programmazione Mod. B - Alberi - prof. E. Burattini
32
M
i
iM
i
i N0
1
0
221
x
xaax
MM
i
i
1
)1( 1
0
Serie geometrica
1a 2x
1221
)21(2 1
1
0
M
MM
i
i
12121 1 MM N
122 1 MM N
Programmazione Mod. B - Alberi - prof. E. Burattini
33
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).
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)).
Toni
Maria
Ugo
Riccardo
Anna
Dora
Sergio
Giulio
Luigi
Guido
N O(N) LOG(N) 1,36*LOG(N)1.000 1.000 9,97 14
1.000.000 1.000.000 19,93 27100.000.000 100.000.000 26,58 36
Programmazione Mod. B - Alberi - prof. E. Burattini
34
ESEMPIOSupponiamo 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
RiccardoGuido
Maria
Roberto
Left Key Info Right
CONSTNullKey= ’un simbolo o valore per indicare NIL ' ;NullInfo=‘quando possibile assegna un significato al nodo NIL’TYPEKItemType= STRING[20]InfoType= un data type per le informazioni non keyBSTP=^BSTNode {puntatore a un nodo}
BSTNode = RECORD Key:KItemType;
Info: InfoType;Left, Right: BSTP END;
VAR Root:BSTP;
Root
Programmazione Mod. B - Alberi - prof. E. Burattini
35
CONSTNullKey= ’un simbolo o valore per indicare NIL ' ;NullInfo=‘quando possibile assegna un significato al nodo NIL’TYPEKItemType= STRING[20]InfoType= un data type per le informazioni non keyBSTP=^BSTNode {puntatore a un nodo}
BSTNode = RECORD Key:KItemType;
Info: InfoType;Left, Right: BSTP END;
VAR Root:BSTP;
FUNCTION LeftMost(Root: BSTP): BSTP;
VARNodoEsaminato:BSTP;
BEGINIF EmptyTree(Root) THEN NodoEsaminato = NIL;ELSE NodoEsaminato = Root;
WHILE NodesLeftTree(NodoEsaminato) <> NIL DO NodoEsaminato = NodesLeftTree(NodoEsaminato) ;
LeftMost: = NodoEsaminatoEND:
Definizione della funzione
Definizione delle variabili
Verifica se l’albero è vuoto
Cerca il nodo
FUNCTION NodesLeftTree(TNode:BSTP) : BSTP;BEGIN
IF Tnode <> NIL THEN NodesLeftTree:=Tnode^.LeftELSE NodesLeftTree:=NIL
END:
Programmazione Mod. B - Alberi - prof. E. Burattini
36
{ Dato un albero binario calcolare il puntatore dell'ultimo nodo a sinistra.}
Program AlberoSin(input,output);uses Crt, Alberi0;CONSTvar Albero,: BSTP;
FUNCTION ChiaveNodiSin(Tree:BSTP):BSTP;BEGINIF EmptyTree(NodesLeftTree(Tree)) THEN ChiaveNodiSin:=Tree ELSE
BEGINChiaveNodiSin:=ChiaveNodiSin(NodesLeftTree(Tree));END;
END;
{************** MAIN***********}beginwriteln('Costruiamo un Albero. '); BuildNameTree(Albero); WriteAlbero(Albero); writeln(' La chiave e'' ', ChiaveNodiSin(Albero)^.Key);end.
Programmazione Mod. B - Alberi - prof. E. Burattini
37
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’TYPEKItemType= STRING[20]InfoType= un data type per le informazioni non keyBSTP=^BSTNode {puntatore a un nodo}
BSTNode = RECORD Key:KItemType;
Info: InfoType;Left, Right: BSTP END;
BSTType=BSTPVARNomeAlbero:BSTTypeNodo:BSTP;
Left Key Info Right
NomeAlbero
Programmazione Mod. B - Alberi - prof. E. Burattini
38
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
39
IMPLEMENTATION
PROCEDURE MakeTree(VAR Tree: BSTType);{inizializza a NIL l’albero, creando un albero vuoto}BEGIN
Tree:=NILEND;
FUNCTION EmptyTree(Tree: BSTType): boolean;{ritorna vero se l’albero è vuoto} BEGIN
EmptyTree:=Tree=NILEND;
Programmazione Mod. B - Alberi - prof. E. Burattini
40
ESEMPIO: COSTRUZIONE DI UN BST DI NOMI
Left Key Info Right
TNode
CONSTNullKey= ’ ' ;NullInfo=‘ ’TYPEKItemType= 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
41
COSTRUZIONE DI UN BST DI NOMI
Sergio
Toni
Anna
Dora
Giulio
RiccardoGuido
Maria
Roberto
MariaGiulioSergioDora GuidoRiccardoToniAnnaRobertoreturn
Supponiamo che vengano introdotti da tastiera i seguenti nomi:
Programmazione Mod. B - Alberi - prof. E. Burattini
42
Pseudo codice
MakeTree(NameTree)introduci NomeWHILE 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
43
CONSTNullKey= ’ ' ;NullInfo=‘ ’TYPEKItemType= 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}VAR
Nome:KItemType;Success: boolean;
BEGINMakeTree(NameTree);write(‘ Dammi un nome : ‘);readln(Nome);WHILE Nome <> NullKey DO BEGIN AddTNode(Nome, NullInfo, NameTree, Success); IF NOT Success THEN
writeln( Nome, ‘ esiste già’); write(‘ Dammi un nome : ‘); readln(Nome) END;
writeln(‘ L’albero è stato piantato’);END;
Programmazione Mod. B - Alberi - prof. E. Burattini
44
DEFINIZIONE DIATTRAVERSAMENTO DI UN BST
Visitare tutti i nodi di un BST di nomi, a partire dalla radice, e elencare i nomi in ordine crescente (o decrescente).
AnnaDoraGiulioGuidoMariaRiccardoRobertoSergioToni
Sergio
Toni
Anna
Dora
Giulio
RiccardoGuido
Maria
Roberto
Programmazione Mod. B - Alberi - prof. E. Burattini
45
MOSTRA IL CONTENUTO DI UN BST
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
RiccardoGuido
Maria
Roberto
ShowTree(NodesLeftTree(NameTree));
GetNodesKey(NameTree, Nome);
Writeln(Nome)
ShowTree(NodesRightTree(NameTree));
Pseudo codice
Programmazione Mod. B - Alberi - prof. E. Burattini
46
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 BEGIN
ShowTree(NodesLeftTree(NameTree));
GetNodesKey(NameTree, Nome);
writeln(Nome)
ShowTree(NodesRightTree(NameTree));
END
END;
Programmazione Mod. B - Alberi - prof. E. Burattini
47
PROGRAM WriteAlbero(Tree:BSTP); PROCEDURE Wa(Tree:BSTP;I:integer); VAR J:integer; BEGIN IF NOT EmptyTree(Tree) THEN BEGIN Wa(NodesRightTree(Tree),I+1); FOR J:=1 TO I DO write(' '); write(Tree^.Key); writeln; Wa(NodesLeftTree(Tree),I+1); END; END;{************* MAIN***********}BEGINIF NOT EmptyTree(Tree) THEN Wa(Tree,1)END;
EsercizioAnalizzare la seguente procedure ricorsiva e descrivere il suo comportamento con un esempio
Programmazione Mod. B - Alberi - prof. E. Burattini
48
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.
main
F(3)
F(1) F(2)
F(4)
F(2)
Fibonacci(4)
F(1) F(0)
F(1) F(0)
main
F(3)
F(1) F(2)
F(1) F(0)
Fibonacci(3)
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.
Programmazione Mod. B - Alberi - prof. E. Burattini
49
Fibonacci(6)F(6)
F(5)F(4) +
F(2) F(3)+
F(2) F(1)+F(0)F(1) + 01 +
1 F(3)+
F(0)F(1) + 01 +
2
1 1+
3
F(3)
F(1)
F(2)
F(4)
F(5)
F(3)
F(6)
F(1) F(2)
F(3)
F(4)
F(2)
F(2)F(0)F(1)
F(0)
F(1)
F(0)F(1) F(1) F(0)F(0)F(1)
fibon1
Programmazione Mod. B - Alberi - prof. E. Burattini
50
RICERCA DI UN DATO SU UN BST
Sergio
Toni
Anna
Dora
Giulio
RiccardoGuido
Maria
Roberto
Riccardo ?????????
Programmazione Mod. B - Alberi - prof. E. Burattini
51
FUNCTION Binary (VAR Studenti: StudenteRecord; MatrCercata:StringaNome; Lo, Hi :integer) :integer
VARMid:integer;
BEGINIF Lo>Hi THEN Binary := 0ELSE BEGIN Mid (Lo+Hi) DIV 2 IF Studenti[Mid].Matr=MatrCercata THEN
Binary := Mid ELSE
IF Studenti[Mid].Matr<MatrCercata THEN Binary := Binary(Studenti, MatrCercata, Mid+1, Hi)ELSE Binary := Binary(Studenti, MatrCercata, Lo, Mid-1)
END;END;
CASE BASE 2
ESPRESSIONE RICORSIVA
CASE BASE 1
Programmazione Mod. B - Alberi - prof. E. Burattini
52
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 NILELSE BEGIN GetNodesKey(Tree, TheKey) IF TheKey = KeyValue THEN
SearchTNode Tree ELSE
IF KeyValue < TheKey SearchTNode SearchTNode(NodesLeftTree(Tree), KeyValue)ELSE SearchTNode SearchTNode(NodesRightTree(Tree), KeyValue)
ENDEND;
TheKey:= TNode ^.Key
NodesLeftTree:=Tnode^.Left
NodesLeftRight:=Tnode^. Right
Programmazione Mod. B - Alberi - prof. E. Burattini
53
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
DF E
H G
Programmazione Mod. B - Alberi - prof. E. Burattini
54
{ 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);
BEGINIF NOT EmptyTree(Tree) THEN BEGIN ScambiaNodi(NodesLeftTree(Tree)); ScambiaNodi(NodesRightTree(Tree)); Temp:=Tree^.Left; Tree^.Left:= Tree^.Right; Tree^.Right:=Temp; END;END;
{************** MAIN***********}
beginclrscr; writeln('Costruiamo un Albero. '); BuildNameTree(Albero); WriteAlbero(Albero); readln; {scambia nodi} ScambiaNodi(Albero); writeln(' SCAMBIO '); WriteAlbero(Albero); writeln(' FINE'); readln;
end.
Programmazione Mod. B - Alberi - prof. E. Burattini
55
AGGIUNTA DI UN DATO SU UN BST
Sergio
Toni
Anna
Dora
Giulio
RiccardoGuido
Maria
Roberto
Rolando
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.
Programmazione Mod. B - Alberi - prof. E. Burattini
56
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
57
Pseudo Codice di AddTNode
Search(Tree, KeyValue, TNode, Parent)
IF NOT EmptyTree(TNode) THENDone FALSE
ELSEcrea e aggiungi un nuovo nodo come figlio del nodo ParentDone TRUE
Se il nodo che vogliamo inserire, avente un certo KeyValue, esiste, allora Tnode non è vuoto e
quindi non lo aggiungiamo altrimenti lo aggiungiamo
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
58
PROCEDURE AddTNode(KeyValue:KItemType; TheInfo:InfoType;VAR Tree: BSTType; VAR Done: boolean);
VARTnode, Parent : BSTP; {deve valere NIL se il nodo esiste già}ParentsKey: KeyItemType; {genitore del nodo da aggiungere}
BEGINSearch(Tree, KeyValue, TNode, Parent)IF NOT EmptyTree(TNode) THEN {il nodo esiste già}
Done := FALSEELSE {crea e aggiungi un nuovo nodo come figlio del nodo Parent}
BEGIN IF EmptyTree(Parent) THEN {il nuovo nodo sarà la radice}
MakeTNode(KeyValue, TheInfo, Tree) ELSE
BEGIN 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
END;
Programmazione Mod. B - Alberi - prof. E. Burattini
59
SearchSearch(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.
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
GetNodesKey(TNode, NodesKey) {estrai la chiave del nodo in esame}
EmptyTree(TNode) NodesKey <> KeyValue
IF NodesKey > KeyValue THEN TNode radice del sottoalbero sinistroELSE TNode radice del sottoalbero destro
Il padre dell’ultimo nodo esaminatodurante la ricerca di KeyValue
Programmazione Mod. B - Alberi - prof. E. Burattini
60
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
BEGIN
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
61
19
13 21
12 15
14 17
16 18
20 24
23 26
Aggiungi 17 Tnode NIL
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
GetNodesKey(TNode, NodesKey) {estrai la chiave del nodo in esame}
Aggiungi 22
22
Tnode = NIL
BEGINSearch(Tree, KeyValue, TNode, Parent)IF NOT EmptyTree(TNode) THEN {il nodo esiste già}
Done := FALSEELSE {crea e aggiungi un nuovo nodo come figlio del nodo Parent} BEGIN IF EmptyTree(Parent) THEN MakeTNode(KeyValue, TheInfo, Tree) {il nuovo nodo sarà la radice} ELSE
BEGINGetNodesKey(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 := TRUEEND
END;
AddTNode
Search
Programmazione Mod. B - Alberi - prof. E. Burattini
62
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
63T19, riga=0,
lev=3, num= 0
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)) THENBEGINIF riga=lev THEN num:=num+1;IF riga<lev THENBEGIN ContaLivello(NodesLeftTree(tree)
riga+1,lev,num); ContaLivello(NodesRightTree(tree), riga+1,lev,num);END;END;END;
T13, riga=1,
lev=3, num= 0
T12, riga=2,
lev=3, num= 0
T15, riga=2,
lev=3, num= 0
T14, riga=3,
lev=3, num= 1
T17, riga=3,
lev=3, num= 2
T15, riga=2,
lev=3, num= 1
T15, riga=2,
lev=3, num= 2
T13, riga=1,
lev=3, num= 2
T21, riga=1,
lev=3, num= 2
T20, riga=2,
lev=3, num= 2
T24, riga=2,
lev=3, num= 2
T23, riga=3,
lev=3, num= 3
T26, riga=3,
lev=3, num= 4
T24, riga=2,
lev=3, num=4
T21, riga=1,
lev=3, num= 4
T19, riga=0,
lev=3, num= 2
T19, riga=0,
lev=3, num= 4
Programmazione Mod. B - Alberi - prof. E. Burattini
64
ProblemaRealizzare una procedura che elimina il nodo con chiave KeyValue
Pseudo CodiceSearch(Tree, KeyValue, Candidate, Parent)GetNodesKey(Candidate, CandsKey)IF CandsKey <> KeyValue THEN
Done FALSEELSE
riorganizza l’albero dopo aver rimosso CandidateKillTNode(Candidate)Done TRUE
Ritorna la chiave CandsKey puntata da Candidate
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
65
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
Sergio
Toni
Anna
Dora
Giulio
RiccardoGuido
Maria
Roberto
Sergio
Toni
Anna
Dora
Giulio
RiccardoGuido
Maria
Roberto
Caso b- il nodo da eliminare ha il sotto albero destro vuoto.La procedura è analoga alla precedente.
Eliminare Riccardo
Programmazione Mod. B - Alberi - prof. E. Burattini
66
Pseudo Codice
IF EmptyTree(NodesLeftTree(Candidate)) THENLinkParent(Candidate, NodesRightTree(Candidate), Parent, Tree)
ELSEIF EmptyTree(NodesRightTree(Candidate)) THEN LinkParent(Candidate, NodesLeftTree(Candidate), Parent, Tree)ELSE continua a riorganizzare l’albero
PROCEDURE LinkParent (OldChild, NewChild, Parent: BSTP;VAR Tree: BSTType);{riorganizza l’albero BST dopo l’eliminazione di un nodo}
QQQ
RRR
Parent
Candidate
left right
Programmazione Mod. B - Alberi - prof. E. Burattini
67
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
68
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
30
5
3
40
35
80
38
8
35
5
3
40
35
80
38
8
Programmazione Mod. B - Alberi - prof. E. Burattini
69
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)ELSE IF EmptyTree(NodesRightTree(Candidate)) THEN LinkParent(Candidate, NodesLeftTree(Candidate), Parent, Tree) ELSE GetNewCandidate(KeyValue, Candidate, Tree);
KillTNode(Candidate);END;
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
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 sue sotto alberi è vuoto allora chiama GetNewCandidate
Non c’è niente da cancellare
Programmazione Mod. B - Alberi - prof. E. Burattini
70
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:= NewChildELSE IF OldChild = NodesLeftTree(Parent) THEN
Parent^.Left:=NewChild {sostituiamo al genitore il figlio sinistro} ELSE
Parent^.Right:=NewChild {sostituiamo al genitore il figlio destro}END;
New
Old
Parent
Old
New
Programmazione Mod. B - Alberi - prof. E. Burattini
71
ProblemaRealizzare una procedura che elimina il nodo con chiave KeyValue
Pseudo CodiceSearch(Tree, KeyValue, Candidate, Parent)GetNodesKey(Candidate, CandsKey)IF CandsKey <> KeyValue THEN
Done FALSEELSE
riorganizza l’albero dopo aver rimosso CandidateKillTNode(Candidate)Done TRUE
Ritorna la chiave CandsKey puntata da Candidate
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)) THENLinkParent(Candidate, NodesRightTree(Candidate), Parent, Tree)
ELSEIF EmptyTree(NodesRightTree(Candidate)) THEN LinkParent(Candidate, NodesLeftTree(Candidate), Parent, Tree)ELSE continua a riorganizzare l’albero
Programmazione Mod. B - Alberi - prof. E. Burattini
72
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=bCandidate=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
OldNew
Programmazione Mod. B - Alberi - prof. E. Burattini
73
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 nessuno dei due sotto alberi è vuoto allora chiama GetNewCandidate
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.
Programmazione Mod. B - Alberi - prof. E. Burattini
74
35
5
3
40
35
80
38
8
Nodo da cancellare
30
5
3
40
35
80
38
8
old
candidate
parent
Programmazione Mod. B - Alberi - prof. E. Burattini
75
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)
Ricerca OldCandidate a partire dal suo nodo destro con la conseguenza che trova il più piccolo di questo sottoalbero (Candidate) (Dummy vale NIL)
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
Collega il sottoalbero destro con il padre del nodo spostato
Se il nodo da cancellare è la root e segue immediatamente il padre allora collega il sottoalbero destro con la root
Programmazione Mod. B - Alberi - prof. E. Burattini
76
PROCEDURE GetNewCandidate(KeyValue: KItemType; VAR Candidate:BSTP; VAR Tree:BSTType);
VARDummy, {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
77
90
50 95
30
34
40
3615
93 98
10017
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) ELSE IF EmptyRight(NodesRightTree(Candidate)) THEN LinkParent(Candidate, NodesLeftTree(Candidate), Parent, Tree) ELSE GetNewCandidate(KeyValue, Candidate, Tree);KillTNode(Candidate);Done:= TRUE
Cancellare il nodo 30
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;
P30
P4030 NIL P34
34
34
P40 34 P34 P363834
P34 P35 P36
GetNewCandidate(KeyValue, Candidate, Tree);
DeleteTNode(KeyValue, Tree, Done)
Programmazione Mod. B - Alberi - prof. E. Burattini
78
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
45
6030
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
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
Programmazione Mod. B - Alberi - prof. E. Burattini
79
Program AlberoProva(input,output);uses Crt, Alberi0;CONST NKey=-100;var Albero : BSTP; Item: KItemType; Chiave:KItemType; Info:InfoType; Done:boolean;
{************** MAIN***********}beginclrscr; 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 >>> '); readln(chiave); END; WriteAlbero(Albero); readln;
{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;WriteAlbero(Albero);writeln;writeln(' FINE');readln;end.
albpr6
Programmazione Mod. B - Alberi - prof. E. Burattini
80
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;END;
PROCEDURE WriteAlbero(Tree:BSTP); PROCEDURE Wa(Tree:BSTP;I:integer); VAR J:integer; BEGIN IF NOT EmptyTree(Tree) THEN BEGIN Wa(NodesRightTree(Tree),I+1); FOR J:=1 TO I DO write(' '); write(Tree^.Key); writeln; Wa(NodesLeftTree(Tree),I+1); END;
1 1 80
Programmazione Mod. B - Alberi - prof. E. Burattini
81
ALGORITMI DI ATTRAVERSAMENTO DI BST
Algoritmi di attraversamento di un albero:
LNR - (LeftNodeRight) - Attraversamento inorder Per ogni nodo1 - Visita il sottoalbero sinistro 2 - Visita il nodo root3 - Visita il sottoalbero destroNLR - (NodeLeftRight) - Attraversamento pre-order Per ogni nodo1 - Visita il nodo root2 - Visita il sottoalbero sinistro 3 - Visita il sottoalbero destro
LRN - (LeftRightNode) - Attraversamento post-order Per ogni nodo1 - Visita il sottoalbero sinistro 2 - Visita il sottoalbero destro3 - Visita il nodo root
Programmazione Mod. B - Alberi - prof. E. Burattini
82
LNR - (LeftNodeRight) - Attraversamento ordinato Per ogni nodo1 - Visita il sottoalbero sinistro 2 - Visita il nodo3 - Visita il sottoalbero destro
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}
PROCEDURE ShowTree(NameTree: BSTType);VAR NodesKey: KItemType;BEGIN
IF NOT EmptyTree(NameTree) THEN BEGIN
ShowTree(NodesLeftTree(NameTree));
GetNodesKey(NameTree, Nome);
writeln(Nome)
ShowTree(NodesRightTree(NameTree));
END
END;
Programmazione Mod. B - Alberi - prof. E. Burattini
83
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}
NLR - (NodeLeftRight) - Attraversamento pre-ordinato Per ogni nodo1 - Visita il nodo root2 - 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
Programmazione Mod. B - Alberi - prof. E. Burattini
84
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)
LRN - (LeftRightNode) - Attraversamento post-ordinato Per ogni nodo1 - Visita il sottoalbero sinistro 2 - Visita il sottoalbero destro3 - Visita il nodo root
Programmazione Mod. B - Alberi - prof. E. Burattini
85
ProblemaEliminare un BST senza lasciare spazzatura.
SoluzioneAttraversa 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 BEGIN
KillTree(NodesLeftTree(Tree);KillTree(NodesRightTree(Tree);KillTNode(Tree)
ENDEND; Sergio
Toni
Anna
Dora
Giulio
RiccardoGuido
Maria
Roberto
Programmazione Mod. B - Alberi - prof. E. Burattini
86
ProblemaEspressioni aritmetiche.
Notazione Polacca Inversa 5 3 * 4 1 - /
Visita LRNpost-order
Notazione Polacca Diretta/ * 5 3 - 4 1
Visita NLRpre-order
/
*
5 3
-
4 1
Notazione infissa(5*3)/(4-1)
Visita LNRinorder
/
*
5 3
-
4 1
/
*
5 3
-
4 1
PROCEDURE Traverse(Root)IF root <> NIL THEN
Visit(Root)Traverse(Root^.Left)Traverse(Root^.Right)
PROCEDURE Traverse(Root)IF root <> NIL THEN
Traverse(Root^.LeftTraverse(Root^.Right) Visit(Root)
PROCEDURE Traverse(Root)IF root <> NIL THEN
Traverse(Root^.Left)Visit(Root)Traverse(Root^.Right)
Programmazione Mod. B - Alberi - prof. E. Burattini
87
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;BEGINIF EmptyTree(Tree) THEN ContaNodiSinNul:= 0 else
BEGIN 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;END;
{************** MAIN***********}beginwriteln('Costruiamo un Albero. '); BuildNameTree(Albero); WriteAlbero(Albero); writeln('Ci sono ', ContaNodiSinNul(Albero),' nodi con sotto albero sinistro nullo');end.
ESERCIZIO{ Dato un albero binario calcolare quanti nodi hanno il sottoalbero sinistro nullo.}
ALBCONT2
Programmazione Mod. B - Alberi - prof. E. Burattini
88
{ 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);BEGINIF Not EmptyTree(Tree) THEN BEGIN
Crescente(NodesLeftTree(Tree)); write(' ',tree^.key);
Crescente(NodesRightTree(Tree));END;
END;PROCEDURE DeCrescente(Tree:BSTP);BEGINIF Not EmptyTree(Tree) THEN
BEGINDeCrescente(NodesRightTree(Tree));
write(' ',tree^.key);DeCrescente(NodesLeftTree(Tree));END;
END;
{************** 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
89
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
90
uses Alberi0;CONST NKey=-100;VAR
Albero: BSTP;Cont:integer;
PROCEDURE ContaNodiNul(Tree:BSTP; VAR Conta:integer);BEGINIF NOT EmptyTree(Tree) THEN
BEGINContaNodiNul(NodesLeftTree(Tree),Conta);ContaNodiNul(NodesRightTree(Tree),Conta);IF (Tree^.Right=NIL) AND (Tree^.key MOD 2 <>0) THEN Conta:=Conta+1;END;
END;
{************** MAIN***********}BEGINwriteln('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
91
ALBERO BILANCIATO CON M LIVELLI
Totale Nodi
N°NODI
1M2
02
12
1
1
0
21M
i
i
N°NODI
0
1
MM2
02
12
Totale Nodi
M
i
i
0
2
Programmazione Mod. B - Alberi - prof. E. Burattini
92
ESERCIZIO{ Dato un albero binario non bilanciato costruire un albero
bilanciato.}
Da Albero a Vettore
Bilanciamento
Stampa
Non bilanciatobilanciato
Controllo bilanciamento
Programmazione Mod. B - Alberi - prof. E. Burattini
93
Da Albero a Vettore
Bilanciamento
Stampa
Non bilanciato
bilanciato
Controllo bilanciamento
1
2
5
3
7
8
9
1
2
5
3 7
8
9
1 2 3 5 7 8 9
1 2 3 5 7 8 9
Programmazione Mod. B - Alberi - prof. E. Burattini
94
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;
BEGINnew(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
95
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);
{************** MAIN***********}BEGIN writeln('Costruiamo un Albero. '); BuildNameTree(Albero); IF not ControlloBilanciamento(Albero) THEN BEGIN Vmax:=0; DaAlberoAVettore(Albero,V,Vmax); Bilanciato:=Vet2ALb(V,1,Vmax); writeln(ControlloBilanciamento(Bilanciato)); END ELSE writeln(' FINE');END.
Programmazione Mod. B - Alberi - prof. E. Burattini
96
FUNCTION Bilancia(A:BSTP;VAR cmax,cmin:integer;livello:integer):integer;BEGINIF not EmptyTree(A) THENBEGINIF EmptyTree(NodesRightTree(A)) OR EmptyTree(NodesLeftTree(A)) THENBEGINIF cmax<livello THENcmax:=livello;IF cmin>livello THENcmin:=livello;END;bilancia:=bilancia(NodesRightTree(A),cmax,cmin,livello+1);bilancia:=bilancia(NodesleftTree(A),cmax,cmin,livello+1);END;Bilancia:=cmax-cminEND;
FUNCTION ControlloBilanciamento(A:BSTP):boolean;VAR cmx,cmn:integer;BEGINcmx:=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') END ELSE BEGIN ControlloBilanciamento:=FALSE;writeln(' L''albero non è bilanciato'); END;END;
Programmazione Mod. B - Alberi - prof. E. Burattini
97
PROCEDURE DaAlberoAVettore(A:BSTP;VAR V:vettore;VAR max:integer);VAR I:integer;BEGINIF NOT EmptyTree(A) THEN BEGIN DaAlberoAVettore(NodesLeftTree(A),V,max); Max:=max+1; V[max]:=Tree^.key; DaAlberoAVettore(NodesRightTree(A),V,max); END;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
98
FUNCTION vet2alb(vx:vettore;i,j:integer):BSTP;{a partire dal vettore V ordinato genero l'albero vet2alb}VARK:integer;BEGINIF I>J THEN
Vet2alb:=NILELSE
IF I=J THENVet2alb:=UnisciAlberi(Vx[I],NIL,NIL)
ELSEBEGIN K:=(I+J) DIV 2; Vet2alb:=UnisciAlberi(Vx[K],vet2alb(Vx,I,K-1),vet2alb(vx,K+1,j))END;
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(' FINE');end.
ALBBIL3
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;
Programmazione Mod. B - Alberi - prof. E. Burattini
99
UnisciAlberi(Vx[K],vet2alb(Vx,I,K-1),vet2alb(vx,K+1,j))
gfedcba
7654321
Vet2ALb(V,1,Vmax);
Vet2ALb(V,1,7); K=4
UnisciAlberi(Vx[4],vet2alb(Vx,1,3),vet2alb(vx, 5,7))
Vet2ALb(V,1,3); K=2
UnisciAlberi(Vx[2],vet2alb(Vx,1,1),vet2alb(vx, 3,3))
Vet2ALb(V,1,1); K=1 Vet2ALb(V,3,3); K=3a c
b
UnisciAlberi(Vx[4],vet2alb(Vx,1,3),vet2alb(vx, 6,7))
Vet2ALb(V,5,7); K=6
Vet2ALb(V,5,5); K=5 Vet2ALb(V,7,7); K=7e g
f
d
d
f
e gca
b
Programmazione Mod. B - Alberi - prof. E. Burattini
100
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
101
Esercizio .
Dato un albero determinare quanti nonni hanno un solo nipote.
Programmazione Mod. B - Alberi - prof. E. Burattini
102