1. SEDE CONCEPCIÓN TALCAHUANO
Algoritmos de Búsqueda
Truncamiento
Asignatura
Análisis de Algoritmos
Integrantes:
Patricia Espinoza Correa
Javier Vilugrón Gozález
Alvaro Paredes
Daniel Quiñones
Jonh Fornerot
Docente:
Pilar Pardo H
Fecha:
Abril 2014
2. Contenido
Contenido...........................................................................................................................................2
I Introducción.....................................................................................................................................1
1.ALGORITMOS DE BÚSQUEDA .........................................................................................................2
1.1.BÚSQUEDA LINEAL (secuencial)...............................................................................................2
1.2.BÚSQUEDA BINARIA.................................................................................................................3
1.3 MÉTODO HASHING..................................................................................................................5
1.3.1. PLEGAMIENTO....................................................................................................................10
1.3.2. TRUNCAMIENTO.................................................................................................................11
1.3.4. ARITMÉTICA MODULAR......................................................................................................12
1.3.5. BÚSQUEDA POR LA MITAD DEL CUADRADO.......................................................................14
CONCLUSIÓN:...................................................................................................................................15
BIBLIOGRAFÍA...................................................................................................................................16
3. I Introducción
Es común que siempre tengamos la interrogante o el deseo de conocer el lugar en
donde se encuentra almacenado un dato o si es que efectivamente está dentro de
nuestra estructura de datos, el problema es la “BÚSQUEDA”…..
¿Cuánto tiempo tardaría una Secretaria si tuviera que buscar entre decenas de
carpetas el archivo de uno de los clientes de la empresa en la cual trabaja....?, de
acuerdo a la eficiencia de la Secretaria, la experiencia que tenga y asumiendo que
estos archivos están perfectamente ordenados y catalogados, se podría especular
que tardaría en promedio unos 15 minutos. Ahora si la misma secretaria pudiera
extraer la información solicitada desde un computador, ¿cuánto tiempo tardaría su
procesador en mostrar el requerimiento que ella está haciendo?
Este es tan sólo un ejemplo de la importancia de las operaciones de búsqueda en
un computador, las cuales se realizan a todos los niveles y con infinidad de
implementaciones distintas, de la cuales, a continuación se examinarán los
algoritmos de búsqueda en una estructura de datos lineal.
1 | P á g i n a
4. 1. ALGORITMOS DE BÚSQUEDA
Un algoritmo de búsqueda es un algoritmo que acepta un argumento a y
trata de encontrar un registro cuya llave sea a. El algoritmo puede dar como
resultado el registro entero o, lo que es más común, un apuntador a dicho registro.
La búsqueda de un elemento dentro de un vector es una de las operaciones
más importantes en el procesamiento de la información, y permite la recuperación
de datos previamente almacenados. El tipo de búsqueda se puede clasificar como
interna o externa, según el lugar en el que esté almacenada la información (en
memoria o en dispositivos externos). Todos los algoritmos de búsqueda tienen dos
finalidades:
• Determinar si el elemento buscado se encuentra en el conjunto en el que se
busca.
• Si el elemento está en el conjunto, hallar la posición en la que se encuentra.
1.1. BÚSQUEDA LINEAL (secuencial)
También se le conoce como búsqueda secuencial y es el método más
sencillo de búsqueda, se utiliza en listas pequeñas y consiste en recorrerla desde
el inicio hasta encontrar la llave indicada o hasta el final en caso que no sea
encontrada antes.
Este tipo de búsqueda compara cada elemento de la lista con el valor
deseado, hasta que este es encontrado o hasta el fin de la lista, en el caso en que
no se encuentre el elemento quiere decir que este no existe dentro de la lista.
Existen tres opciones de casos entre los cuales:
- Mejor caso: el elemento buscado se encuentra en la primera posición del
vector.
2 | P á g i n a
5. - Peor caso: el elemento buscado se encontró en la última posición del vector
y recorrió todas las posiciones.
- Caso promedio: el elemento se encontró en el medio del vector.
Existen también, mejoras que tienden a la eficiencia de la búsqueda lineal, como
son:
- Muestreo de acceso: consiste en detectar la frecuencia en que aparece los
registros y ordenarlos de acuerdo a las probabilidades de que aparezca.
- Movimiento hacia el frente: consiste en que cada vez que se encuentre un
registro a lo largo de la lista, este registro se reorganiza de tal forma que el
registro encontrado se mueve hacia el inicio del vector, y se corren una
posición hacia abajo los que estaban antes que él.
- Transposición: este método es similar al anterior, con la diferencia que una
vez que el elemento buscado es encontrado, este intercambia su posición
con el elemento anterior, ganándose poco a poco su derecho a estar en el
inicio, la ventaja respecto al método anterior, es que no es necesario mover
todos los elementos de la lista para que el elemento encontrado avance
hacia el inicio.
- Ordenamiento: consiste en ordenar los registros en base a la llave de
búsqueda. Esta técnica es útil cuando es una lista de excepciones. En este
caso la búsqueda termina cuando la llave se compara con el primer valor y
ahí termina la búsqueda.
1.2. BÚSQUEDA BINARIA
Este método consiste en examinar primero el elemento central de la lista; si
éste es el elemento buscado, entonces la búsqueda ha terminado. En caso
contrario, se determina si el elemento buscado está en la primera o la segunda
mitad de la lista utilizando el elemento central de la sublista, ejecutando
nuevamente la búsqueda en esa sublista. Este método se utiliza para reducir los
tiempos de búsqueda
3 | P á g i n a
6. En la búsqueda binaria se reduce sucesivamente la operación eliminando
repetidas veces la mitad de la lista restante. Es claro que para poder realizar una
búsqueda binaria debe tenerse una lista ordenada.
Se puede aplicar tanto a datos en listas lineales como en árboles binarios de
búsqueda. Los prerrequisitos principales para la búsqueda binaria son:
- La lista debe estar ordenada.
- Debe conocerse el número de registros.
- Debe tener datos únicos.
Para encontrar el elemento central, suma la primera posición y la última
posición del vector y lo divide por dos.
Cuando ejecuta la búsqueda, compara si el elemento buscado es igual al
elemento central, en caso que sea igual, la búsqueda termina y nos encontramos
con el mejor caso.
En el caso que el elemento buscado no sea igual al elemento central de la lista,
compara ambos y verifica si el buscado es mayor o menor que el central, en caso
que sea menor, iniciará desde la sublista izquierda y nuevamente calculará el
elemento central para repetir la comparación del elemento buscado con el
elemento central, en caso que sean iguales, termina la búsqueda y nos
encontramos con caso promedio.
En el caso en que el elemento buscado no sea igual al elemento central que
resultó de la sublista, nuevamente se calcula el elemento medio de la forma ya
explicada y así sucesivamente hasta que el elemento medio que coincida con el
elemento buscado. Una vez que se han calculado todos los elementos medios
posibles y si el elemento buscado coincide con el último elemento medio posible
coincide con el elemento buscado, entonces nos encontramos con el peor caso.
4 | P á g i n a
7. 1.3 MÉTODO HASHING
Búsqueda mediante transformación de claves (HASH)
Hasta ahora las técnicas de localización de registros vistas, emplean un
proceso de búsqueda que implica cierto tiempo y esfuerzo. El método de
transformación de claves nos permite encontrar directamente el registro buscado
en tablas o archivos que no se encuentran necesariamente ordenados, en un
tiempo independiente de la cantidad de datos.
En los párrafos siguientes se hará referencia a tablas, en lugar de arreglos,
como las estructuras de almacenamiento de la información, pues en general el
método de Hashing se aplica en situaciones que implican el manejo de una
considerable cantidad de información, organizada.
A diferencia de una búsqueda indexada por claves ordinaria, donde usamos
el valor de las claves como índices de un arreglo y necesitamos
indispensablemente que los mismos sean enteros distintos dentro de un rango
equivalente al rango de la tabla, utilizar el método de Hashing nos permite manejar
aplicaciones de búsqueda donde no tenemos claves con características tan
limitadas. El resultado es un método de búsqueda completamente diferente a los
métodos basados en comparaciones, ahora en vez de navegar por las estructuras
comparando palabras clave con las claves en los items, tratamos de referenciar
items en una tabla directamente haciendo operaciones aritméticas para
transformar claves en direcciones de la tabla. Esto último se logra implementando
una Función Hash, que se va a encargar de dicha transformación.
Idealmente, todas las claves deberían corresponder con direcciones
diferentes, pero es muy frecuente que dos o más claves diferentes sean
transformadas a la misma dirección, cuando esto pasa, se dice que se presenta
una Colisión. Es por eso que también se debe implementar algún proceso de
resolución de Colisiones, que se va a encargar de tratar tales situaciones. Uno de
los métodos de resolución de colisiones que existen usa Listas enlazadas y se lo
5 | P á g i n a
8. denomina “encadenamiento directo” o “Hashing abierto” el cual es muy útil en
situaciones dinámicas, donde el número de elementos es difícil de predecir por
adelantado.
El Hashing es un buen ejemplo de balance entre tiempo y espacio. Si no
hubiera limitaciones de memoria, entonces podríamos hacer cualquier búsqueda
en un solo acceso simplemente utilizando la clave como una dirección de
memoria. Este ideal no puede ser llevado a cabo, porque la cantidad de memoria
requerida es prohibitiva cuando la cantidad de registros es considerable. De la
misma manera, si no hubiese limitación de tiempo, podríamos usar un menor
espacio en memoria usando un método secuencial. Hashing provee una manera
de usar una razonable cantidad de memoria y tiempo y lograr un balance entre los
dos extremos mencionados. En particular, podemos lograr el balance deseado
simplemente ajustando el tamaño de la tabla, sin necesidad de re-escribir código o
cambiar algoritmos.
En líneas generales podemos decir, que es razonable esperar búsquedas
(Search), borrados (Delete) e inserciones (Insert) en tiempo constante,
independientemente del tamaño de la tabla. O sea que es ideal para aplicaciones
que realicen mayoritariamente este tipo de operaciones, por el otro lado, Hashing
no provee implementaciones eficientes para otras operaciones como por ejemplo
Ordenamiento (Sort) o Selección (Select).
METODO DE BUSQUEDA HASHING:
Hash: se refiere a una función o método para generar claves o llaves que
representen de manera casi unívoca a un documento, registro, archivo, etc.,
resumir o identificar un dato a través de la probabilidad, utilizando una función
Hash o algoritmo Hash. Un Hash es el resultado de dicha función o algoritmo.
6 | P á g i n a
9. FUNCION HASH
Es una función para resumir o identificar probabilísticamente un gran
conjunto de información, dando como resultado un conjunto imagen finito
generalmente menor (un subconjunto de los números naturales).. Varían en los
conjuntos de partida y de llegada y en cómo afectan a la salida similitudes o
patrones de la entrada
ALGORITMO HASHING
Algoritmo que se utiliza para generar un valor de Hash para algún dato,
como por ejemplo claves. Un algoritmo de Hash hace que los cambios que se
produzcan en los datos de entrada provoquen cambios en los bits del Hash.
Gracias a esto, los Hash permiten detectar si un dato ha sido modificado.
Ventajas
Se pueden usar los valores naturales de la llave, puesto que se traducen
internamente a direcciones fáciles de localizar.
Se logra independencia lógica y física, debido a que los valores de las
llaves son independientes del espacio de direcciones.
No se requiere almacenamiento adicional para los índices.
Desventajas
No pueden usarse registros de longitud variable.
El archivo no está clasificado.
No permite claves repetidas.
Solo permite acceso por una sola llave.
7 | P á g i n a
10. Un problema potencial encontrado en este proceso, es que tal función no
puede ser uno a uno; las direcciones calculadas pueden no ser todas únicas,
cuando R(k1 )= R(k2)Pero : K1 diferente de K2 decimos que hay una colisión.
Costos
Tiempo de procesamiento requerido para la aplicación de la función Hash.
Tiempo de procesamiento y los accesos E/S requeridos para solucionar las
colisiones.
La eficiencia de una función Hash depende de:
La distribución de los valores de llave que realmente se usan.
El número de valores de llave que realmente están en uso con respecto al
tamaño del espacio de direcciones.
El número de registros que pueden almacenarse en una dirección dada sin
causar una colisión.
La técnica usada para resolver el problema de las colisiones.
COMPARACIÓN ENTRE LAS FUNCIONES HASH
Aunque alguna otra técnica pueda desempeñarse mejor en situaciones
particulares, la técnica del residuo de la división proporciona el mejor desempeño.
Ninguna función Hash se desempeña siempre mejor que las otras. El método del
medio del cuadrado puede aplicarse en archivos con factores de cargas bastantes
bajas para dar generalmente un buen desempeño. El método de pliegues puede
ser la técnica más fácil de calcular pero produce resultados bastante erráticos, a
menos que la longitud de la llave sea aproximadamente igual a la longitud de la
dirección.
Si la distribución de los valores de llaves no es conocida, entonces el
método del residuo de la división es preferible. Note que el hashing puede ser
aplicado a llaves no numéricas. Las posiciones de ordenamiento de secuencia de
8 | P á g i n a
11. los caracteres en un valor de llave pueden ser utilizadas como sus equivalentes
"numéricos". Alternativamente, el algoritmo Hash actúa sobre las representaciones
binarias de los caracteres.
Todas las funciones Hash presentadas tienen destinado un espacio de
tamaño fijo. Aumentar el tamaño del archivo relativo creado al usar una de estas
funciones, implica cambiar la función Hash, para que se refiera a un espacio
mayor y volver a cargar el nuevo archivo.
Matemáticamente hablando:
Lo fundamental del método es encontrar una función que a partir de la clave
(proveniente de un universo de N claves posibles), sea ésta numérica o
alfanumérica, encuentre un entero sin signo entre 0 y B-1, si la tabla de hash está
formada por B elementos. Con N> B.
La función de Hash muele o desmenuza o hace un picadillo con la clave, de allí el
nombre; que es el significado de la palabra inglesa Hash (no es un apellido).
Para toda clave x, perteneciente al Universo, debe estar definida la función de
Hash, h(x), con valores enteros entre 0 y (B-1).
La función h(x) debe distribuir las claves, lo más equitativamente posible, entre los
B valores.
Si la función de Hash es “buena”, habrán pocas colisiones; si hay c
colisiones en promedio, las operaciones resultarán de complejidad N, constante;
prácticamente independiente de B. Si todas las claves que se buscan en la tabla,
producen colisiones, que es el peor caso, las operaciones resultarán O(B), esto en
caso de tener B claves que colisionen en la misma entrada de la tabla.
Las funciones de Hash son generadores de números pseudo aleatorios.
9 | P á g i n a
12. 1.3.1. PLEGAMIENTO
Consiste en dividir el número en diferentes partes, y operar con ellas
(normalmente con suma o multiplicación).
También se produce colisión. Por ejemplo, si dividimos los números de 8
cifras en 3, 3 y 2 cifras y se suman, dará otro número de tres cifras (y si no, se
cogen las tres últimas cifras):
Ejemplos:
13000000 --> 130 + 000 + 00 = 130
12345678 --> 123 + 456 + 78 = 657
71140205 --> 711 + 402 + 05 = 1118 --> 118
13602499 --> 136 + 024 + 99 = 259
25000009 --> 250 + 000 + 09 = 259
En esta técnica el valor de la llave es particionada en varias partes, cada
una de las cuales (excepto la última) tiene el mismo número de dígitos que tiene la
dirección relativa objetivo. Estas particiones son después plegadas una sobre otra
y sumadas. El resultado, es la dirección relativa. Igual que para el método del
medio del cuadrado, el tamaño del espacio de direcciones relativas es una
potencia de 10.
Ejemplo:
Sea K la clave del dato a buscar. K está formada por los dígitos d1, d2, ... , dn. La
función Hash queda definida por la siguiente fórmula:
H(K) = dígmensig ((d1 ... di) + (di+1 ... dj) + ... + (dl ... dn)) + 1
10 | P á g i n a
13. Sean N=100 el tamaño del vector, y sean sus direcciones los números entre 1 y
100.
Sean:
K1=7259
K2=9359
Dos claves a las que deban asignarse posiciones en el arreglo. Se aplica la
fórmula para calcular las direcciones correspondientes al K1 y K2.
H(K1)=dimensig (72 + 59) + 1 = dígmensig (131) + 1 = 32
H(K2)=dimensig (93 + 59) + 1 = dígmensig (152) + 1 = 53
De la suma de las partes se toman solamente dos dígitos porque los índices del
arreglo varían de 1 a 100.
1.3.2. TRUNCAMIENTO
Consiste en tomar algunos dígitos de la clave y formar con ellos una
dirección. Este método es de los más sencillos, pero es también de los que
ofrecen menos uniformidad en la distribución de las claves.
Sea K la clave del dato a buscar. K está formada por los dígitos d1, d2, ... , dn. La
función hash queda definida por la siguiente fórmula:
H(K) = elegirdígitos (d1d2...dn) + 1)
La elección de los dígitos es arbitraria. Podrían tomarse los dígitos de las
posiciones impares o de las pares. Luego podría unírseles de izquierda a derecha
o de derecha a izquierda. La suma de una unidad a los dígitos seleccionados es
para obtener un valor entre 1 y 100.
El siguiente ejemplo presenta un caso de función Hash por truncamiento:
Sean N = 100 el tamaño del arreglo, y sean sus direcciones los números entre 1 y
100.
Sean :
11 | P á g i n a
14. K1 = 7259
K2 = 9359
Dos claves a las que deban asignarse posiciones en el arreglo. Se aplica la
fórmula para calcular las direcciones correspondientes a K1 y K2.
H(K1)=elegirdígitos(7 2 5 9) + 1 = 76
H(K2)=elegirdígitos(9 3 5 9) + 1 = 96
En este ejemplo se toma el primer y tercer número de la clave y se une éste de
izquierda a derecha.
En todas las funciones Hash anteriores se presentan ejemplos de claves
numéricas. Sin embargo, en la realidad las claves pueden ser alfabéticas o
alfanuméricas. En general, cuando aparecen letras en las claves se suele asociar
a cada una un entero a efectos de convertirlas en numéricas.
A B C D ...Z
01 02 03 04 27
Si por ejemplo la clave fuera ADA, su equivalente numérica sería 010401. Si
hubiera combinación de letras y números, se procedería de la misma manera. Por
ejemplo, dada una clave Z4F21, su equivalente numérica sería 2740621. Otra
alternativa sería, para cada carácter, tomar el valor decimal asociado según el
código ASCII. Una vez obtenida la clave en su forma numérica, se puede utilizar
normalmente cualquiera de las funciones antes mencionadas.
1.3.4. ARITMÉTICA MODULAR
Convertir la clave a un entero, dividir por el tamaño del rango del índice y
tomar el resto como resultado. La función de conversión utilizada es MOD (Modulo
o resta de división entera).
12 | P á g i n a
15. Donde el mes el tamaño del arreglo con índices de 0 hasta n-1. Los valores
de la función y direcciones van de 0 a n-1 ligeramente menor al tamaño del array.
La mejor elección de los módulos son los números primos.
M=100 F(x)= x mod 100
X=234661234
F(x)=234661234 mod 100 =34
La clave de búsqueda en una cadena de caracteres tal como el nombre
para obtener direcciones de conversión el método más simple es asignar a cada
carácter de la cadena un valor entero (ejemplo A=1, B=2, C=3, etc) y sumar los
valores de los caracteres en la cadena al resultado se le aplica entonces el
modulo.
El índice de un número es resto de la división de ese número entre un
número N prefijado, preferentemente primo. Los números se guardarán en las
direcciones de memoria de 0 a N-1. Este método tiene el problema de que cuando
hay N+1 elementos, al menos un índice es señalado por dos elementos (teorema
del palomar). A este fenómeno se le llama colisión, y es tratado más adelante. Si
el número N es el 13, los números siguientes quedan transformados en: 13000000
--> 0
Ejemplo:
En este caso, h(k) = m (k A mod 1)⎣ ⎦ , en que 0 < A < 1; el valor de m no es
crítico y típicamente se usa una potencia de 2 para facilitar el cálculo
computacional de la función.
Por ejemplo, si
k = 123456,
m = 10,000, y
A = ( 5 – 1)/2 ≈ 0.6180339887,
Entonces:
13 | P á g i n a
16. h(k) = 41.
1.3.5. BÚSQUEDA POR LA MITAD DEL CUADRADO
En esta técnica, la llave es elevada al cuadrado, después algunos dígitos
específicos se extraen de la mitad del resultado para constituir la dirección relativa.
Si se desea una dirección de n dígitos, entonces los dígitos se truncan en ambos
extremos de la llave elevada al cuadrado, tomando n dígitos intermedios. Las
mismas posiciones de n dígitos deben extraerse para cada llave.
Utilizando esta función hashing el tamaño del archivo resultante es de 10^n donde
n es el número de dígitos extraídos de los valores de la llave elevada al cuadrado.
Ejemplo:
Con el número 89047 que tomamos como clave tendremos:
89047 * 89047 = 7929368209
Y luego por medio de la extracción (números de en medio) obtenemos (10^4 no da
un rango de 10000 direcciones) el número 9368 como dirección de dicha clave.
Éste método presenta problemas de colisión.
14 | P á g i n a
17. CONCLUSIÓN:
La característica fundamental que debe tener un algoritmo es que sea
correcto, es decir, que produzca el resultado deseado en tiempo finito.
Adicionalmente puede interesarnos que sea claro, que esté bien estructurado, que
sea fácil de usar, que sea fácil de implementar y que sea eficiente.
De acuerdo a esta lógica y en la búsqueda constante por encontrar
algoritmos de búsqueda correctos que mantengan tan bajo como sea posible el
consumo de recursos, es decir, que sean lo más eficientes posible, concluimos
que de todos los que investigamos, ningún tipo de búsqueda es mala y a la vez
ninguna es perfecta, depende exclusivamente del uso dado , como por ejemplo la
búsqueda binaria es la más rápida pero a su vez no nos sirve si los datos no están
ordenados de lo contrario la búsqueda lineal a pesar de ser más lenta funcionará
aunque los datos no tengan un orden, por lo tanto el concepto de eficiencia de un
algoritmo es un concepto relativo, esto quiere decir que ante dos algoritmos
correctos que resuelven el mismo problema, lo que prima es la necesidad
individual de cada caso que tengamos que resolver.
15 | P á g i n a