Está en la página 1de 32

Árboles de búsqueda /

Conjuntos ordenados Pt.1


Iván Yesid Castellanos
Motivación
 Una de las operaciones mas importantes en las estructuras de datos
consiste en la búsqueda elementos específicos
 Ejemplo: buscar si un estudiante existe en la base de datos de la cafetería de la
universidad para darle el descuento del almuerzo
 Si nuestra estructura la manejamos como una lista cualquiera tendríamos
que recorrerla toda para hacer la búsqueda (inserción O(1), consulta
O(N))
 Otra opción para manejar esta situación sería mantener una lista
ordenada, es decir, insertar los elementos de forma que la lista siempre
esté ordenada y por cada consulta realizar una búsqueda binaria
(consulta O(log N), inserción O(N))
 Si además queremos eliminar elementos en nuestra estructura sea que se
implemente con arreglos o con apuntadores tenemos una complejidad de
O(N)
Árbol de búsqueda binario
 También hay forma de implementar la estructura anterior utilizando árboles, en este
caso se usarán árboles de búsqueda binarios (BST - Binary Search Tree)
 Un BST es un árbol binario con la propiedad de que para cada nodo todos los
elementos del subárbol del hijo izquierdo (del nodo) son menores al elemento en el
nodo y todos los elementos del subárbol del hijo derecho (del nodo) son mayores al
elemento en el nodo
Conjunto ordenado

 En un árbol de búsqueda binario estándar todos los elementos insertados


son diferentes, pues de haber varios iguales no tendría sentido la
operación principal que es la de búsqueda
 Esto motiva el uso de arboles de búsqueda binarios para representar
conjuntos (pues en un conjunto solo hay una aparición por elemento)
 Esto se ha de tener en cuenta para considerar que al insertar no se puede
insertar un elemento igual a otro que ya esté (igual desde el punto de vista
de la comparación)
 De igual forma sabremos que al consultar un elemento este es único
dentro de ese conjunto
TDA conjunto ordenado

 Instancias: un conjunto de elementos comparables


 Operaciones:
 EsVacio(): retorna true si el conjunto está vacío
 Buscar(x): busca si algún elemento del conjunto coincide con x y retorna la
referencia de ese elemento en la colección o null en caso de que no esté en el
conjunto
 Consultar(x): retorna true si x está en el conjunto, false en otro caso
 Eliminar(x): retorna true si el elemento x está en el conjunto y además lo elimina
de este, en caso de que x no esté en el conjunto retorna false
 Insertar(x): inserta el elemento x en el conjunto
Definición BinarySearchTree
Constructor, EsVacio
Insertar

 Se utilizará la propiedad de orden en el árbol para insertar el elemento en


el lugar que le debería corresponder en el árbol, para esto vamos a
realizar un procedimiento recursivo
 Si estamos en un nodo y el elemento que queremos insertar es menor al
elemento en el nodo entonces inserto el elemento en el subárbol del hijo
izquierdo del nodo
 Si estamos en un nodo y el elemento que queremos insertar es mayor al
elemento en el nodo entonces inserto el elemento en el subárbol del hijo
derecho del nodo
 Si estamos en un nodo y el elemento que queremos insertar es igual al
elemento en el nodo entonces no hacemos nada
 Complejidad O(h), donde h es la altura del árbol
Ejemplo Insertar
 Insertar 20, 43, 16, 18, 35, 48, 45, 6 (en ese orden)
Insert, auxInsert
Buscar / Consultar

 Para buscar o consultar la existencia de un elemento en el conjunto


utilizamos fuertemente la propiedad del ordenamiento
 Iniciamos explorando desde la raíz
 Si el elemento está en el nodo que estemos explorando entonces
terminamos, en caso contrario, si es menor al que estamos explorando nos
vamos al subárbol izquierdo y si es mayor nos vamos al árbol izquierdo
 Realizamos esto hasta encontrar el elemento o hasta llegar a alguna hoja
sin haberlo encontrado
 Complejidad O(h), donde h es la altura del árbol
Ejemplo Buscar / Consultar
Buscar(19) Buscar(48)
Search, contains
Encontrar Mínimo, Máximo

 Para encontrar el elemento mínimo del árbol basta con ir al descendiente


mas izquierdo posible, es decir, voy recorriendo por la izquierda hasta no
tener mas hijos izquierdos
 En caso de que el árbol sea vacío retorna null
 Nótese que esto también funciona para encontrar el mínimo de cualquier
subárbol del árbol, dado que cada subárbol de un BST es un BST
 La misma idea funciona para encontrar el máximo del árbol, pero
haciendo el recorrido a la derecha
 Complejidad O(h), h es la altura del arbol
Ejemplo Encontrar Mínimo
FindMin
Eliminar

 Para eliminar un elemento del árbol consideraremos 3 posibles


casos:
 El elemento está en una hoja: en este caso es sencillo eliminar pues
solamente hacemos que la referencia al nodo se vuelva nula
 El elemento está en un nodo con un hijo: este caso también es sencillo,
pues hacemos que la referencia a este nodo sea la referencia al hijo
 El elemento está en un nodo con 2 hijos: En este caso reemplazaremos
al elemento con el supremo (el mínimo de los mayores) o el infímo (el
máximo de los menores) del elemento y eliminamos luego ese nodo
 Ese nodo o bien será hoja o tendrá un único hijo (la demostración de este
hecho queda como tarea del estudiante), por lo que entra en los 2 primeros
casos de eliminación

 Complejidad O(h), donde h es la altura del árbol


Ejemplo Eliminar caso 1 y 2

 Eliminar(2)

 Eliminar(45)
Ejemplo Eliminar caso 3
 Eliminar 20
Remove
Altura

 También puede ser de nuestro interés (como desarrolladores) conocer la


altura del árbol, dado que las complejidades está en orden de esta
cantidad
 De igual forma que con el encontrar mínimo o máximo podemos calcular
altura de subárboles del árbol original, utilizaremos polimorfismo para esto
 De forma recursiva podemos calcular la altura de un árbol con el máximo
de las alturas de los subárboles de los hijos izquierdo y derecho
 La altura de un árbol vacío es 0
 Complejidad O(N), donde N es la cantidad de elementos en el arbol
Height
test BinarySearchTree
test BinarySearchTree
test BinarySearchTree
test BinarySearchTree
Test BinarySearchTree
Test BinarySearchTree
Árboles de búsqueda generales

 En general la noción de árboles de búsqueda binarios se puede extender


a árboles de búsqueda n-arios, donde los hijos representan un orden
lexicográfico de los elementos
 Para cada nodo cuyos hijos son a1, a2,…, ak entonces todos los elementos
del subárbol a1 son menores a todos los elementos del subárbol a2, los
cuales son menores a todos los del árbol a3 y así sucesivamente, los
elementos del subárbol ak son mayores a los de los demás subárboles
 Existen varias estructuras especializadas que manejan este tipo de árboles
para almacenamiento de datos y realizar búsquedas eficientes
Estructuras Avanzadas basadas en
árboles de búsqueda

 Árbol de sufijos (Suffix


Tree): Es un árbol que
contiene todos los sufijos
de un texto, tener este
árbol puede ayudar a
resolver problemas como
el de Longest Common
Substring de forma
eficiente o el Longest
Palindrome, de igual
forma tiene aplicaciones
en bioinformática y en
búsqueda de patrones
de texto
Estructuras Avanzadas basadas en
árboles de búsqueda

 Árbol de prefijos (Prefix


Tree) / Trie: Es un árbol que
contiene varias palabras,
pero la búsqueda se da a
partir re prefijos, y los nodos
se construyen con las letras
de las palabras, es muy
eficiente para predicción
de texto, y para almacenar
bases de datos de palabras
(como el diccionario de las
palabras en español o en
inglés)
Estructuras Avanzadas basadas en
árboles de búsqueda

 Radix Tree: Es un Trie


optimizado, en el cual se
comprimen nodos con
un único hijo y así utilizar
menos memoria y
decrementar la altura
del árbol, funciona igual
que el Trie, pero se debe
tener cuidado con el
manejo de estos nodos
‘comprimidos’ en la
implementación,
recomendado cuando
la memoria sea limitada

También podría gustarte