2.b. Árbol Binario de Búsqueda
2.b. Árbol Binario de Búsqueda
2.b. Árbol Binario de Búsqueda
Contenido
Árbol binario de búsqueda
Contenido
Introducción
Definición
Interfaz IArbolBinarioBusqueda
Implementación
Eficiencia de los ABB
El peor caso
El mejor caso
El caso promedio
Introducción
Una actividad común en todos los sistemas de cómputo es el mantenimiento de un conjunto de
datos, sobre el cual deseamos hacer las siguientes operaciones:
1. Insertar un elemento.
2. Eliminar un elemento.
3. Buscar un elemento.
Otro ejemplo es la lista de alumnos inscritos en un curso, en donde servicios escolares puede
inscribir o dar de baja alumnos y en donde podemos buscar si un alumno está inscrito en un
curso en específico.
1
El contenido de estas notas está basado principalmente en: A. V. Aho y J. Ullman. Foundations of
Computer Science. W.H. Freeman and Company, 1992.
Una forma más eficiente de representar un diccionario es mediante un árbol binario de
búsqueda (ABB), que es un árbol binario con cumple con ciertas propiedades.
Definición
La propiedad que hace a un árbol binario un ABB es que, para cada nodo n en el árbol, la
información almacenada en todos los nodos del subárbol izquierdo de n es menor a la
información almacenada en n y la información que guardan todos los nodos del subárbol
derecho de n es mayor que la de n. La Figura 1 muestra algunos ejemplos de esta propiedad.
Veamos el siguiente ejemplo: ¿Cómo saber si un árbol es un ABB? Para saberlo, tenemos que
asegurarnos que todos los nodos del subárbol izquierdo de la raíz contienen información que
es menor a la almacenada en la raíz y que todos los nodos del subárbol derecho contienen
información que es mayor. Además, los subárboles izquierdo y derecho de la raíz son ABB. Los
siguientes son los métodos que se podrían utilizar para implementar esta operación.
Ejercicio. Proporciona un ABB para los siguientes tenistas: Djokovic, Murray, Federer, Nadal,
Ferrer, Berdych, Del Potro, Tsonga.
Una vez construido el ABB, ¿en dónde se ubicaría a Gasquet? ¿Y, después, en dónde a
Wawrinka?
Interfaz IArbolBinarioBusqueda
Un ABB, por ser un árbol, hereda las operaciones sobre árboles, además de definir algunas
otras que son propias del ABB, las cuales consideran a x de tipo Object.
El método buscar tiene que considerar los siguientes casos. Si el árbol está vacío, entonces x
no existe en el árbol y se devuelve None. Si el árbol no está vacío y x está en la raíz, entonces
se devuelve el nodo raíz. Si x no está en la raíz, sea y la información en la raíz. Si, mediante
algún orden lineal x < y, entonces se busca a x en el subárbol izquierdo de la raíz. Si x > y,
buscaremos a x en el subárbol derecho de la raíz. La propiedad del ABB garantiza que x no
puede existir en el subárbol que no se está considerando.
Para eliminar un nodo de un ABB podemos considerar tres casos. El primero y más sencillo es
cuando el nodo es una hoja. En este caso, simplemente se elimina el nodo y se devuelve
True. Los otros dos casos suceden cuando el nodo que se desea eliminar es un nodo interno.
En estos casos no podemos simplemente eliminar el nodo porque el ABB podría quedar
desconectado. Entonces debemos modificar el árbol de tal forma que se mantenga la
propiedad del ABB. El segundo caso es cuando el nodo que se requiere eliminar sólo tiene un
hijo. Lo que tenemos que hacer entonces es asignar como hijo del padre del nodo eliminado, al
hijo del nodo eliminado, como se muestra en la Figura 2(a), en donde las líneas discontinuas
representan la conexión original de los nodos, antes de eliminar al nodo que contiene 8.
El tercer caso es cuando el nodo n que se quiere eliminar tiene a sus dos hijos, como el que se
muestra en la Figura 2(b). Una estrategia es encontrar al nodo que contiene la información
mínima y dentro del subárbol derecho de n y moverlo al lugar del nodo n. En este caso, la
propiedad del ABB se sigue manteniendo porque x es mayor a toda la información del subárbol
izquierdo y, dado que x < y, y también será mayor. En el ejemplo que se muestra en la Figura
2(c), el nodo que contenía a 8 fue eliminado y reemplazado por el nodo que contiene a 9, la
información mínima del subárbol derecho del nodo eliminado.
Implementación
La implementación de la clase ArbolBinarioBusqueda es mediante la extensión de la clase
Arbol, más la implementación de los métodos de la interfaz IArbolBinarioBusqueda.
Esto se vería más o menos de la siguiente forma.
class ArbolBinarioBusqueda:
...
return n
El peor caso
Supongamos que tenemos una lista ordenada de elementos 1, 2, …, k-1, k y queremos
crear un ABB a partir de esta lista. El resultado será un árbol como el que se muestra en la
Figura 3. Claramente podemos ver que la altura de este árbol es k-1. Entonces, podríamos
esperar que las operaciones buscar, insertar y eliminar se ejecuten en a lo más k-1
llamadas recursivas.
El mejor caso
Por otro lado, consideremos un ABB en donde cada nodo interior tiene ambos hijos, es decir,
un ABB perfecto. Ya hemos visto que un árbol de este tipo con k = 2h+1-1, tiene una altura a
≈ log2 k. En este caso, el número de llamadas recursivas será, a lo más, log2 k.
El caso promedio
¿Cuál de los dos casos anteriores es el caso promedio? En realidad, ninguno de los dos casos
es común en la práctica, pero el árbol completo se acerca a la eficiencia de un caso promedio.
No haremos una comprobación rigurosa, sino que haremos un análisis intuitivo. La raíz de un
árbol divide al resto de los nodos en dos subárboles. La división más pareja de un árbol con k
nodos tendrá dos subárboles de aproximadamente k/2 nodos cada uno. Este caso ocurre si la
raíz es el elemento que se encuentra exactamente a la mitad de la lista ordenada de los
elementos. La división más dispareja sucede cuando la raíz es el primero o el último de los
elementos y en este caso sólo tendrá un subárbol con k-1 nodos.
En un caso promedio, esperaríamos que la raíz sea uno de los elementos entre el de enmedio
y uno de los extremos y podríamos esperar que, en promedio, k/4 nodos vayan de un lado del
árbol y 3k/4 nodos del otro. Consideremos que cuando nos movemos dentro del árbol,
siempre lo hacemos hacia el subárbol más grande y encontramos la misma distribución de
nodos. Entonces, en el primer nivel encontramos 3k/4 nodos, en el segundo (3/4)(3k/4)
nodos y así sucesivamente. De esta forma, en el h-ésimo nivel encontramos (3/4)h k nodos.
Lo que quiere decir que a una profundidad de 2.5 veces el logaritmo del número de nodos,
esperamos ver sólo hojas. Este argumento justifica, pero no comprueba, que un ABB típico
tiene una altura que es proporcional al logaritmo del número de nodos contenido en el árbol.