Cerchiamo di definire una funzione split(T,v)
che prende in un albero, T
e un valore di scissione a, v
. Supponiamo che ciascun nodo dell'albero memorizzi il suo figlio sinistro e il figlio destro oltre al valore su quel nodo. Utilizzare il seguente algoritmo:
Per prima cosa controlliamo se l'albero di input è semplicemente una foglia o no.
Se T
non è una foglia, confronta il valore del suo nodo radice v'
con v
.
Se v' < v
quindi chiama in modo ricorsivo la divisione sulla sottostruttura sinistra. Memorizzare i valori della chiamata ricorsiva come L'
(albero a sinistra restituito), R'
(albero a destra restituito) e r
(tipo di opzione indicato se il valore è v
stato trovato o meno). Costruisci il nuovo albero a destra newR = Node(R',v',R)
e torna indietro (L',r,newR)
.
Altrimenti, se v' > v
poi chiama in modo ricorsivo split sulla sottostruttura destra. Memorizzare i valori della chiamata ricorsiva come L'
(albero a sinistra restituito), R'
(albero a destra restituito) e r
(tipo di opzione indicato se il valore è v
stato trovato o meno). Costruisci il nuovo albero a sinistra newL = Node(L',v',L)
e torna indietro (newL,r,R')
.
Altrimenti se v' = v
, ritorna L, SOME(v), R
.
Se T
è una foglia, dobbiamo aver raggiunto la radice dell'albero senza trovare il valore di input v a cui dividere. Ritorna che non sei riuscito a trovare la foglia tornando indietro NONE
.
Perché questo logaritmico? Bene, attraversi sempre e solo un percorso radice-foglia dell'albero, al massimo. Possiamo ricostruire facilmente nodi in tempo costante poiché stiamo semplicemente riassegnando riferimenti (in un linguaggio imperativo) o riassegnando valori che richiedono un tempo costante per generare (in un linguaggio funzionale ).O ( logn )O ( logn )
Ecco il codice corrispondente per l'algoritmo. È scritto in SML, ma sarei disposto a chiarire cosa significhi qualcosa nei commenti.
fun split(T,v) =
case T of
Leaf => (Leaf, NONE, Leaf)
| Node(L,v,R) =>
case compare(v, v') of
LESS =>
let
val (L',r,R') = split(L,k)
in
(L',r,Node(R',r,R))
end
| GREATER =>
let
val (L',r,R') = split(R,k)
in
(Node(L',v',L),r,R')
end
| EQUAL => (L, SOME(v), R)
Vedi questo documento per maggiori dettagli. Fornisce una spiegazione più approfondita di quanto sopra.