Está en la página 1de 15

Metodos de B usqueda

Notas de Clase
Prof. Juan Andres Colmenares, M.Sc.
Instituto de Calculo Aplicado
Facultad de Ingeniera
Universidad del Zulia
19 de mayo de 2004

Indice
1. Introduccion 2
2. Metodos Elementales de B usqueda 2
2.1. B usqueda Secuencial . . . . . . . . . . . . . . . . . . . . . . . 2
2.2. B usqueda Binaria . . . . . . . . . . . . . . . . . . . . . . . . . 3
2.3. B usqueda por Interpolacion . . . . . . . . . . . . . . . . . . . 6
3. B usqueda por

Arbol Binario 7
3.1. Operaciones Basicas . . . . . . . . . . . . . . . . . . . . . . . 8
3.1.1. Buscar . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
3.1.2. Insertar . . . . . . . . . . . . . . . . . . . . . . . . . . 8
3.1.3. Ordenar . . . . . . . . . . . . . . . . . . . . . . . . . . 9
3.1.4. Remover . . . . . . . . . . . . . . . . . . . . . . . . . . 9
3.1.5. Manejo de Duplicados . . . . . . . . . . . . . . . . . . 10
4. Dispersion (Hashing) 10
4.1. Funcion de Dispersion (Hash Function) . . . . . . . . . . . . 10
4.2. Resolviendo Colisiones . . . . . . . . . . . . . . . . . . . . . . 12
4.2.1. Encadenamiento Separado (Separate Chaining) . . . . 13
4.2.2. Direccionamiento Abierto (Open Addressing) . . . . . 14
4.3. Factor de Carga y Rehashing . . . . . . . . . . . . . . . . . . 15
1
1. Introduccion
Los algoritmos de b usqueda permiten recuperar uno o varios elementos
particulares de un gran volumen de informacion previamente almacenada
(e.g., buscar un elemento contenido en una lista). La informacion tpicamente
esta almacenada en registros que contienen una clave y la data. El objetivo
de la operacion de b usqueda es encontrar todos los registros cuya claves
coincidan con una cierta clave especicada con el proposito de acceder a la
informacion (no solo a la clave ) para su procesamiento.
Algunos terminos comunes para describir las estructuras de datos rela-
cionadas con las operaciones de b usqueda son: i) diccionarios y ii) tablas de
smbolos.
En esta unidad estudiaremos metodos de b usqueda elementales y avan-
zados. Como ocurre regulamente, es preferible considerar que los algoritmos
de b usqueda pertenecen a conjunto de rutinas empaquetadas que realizan
una serie de rutinas genericas, que se pueden disociar de las implementa-
ciones particulares, de forma tal de facilitar el pase de una implementacion a
otra. En consecuencia, se dene un tipo de dato abstracto cuyas operaciones
principales son:
buscar
inicializar
incertar un nuevo registro
eliminar un registro
ordenar (dar como salida todos los registros ordenados)
unir 2 diccionarios en uno solo (de mayor tama no)
2. Metodos Elementales de B usqueda
2.1. B usqueda Secuencial
Es un metodo sumamente simple que resulta util cuando se tiene un con-
junto de datos peque no (hasta aproximadamente 500 elementos). Consiste
en:
1. almacenar todos los registros en un arreglo o lista,
2. insertar cada registro al nal del arreglo o lista, y
2
3. recorrer o iterar sobre el arreglo o lista hasta conseguir el elemento
requerido.
Propiedad 1
La b usqueda secuencial (implementadas empleando arreglos) siempre
utiliza N comparaciones para una b usqueda sin exito y alrededor N/2 com-
paraciones (en termino medio) para una b usqueda con exito.
Lo primero es obvio. Por otra parte, si suponemos que todos los reg-
istros tienen la misma probabilidad de ser buscados, el n umero medio de
comparaciones para una b usqueda exitosa es:
1 + 2 + 3 + +N
N
=
N + 1
2
Propiedad 2
Es facil adaptar la b usqueda secuencial para que utilice una lista enlazada
ordenada, lo que hace la b usqueda mas ecaz. Es facil mantener el orden
insertando cada registro en el lugar donde termina una b usqueda sin exito
y cada b usqueda termina cuando se encuentra un registro con una clave no
menor que la clave de b usqueda.
En este caso, la b usqueda secuencial (en una implementacion basada en
lista ordenada) utiliza alrededor de N/2 comparaciones (por termino medio)
para las b usquedas exitosas o no.
Por otra parte, se puede usar tambien listas desordenadas cuando se re-
quiere varias inserciones (en tiempo constante) y b usquedas poco frecuente.
Tambien, si se conoce la frecuencia de acceso de diferentes registros se pueden
obtener mejoras relativas signicativas ordenando los inteligentemente los
de acceso mas frecuente al principios. En caso contrario, se puede utilizar la
b usqueda autoorganizada: cada vez que se accede a un registro se le coloca
al principio.
2.2. B usqueda Binaria
Si el conjunto de registro es grande, el tiempo de b usqueda se puede
reducir utilizando el siguiete algortimo de tipo divide y veceras:
1. se divide el registro en 2 partes
2. se determina la parte debe contener la clave buscada
3. se repite el proceso en esa parte
3
Una forma razonable de dividir el conjunto de registro es mantener los
registros ordenados y despues utilizar los ndices del arreglo ordenado para
determinar la parte del arreglo sobre la que se va a trabajar. A continuacion
se presenta una implementacion en Java del metodo de b usqueda binaria:
/**
* A simple implementation of binary search.
* @param a array of comparable elements.
* @param key search key.
* @return index of the element found; -1 if it is not found.
*/
public static int binarySearch(Comparable[] a, Comparable key)
{
if (a == null || key == null){
throw new
NullPointerException("a == null || key == null");
}
if (a.length == 0){
return -1;
}
int izq = 0, der = a.length - 1;
int x = 0;
while (der >= izq){
// x = (izq + der)/2;
x = (izq + der) >> 1;
if (a[x].compareTo(key) == 0){
return x;
}
if (a[x].compareTo(key) > 0){
der = x - 1;
}
else{
izq = x + 1;
}
}
4
return -1;
}
La Figura 1 muestra un ejemplo de b usqueda binaria.
Figura 1: Ilustracion de la b usqueda binaria.
Propiedad 3
La b usqueda binaria nunca utiliza mas de lgN + 1 comparaciones para
cada b usqueda (con exito o sin el).
Notese que el tama no del arreglo se reduce a la mitad en cada paso,
enotonces el n umero de comparaciones satisface la formula de recurrencia
C
N
= C
N/2
+ 1 con C
1
= 1.
Sin perder generalidad, supongamos que N = 2
n
, entonces:
5
C
2
n = C
2
n1 + 1
= C
2
n2 + 1 + 1
= C
2
n3 + 1 + 1 + 1

= C
2
0 +n
= 1 +n
C
2
n = lg(N) + 1
(1)
Es claro que el tiempo de insercion de un elemento en el arreglo em-
pleado para busqueda binaria es elevado ya que dicho este debe mantenerse
ordenado. Por ello no debe utilizarse en aplicaciones que involucren muchas
inserciones. Por otra parte, es la mejor eleccion en situaciones en que el
arreglo puede construirse una vez al principio (por ejemplo, a traves medi-
ante MergeSort o QuickSort) y utilizarse despues para un gran n umero de
b usquedas.
Hasta ahora el metodo descrito solo devuelve el primer elemento que se
consiga que contenga la clave de b usqueda, sin embargo con frecuencia no se
puede garantizar que exista un unico elemento con esa clave. Por lo tanto,
en algunas aplicaciones es necesario retornar todos los elementos que tengan
una clave de b usqueda. En este caso luego de que el metodo de b usqueda
binaria determina la ubicacion del primer elemento se exploran secuencial-
mente los elementos a ambos lados del primer elemento hasta conseguir uno
(a cada lado) que no contenga la clave buscada. Puesto que los elementos
en el arreglo estan ordenados entonces elementos con la misma clave deben
estar adyacentes
2.3. B usqueda por Interpolacion
Consiste en tratar de acertar en que parte del intervalo esta la clave que
se esta buscando en lugar de ciegamente dividir el arreglo a la mitad. Para
ello se utiliza la siguiente formula
1
:
x = izq +
(key-a[izq].key)*(der-izq)/(a[der].key-a[izq].key)
1
Se debe prevenir posible division entre cero
6
Si aplicamos la b usqueda por interpolacion al ejemplo de la Figura 1 el
elemento se obtiene en un solo paso ya que:
x = 0 + (pos(O) pos(A)) (16 0)/(pos(U) pos(A))
x = 0 + (14 0) (16 0)/(20 0)
x = 14 16/20
x = 11
(2)
Propiedad 4
La b usqueda por interpolacion utiliza menos de lglgN+1 comparaciones
tanto para una b usqueda con exito como para una b usqueda infructuosa en
archivos con claves aleatorias.
Notese que este metodo:
1. Depende fuertemente de que las claves esten bien distribuidas en el
intervalo. Esta tecnica puede ser enga nada una distribucion no uni-
forme (lo que es frecuente en la practica).
2. Los calculos requeridos no merecen la pena si N es peque no (lgN
lglgN).
3. Debe tenerse en cuenta cuando el arreglo es grande y las coparaciones
entre claves son costosas.
3. B usqueda por

Arbol Binario
Es un metodo simple y ecaz que constituye un algoritmo fundamental
de la informatica.
La propiedad que hace que un arbol binario sea un arbol binario de
b usqueda es la siguiente:
Sea x un nodo de un arbol binario, entonces los valores de todos los
elementos en su subarbol izquierdo son menores que x y los elementos en el
subarbol derecho son elementos mayores que o iguales a x.
7
3.1. Operaciones Basicas
Debido a la naturaleza recursiva de los arboles, es com un que las rutinas
de un arbol binario de busqueda sean recursivas. A continuacion se describen
las operaciones basicas de un arbol de b usqueda binario (considerandolo un
tipo de dato abstracto).
3.1.1. Buscar
Esta operacion retorna el elemento buscado o nulo en caso de que falle
la b usqueda.
Para encontrar un elemento con una clave dada se aplican los siguientes
pasos de forma recursiva:
1. Se compara la clave con la raz.
2. Si es mas peque na se va al subarbol izquierdo.
3. Si es mayor se va al subarbol derecho.
4. Si es igual se detiene la b usqueda.
El procedimiento termina cuando se encuentra un nodo con la clave o
cuando se procesa un arbol vaco (no hay tal clave).
Cabe destacar la simplicidad del metodo y que el n umero de llamadas re-
cursivas es relativamente bajo si el arbol se mantienen balanceado (O(lgN)).
3.1.2. Insertar
Para insertar un nodo en el arbol tpicamente se efect ua una b usqueda
infructuosa de su clave y a continuacion se agrega el nuevo nodo en el lugar
del nodo externo (z o null) donde termino la b usqueda.
Propiedad 5
El tiempo de ejecucion de las operaciones de b usqueda e insercion de-
pende mucho de la forma del arbol binario de b usqueda. Una b usqueda o
insercion en un arbol binario de b usqueda requiere alrededor de 2lgN com-
paraciones, por termino medio, en un arbol construido a partir de N claves
aleatorias.
El mejor caso ocurre cuando el arbol esta balanceado o equilibrado
(O(lgN)). Sin embargo, si las claves no estan ordenadas aleatoriamente el al-
goritmo puede tener un mal comportamiento. En el peor caso, una b usqueda
8
en un arbol binario de b usqueda con N elementos puede necesitar N com-
paraciones.
3.1.3. Ordenar
Para obtener un listado ordenado de los elementos que conforman el
arbol binario de b usqueda solo hace falta recorrelo en en orden simetrico,
por lo tanto la ordenacion se obtiene practicamente de forma gratuita.
3.1.4. Remover
Es una operacion que a menudo resulta incomoda.
En algunas situaciones resulta simple:
1. Eliminar un nodo sin hijos es facil: se podan haciendo nulo el enlace
con su padre.
2. Si el nodo a eliminar tiene un solo hijo se desplaza el enlace del hijo
al enlace del padre.
3. Si el nodo a eliminar tiene dos hijos y uno de sus hijos no tiene hijos,
se utiliza este nodo hijo para reemplazar al padre.
Pero, que hacemos con los nodos mas altos del arbol? Para ello se utiliza
la siguiente estrategia general:
Se reemplaza el nodo a eliminar con el nodo mas peque no del subarbol
derecho. Este nodo es facil de encontrar y contiene la clave superior mas
proxima. Por ser el nodo mas peque no del subarbol derecho no puede tener
hijo izquierdo, por lo que la manipulacion es una de las descritas anterior-
mente.
Note que esta solucion puede parecer asimetrica
2
; en este sentido se
han sugerido varias modicaciones pero la diferencia no es tan notable para
que pueda apreciarse en aplicaciones practicas. Adicionalmente, se ha de-
mostrado que esta estrategia tiende a desequilibrar el arbol (con una altura
media proporcional a

N) si se somete a un gran n umero de operaciones de


insercion y eliminacion.
Cuando el n umero esperado de eliminaciones es peque no se usa una tecni-
ca denominada Lazy Deletion que consiste en unicamente marcar el elemento
que se desea eliminar pero este se deja en el arbol. Si se desea reisertar el
2
Por que no seleccionar la clave inmediatamente inferior es decir el mayor nodo del
subarbol izquierdo?
9
elemento eliminado simplemente se desmarca por lo cual se elimina el costo
de establecer espacios en memoria. Esta tecnica es de uso frecuente cuando
se manejan elementos con claves repetidas (duplicados) y se lleva la cuenta
de la frecuencia de aparicion (simplemente se le resta 1 a la cuenta).
3.1.5. Manejo de Duplicados
Una forma de manejar elementos repetidos es simplemente no hacer nada
especial, sin embargo esto tiende a desbalancear el arbol. Alternativamente
es posible agregar una campo adicional que indique la frecuencia de ocur-
rencia o utilizar una estructura de datos auxiliar (e.g., lista). Esta ultima
altenativa permite que la clave sea parte de una clave mayor.
4. Dispersion (Hashing)
La Tabla de Dispersion (Tabla Hash) es una tabla que almacena pares
(clave, valor). Para ello utiliza un metodo que permite hacer referencia di-
rectamente a los registros por medio de transformaciones aritmeticas sobre
las claves para obtener direcciones de la tabla.
Como tipo de dato abstracto, la tabal de dispersion soporta basicamente
las siguientes operaciones:
insertar
buscar
eliminar
En promedio el tiempo de ejecucion de estas operaciones es constante.
Gracias a esto y a su simplicidad muchas veces se preere a los arboles
binarios de b usqueda; sin embargo requiere memoria extra. Se considera
que es un buen ejemplo del compromiso entre uso de espacio en memoria y
tiempo de ejecucion.
4.1. Funcion de Dispersion (Hash Function)
Las transformaciones aritmeticas se realiza mediante una funcion denom-
inada funcion hash (Figuras 2 y 3). Esta funcion debe tener las siguientes
caractersticas:
1. Facil de calcular.
10
2. Idealmente debera asegurar que dos claves distintas hacen referencia
a celdas distintas. Ya que esto es imposible, al menos debe distribuir
las claves de forma uniforme entre las celdas.
Figura 2: Dominio y recorrido.
Un metodo basico para construir funciones de dispersion consiste en:
1. Disponer de un n umero entero grande k que corresponde directamente
a una clave.
2. Selecciona como tama no de la tabla a un n umero primo (M).
3. Para cualquier clave se determina el valor de k y se calcula f
h
(k) =
k %m.
A continuacion se presenta un ejemplo de la implementacion de una
funcion de dispersion que distribuye de buena manera claves alfanumericas.
/**
* Implements a hash function for String keys.
*
* @param key key.
* @param tableSize size of the table.
* @return hash value.
*/
public static int hash(String key, int tableSize)
11
Figura 3: Asignacion de celdas.
{
int hashVal = 0;
for (int i = 0; i < key.length(); i++)
{
hashVal = 37 * hashVal + key.charAt(i);
}
hashVal %= tableSize;
if (hashVal < 0)
{
hashVal += tableSize;
}
return hashVal;
}
4.2. Resolviendo Colisiones
Entre los problemas que debe resolver una implementacion esta que hacer
cuando dos claves conllevan a un mismo valor (colision). En esta subseccion
abordaremos algunas formas de resolver este problema.
12
4.2.1. Encadenamiento Separado (Separate Chaining)
Simplemente consiste en construir una tabla que contiene una lista en
cada celda. Cuando se inserta un elemento en la tabla, este se pone al nal
de la lista de la celda que le corresponde de acuerdo al valor de la funcion
de dispersion (f
h
) utilizada (ver Figura 4).
Figura 4: Encadenamiento Separado.
Propiedad 6
El encadenamiento separado reduce, en promedio, el n umero de com-
paraciones de la b usqueda secuencial en M (tama no de la tabla) y utiliza
memoria extra de para los M enlaces.
Una mejora simple y evidente es mantener las listas ordenadas, sin em-
bargo el benecio que se obtiene no es tan importante pues las listas tienden
a ser cortas (de hecho es lo deseable).
13
4.2.2. Direccionamiento Abierto (Open Addressing)
Si el n umero de elementos a colocar en la tabla de dispersion se puede
estimar por adelantado, hay suciente espacio de memoria como para al-
macenar todos los registros (clave-data) y ademas se cuenta con espacio de
reserva es mejor no utilizar encadenamiento separado. Esto se debe a que
la b usqueda a traves de las listas enlazadas disminuyen el rendimiento del
algoritmo y son una estructura adicional que agregan complejidad.
El direccionamiento abierto se dene como un metodo para almacenar
N registros en una tabla de tama no M > N, utilizando los lugares vacios de
la tabla para resolver las colisiones.Cuando ocurre una colision se prueban
celdas alternativas hasta encontrar una celda vaca.
Sea la funcion de dispersion f
h
i
= (f
h
(x) + g(i)) %M y g(i) la estrate-
gia de resolucion de colisiones con g(0) = 0, entonces f
h
0
, f
h
1
, f
h
2
, son
probadas sucesivamente hasta encontrar una celda vaca.
Algunas estrategias basicas para resolver colisiones como parte del meto-
do de direccionamiento abierto son: exploracion lineal (g(i) = i), explo-
racion cuadratica (g(i) = i
2
) y doble dispersion (double hashing). El
principal problema de la exploracion lineal es la formacion de bloques de
celdas ocupadas, problema conocido como conglomeracion primaria pri-
mary clustering. Cuando una clave cae de uno de estos bloques se realiza una
b usqueda secuencial para resolver la colision. Para superar este problema se
ha propuesto la exploracion cuadratica, sin embargo una mejor solucion es
la doble dispersion.
La doble dispersion es una solucion popular y, como su nombre lo
indica, consiste en resolver las colisiones mediante el calculo de una segun-
da funcion de dispersion. Formalmente, la funcion de dispersion es f
h
i
=
(f
h
(x) + i f
h
2
(x)) %M donde M es el tama no de la tabla (n umero pri-
mo). Notese que la estrategia de resolucion de colisiones esta dada por la
expresion g(i) = i f
h
2
(x) e incluye la funcion de dispersion (f
h
2
(x)).
Una mala seleccion de la funcionf
h
2
(x) puede ser desastrozo. Por ejemp-
lo, esta funcion nunca debe dar como resultado cero, y es importante probar
todas las celdas en caso de que sea necesario. La literatura establece como
una funcion apropiada f
h
2
(x) = R (x%R), donde R es un n umero primo
menor que el tama no de la tabla (R < M).
Propiedad 7
La doble dispersion utiliza menos exploraciones por termino medio que
la exploracion lineal.
14
Cuando se emplea el direccionamiento abierto se debe tener precausion
al eliminar un registro de tabla. Notese que que las ultimas inserciones para
el valor de dispersion pueden estar mas alla del registro que se pretende
eliminar y el hueco dejado por la eliminacion hara que terminen all las
b usquedas. Entonces en lugar de eliminar (denitivamente) el elemento, este
es marcado de forma tal que las b usquedas no lo tomen en cuenta y pueda
ser sustituido en una futura insercion.
4.3. Factor de Carga y Rehashing
El fator de carga () se dene como la relacion entre el n umero de el-
ementos almacenados en la tabla de dispersion y su tama no ( = N/M).
Es facil intuir que cuando 1 el tiempo de ejecucion de las operaciones
se hace lento y las inserciones pueden fallar
3
. Por ejemplo, en el caso de
una tabla de dispersion de direccionamiento abierto y exploracion lineal, el
promedio de exploraciones necesarias:
para una b usqueda con exito es: ne
1
=
1
2
(1 +
1
(1)
)
para una b usqueda infructuosa es: ne
2
=
1
2
(1 +
1
(1)
2
)
Notese que si 1 ne
1
, ne
2
. En general, se desea que 0,5 0,7
Con frecuencia (en especial en el caso encademamiento separado) cuando
la tabla de dispersion supera el umbral establecido de (e.g. 0.7):
1. se construye otra tabla aproximadamente el doble de grande (pero
siempre su tama no es un numero primo)
2. se recorre la tabla original y se calcula para cada elemento el valor de
la funcion de dispersion para insertarlo en la nueva tabla
Obviamente, es una operacion costosa (O(n)),pero que se realiza con
poca frecuencia.
3
Esto tambien puede ocurrir si existe muchas remociones seguidas de inserciones
15

También podría gustarte