Definamos una función split(T,v)
que toma en un árbol, T
y un valor de división en, v
. Suponga que cada nodo del árbol almacena su hijo izquierdo y su hijo derecho además del valor en ese nodo. Use el siguiente algoritmo:
Primero verificamos si el árbol de entrada es simplemente una hoja o no.
Si T
no es una hoja, compare el valor de su nodo raíz v'
con v
.
Si v' < v
entonces, recursivamente, llame a split en el subárbol izquierdo. Almacene los valores de la llamada recursiva como L'
(árbol izquierdo devuelto), R'
(árbol derecho devuelto) y r
(tipo de opción indicado si v
se encontró el valor o no). Construya el nuevo árbol derecho newR = Node(R',v',R)
, y regrese (L',r,newR)
.
De lo contrario, si v' > v
llama recursivamente split en el subárbol derecho. Almacene los valores de la llamada recursiva como L'
(árbol izquierdo devuelto), R'
(árbol derecho devuelto) y r
(tipo de opción indicado si v
se encontró el valor o no). Construya el nuevo árbol izquierdo newL = Node(L',v',L)
, y regrese (newL,r,R')
.
Si no v' = v
, regrese L, SOME(v), R
.
Si T
es una hoja, debemos haber alcanzado la raíz del árbol sin encontrar el valor de entrada v para dividir. Regrese que no pudo encontrar la hoja al pasar de regreso NONE
.
¿Por qué es esto logarítmico? Bueno, solo atraviesas un camino de raíz a hoja del árbol, como máximo. Podemos reconstruir fácilmente nodos en tiempo constante ya que solo estamos reasignando referencias (en un lenguaje imperativo) o reasignando valores que tardan un tiempo constante en generarse (en un lenguaje funcional )O(logn)O(logn)
Aquí está el código correspondiente para el algoritmo. Está escrito en SML, pero estaría dispuesto a aclarar qué significa algo en los comentarios.
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)
Vea este documento para más detalles. Proporciona una explicación más completa de lo anterior.