interrogazioni su un albero binario di ricerca search(s,k) – dato un insieme s ed un valore chiave...
TRANSCRIPT
![Page 1: Interrogazioni su un albero binario di ricerca Search(S,k) – dato un insieme S ed un valore chiave k restituisce un puntatore x ad un elemento in S tale](https://reader038.vdocuments.net/reader038/viewer/2022100420/5542eb50497959361e8bfbb9/html5/thumbnails/1.jpg)
Interrogazioni su un albero binario di ricerca
Search(S,k) – dato un insieme S ed un valore chiave k restituisce un puntatore x ad un elemento in S tale che key[x] = k
Maximum(S) – dato un insieme S su cui è definita una relazione d’ordine totale, restituisce il puntatore all’elemento di S con chiave più grande
Minimum(S) – dato un insieme S su cui è definita una relazione d’ordine totale, restituisce l’elemento di S con chiave più piccola
Successor(S,x) – dato un insieme S su cui è definita una relazione d’ordine totale, e dato un puntatore x ad un elemento di S, restituisce il successivo elemento più grande in S (o NIL se x punta all’elemento massimo di S).
Predecessor(S,x) - dato un insieme S su cui è definita una relazione d’ordine totale, e dato un puntatore x ad un elemento di S, restituisce il successivo elemento più piccolo in S (o NIL se x punta all’elemento minimo di S).
Interrogazioni – Operazioni che restituiscono informazioni su un insieme dinamico S. Non modificano l’insieme.
![Page 2: Interrogazioni su un albero binario di ricerca Search(S,k) – dato un insieme S ed un valore chiave k restituisce un puntatore x ad un elemento in S tale](https://reader038.vdocuments.net/reader038/viewer/2022100420/5542eb50497959361e8bfbb9/html5/thumbnails/2.jpg)
Ricerca in un ABR
Tree-search(x,k)If (x=NIL) o (k = key[x]) then return xIf (k < key[x]) then Tree-Search(left[x],k) else Tree-Search(right[x],k)
Iterative-Tree-search(x,k)While (xNIL) e (k key[x]) do if k < key[x]
then x left[x] else x right[x]Return x
Qual è la complessità dell’operazione di ricerca in un ABR ?
T(n) = O(h) h = Altezza dell’albero
![Page 3: Interrogazioni su un albero binario di ricerca Search(S,k) – dato un insieme S ed un valore chiave k restituisce un puntatore x ad un elemento in S tale](https://reader038.vdocuments.net/reader038/viewer/2022100420/5542eb50497959361e8bfbb9/html5/thumbnails/3.jpg)
Confronto con il metodo dei dimezzamenti successivi
15
6 20
3 8 17 27
2 4 137 16 19 3022
2 3 4 6 7 8 13 15 16 17 19 20 22 27 30
Ipotizziamo che l’ albero sia completo –Supponiamo di eseguire Tree-search(root(T),7).
Supponiamo di avere implementato il dizionario con un array A ordinato. Eseguiamo ricercaBinariaIter(A,7)
Per le proprietà dell’ABR, se l’ABR fosse completo, allora la chiave di un nodo v sarebbe l’elemento mediano nell’insieme ordinato delle chiavi associate all’insieme di nodi costituiti dal sottoalbero sinistro di v, da v, e dal sottoalbero destro di v
Ad ogni discesa di livello, dimezzerei lo spazio di ricerca!
![Page 4: Interrogazioni su un albero binario di ricerca Search(S,k) – dato un insieme S ed un valore chiave k restituisce un puntatore x ad un elemento in S tale](https://reader038.vdocuments.net/reader038/viewer/2022100420/5542eb50497959361e8bfbb9/html5/thumbnails/4.jpg)
Notare …
Non è detto che un ABR sia completo. Dipende da come lo abbiamo costruito. Ad esempio, i seguenti 2 ABR rappresentano lo stesso insieme di elementi:
15
6 20
3 8 17 27
2 4 137 16 19 3022
15
20
17
27
16
19
30
22
...
Ma anche questo è un ABR
Notare: Tsearch(n) = O(h) in entrambi i casi
Però:
ABR completo h = (log(n))ABR “linearizzato” h = (n)2
![Page 5: Interrogazioni su un albero binario di ricerca Search(S,k) – dato un insieme S ed un valore chiave k restituisce un puntatore x ad un elemento in S tale](https://reader038.vdocuments.net/reader038/viewer/2022100420/5542eb50497959361e8bfbb9/html5/thumbnails/5.jpg)
Minimo e Massimo
Tree-minimum(x) while (left[x] NIL) do x left[x]Return[x]
Tree-maximum(x) while (right[x] NIL) do x right[x]Return[x]
Complessità - T(n) = O(h) h = altezza dell’albero
15
6 18
3 8 17 20
2 4 13
9
7
Tree-minimum(root(T))
Tree-maximum(x)
![Page 6: Interrogazioni su un albero binario di ricerca Search(S,k) – dato un insieme S ed un valore chiave k restituisce un puntatore x ad un elemento in S tale](https://reader038.vdocuments.net/reader038/viewer/2022100420/5542eb50497959361e8bfbb9/html5/thumbnails/6.jpg)
Successore e predecessore
Tree-successor(x)If (right[x] NIL) then return Tree-Minimum(right[x])y p[x]While (y NIL) e (x=right[y]) do x y y p[y]Return y
15
6 18
3 8 17 20
2 4 13
9
7
Cerco il min dell’ABR con root=right[x]
Cerco l’antenato più prossimo di x il cui figlio sinistro è la radice del sottoalbero che contiene x
Complessità T(n) = O(h)
Tree-predecessor(x) è perfettamente simmetrica
![Page 7: Interrogazioni su un albero binario di ricerca Search(S,k) – dato un insieme S ed un valore chiave k restituisce un puntatore x ad un elemento in S tale](https://reader038.vdocuments.net/reader038/viewer/2022100420/5542eb50497959361e8bfbb9/html5/thumbnails/7.jpg)
In conclusione:
Le operazioni di interrogazione Search, Minimum, Maximum, Successor e Predecessor possono essere eseguite in un albero binario di ricerca di altezza h in un tempo O(h).
![Page 8: Interrogazioni su un albero binario di ricerca Search(S,k) – dato un insieme S ed un valore chiave k restituisce un puntatore x ad un elemento in S tale](https://reader038.vdocuments.net/reader038/viewer/2022100420/5542eb50497959361e8bfbb9/html5/thumbnails/8.jpg)
Operazioni di modifica su un albero binario di ricerca
Insert(S,z) – inserisce in S l’elemento puntato da z
Delete(S,k) - rimuove da S l’oggetto con chiave k
Per semplicità, dirò “nodo” o “elemento” intendendo “puntatore al nodo” e “puntatore all’elemento”, rispettivamente.
Operazioni di modifica – operazioni su un insieme dinamico S che modificano le proprietà dell’insieme.
![Page 9: Interrogazioni su un albero binario di ricerca Search(S,k) – dato un insieme S ed un valore chiave k restituisce un puntatore x ad un elemento in S tale](https://reader038.vdocuments.net/reader038/viewer/2022100420/5542eb50497959361e8bfbb9/html5/thumbnails/9.jpg)
Inserimento
Possiamo sempre inserire un nuovo elemento z come foglia.
Per decidere la posizione del nuovo elemento possiamo usare la seguente strategia:
- discendiamo tutto l’albero, partendo dalla radice. In corrispondenza di ogni nodo x, andiamo a sinistra se key[z] < key[x], andiamo a destra altrimenti.
15
6 18
3 9 17 20
2 4 13
10
7
Supponiamo di voler inserire un nodo i cui campi sono inizializzati a:Key[z] = 8p[z] = NILLeft[z] = NILRight[z] = NIL
Se seguo questo schema l’elemento z viene posizionato nellaposizione giusta. Infatti, per costruzione, ogni antenato di z si ritrova z nel giusto sottoalbero.
8
![Page 10: Interrogazioni su un albero binario di ricerca Search(S,k) – dato un insieme S ed un valore chiave k restituisce un puntatore x ad un elemento in S tale](https://reader038.vdocuments.net/reader038/viewer/2022100420/5542eb50497959361e8bfbb9/html5/thumbnails/10.jpg)
Tree-insert(T,z)y NILx root[T]While (xNIL) do y x if (key[z] < key[x])
then x left[x] else x right[x]
p[z] yIf (y NIL) then if (key[z] < key[y]) then left[y] z else right[y] z else root[T] z
Inserimento
Cerchiamo la posizione giusta per una foglia con chiave pari a key[z].y punterà al padre di z
Aggiorniamo i puntatori del nodo y
Se y=NIL, l’albero contiene solo il nodo z. Il nodo z è allora la radice dell’albero. Non è necessario aggiornare I puntatori left[z] e right[z]
Aggiorniamo il puntatore p[z]
Complessità T(n) = O(h) h = altezza dell’ABR
N.B. Operazioni di inserimento successive possono “linearizzare” l’albero.
![Page 11: Interrogazioni su un albero binario di ricerca Search(S,k) – dato un insieme S ed un valore chiave k restituisce un puntatore x ad un elemento in S tale](https://reader038.vdocuments.net/reader038/viewer/2022100420/5542eb50497959361e8bfbb9/html5/thumbnails/11.jpg)
Cancellazione
Sia z (se esiste) il nodo con chiave k. Ci sono 3 situazioni possibili:
1) Cancellazione di un nodo z privo di figli - Modifichiamo il padre di z (p[z]) in modo che non
punti più a z
2) Cancellazione di un nodo z con un unico figlio - Estraiamo il nodo z creando un collegamento tra il
padre di z (p[z]) ed il figlio di z
3) Cancellazione di un nodo z avente due figli. Estraiamo il successore y di z e sostituiamo il
contenuto di z con il contenuto di y
15
6 18
3 9 17 20
2 4 13
10
7
1 2
3
5
![Page 12: Interrogazioni su un albero binario di ricerca Search(S,k) – dato un insieme S ed un valore chiave k restituisce un puntatore x ad un elemento in S tale](https://reader038.vdocuments.net/reader038/viewer/2022100420/5542eb50497959361e8bfbb9/html5/thumbnails/12.jpg)
15
6 18
3 9 17 20
2 4 13
10
7
1 2
Cancellazione
Tree-Delete(T,k)z=Tree-search(root[T],k)If (z NIL) then If (left[z]=NIL) o (right[z]=NIL) then y z else y Tree-Successor(z) If (left[y] NIL) then x left[y] else x right[y] If (x NIL) then p[x] p[y] If (p[y] = NIL) then root[T] x else if (y = left[p[y]]) then left[p[y]] x else right[p[y]] x If (yz) then key[z] key[y]
3
5
![Page 13: Interrogazioni su un albero binario di ricerca Search(S,k) – dato un insieme S ed un valore chiave k restituisce un puntatore x ad un elemento in S tale](https://reader038.vdocuments.net/reader038/viewer/2022100420/5542eb50497959361e8bfbb9/html5/thumbnails/13.jpg)
Nodo senza figli
15
6 18
3 9 17 20
2 4 13
10
7
Tree-Delete(T,k)z=Tree-search(root[T],k)If (z NIL) then If (left[z]=NIL) o (right[z]=NIL) then y z else y Tree-Successor(z) If (left[y] NIL) then x left[y] else x right[y] cioè x=NIL If (x NIL) then p[x] p[y] If (p[y] = NIL) Se il nodo z era la radice, allora then root[T] x root[T] = NIL else if (y = left[p[y]]) altrimenti then left[p[y]] x sostituisce il puntatore a z con NIL else right[p[y]] x If (yz) then key[z] key[y]
5NIL
T(n) = O(h)
![Page 14: Interrogazioni su un albero binario di ricerca Search(S,k) – dato un insieme S ed un valore chiave k restituisce un puntatore x ad un elemento in S tale](https://reader038.vdocuments.net/reader038/viewer/2022100420/5542eb50497959361e8bfbb9/html5/thumbnails/14.jpg)
Nodo con un figlio
15
6 18
3 9 17 20
2 4 13
10
7
Tree-Delete(T,k)z=Tree-search(root[T],k)If (z NIL) then If (left[z]=NIL) o (right[z]=NIL) then y z else y Tree-Successor(z) If (left[y] NIL) then x left[y] x = puntatore all’unico figlio di z else x right[y] If (x NIL) then p[x] p[y] p[x] = puntatore al padre di z If (p[y] = NIL) se z era la radice then root[T] x la nuova radice è il figlio di z else if (y = left[p[y]]) altrimenti then left[p[y]] x crea connessione tra il padre di z else right[p[y]] x ed il figlio di z If (yz) then key[z] key[y]
5
T(n) = O(h)
![Page 15: Interrogazioni su un albero binario di ricerca Search(S,k) – dato un insieme S ed un valore chiave k restituisce un puntatore x ad un elemento in S tale](https://reader038.vdocuments.net/reader038/viewer/2022100420/5542eb50497959361e8bfbb9/html5/thumbnails/15.jpg)
Nodo con due figli
15
6 18
3 9 17 20
2 4 13
10
7
Tree-Delete(T,k)z=Tree-search(root[T],k)If (z NIL) then If (left[z]=NIL) o (right[z]=NIL) then y z else y Tree-Successor(z) y = successore di z If (left[y] NIL) then x left[y] else x right[y] x = figlio destro del succes. di z If (x NIL) N.B. – il figlio ds di y potrebbe non esistere then p[x] p[y] il padre di x diventa il padre di y (cancello y) If (p[y] = NIL) N.B. il padre di y non può mai essere NIL then root[T] x else if (y = left[p[y]]) il padre di y deve puntare al nuovo figlio x then left[p[y]] x else right[p[y]] x If (yz) then key[z] key[y] sostituisce la chiave di z con la chiave di y
5
Success. di z
z
y
xT(n) = O(h)
4
![Page 16: Interrogazioni su un albero binario di ricerca Search(S,k) – dato un insieme S ed un valore chiave k restituisce un puntatore x ad un elemento in S tale](https://reader038.vdocuments.net/reader038/viewer/2022100420/5542eb50497959361e8bfbb9/html5/thumbnails/16.jpg)
In conclusione:
Le operazioni di inserimento e di cancellazione di un nodo in un ABR hanno tempo di esecuzione T(n) = O(h) dove h è l’altezza dell’albero.