2. Introducción
Al aplicar el método de búsqueda pertinente en la solución de un problema real.
Debemos tener algunas bases que podemos consultar en algunas fuentes
bibliográficas los diversos algoritmos de búsqueda y analizarlos. De igual forma
puede ser de gran ayuda los ejercicios prácticos. Implementar en un lenguaje de
programación los métodos de búsqueda para un conjunto de n datos generados
aleatoriamente. Generar un análisis del método de búsqueda puede ser de gran
ayuda.
3. Métodos de búsqueda.
La búsqueda es la operación más importante en el procesamiento de información,
ya que permite recuperar datos previamente almacenados. El resultado de una
búsqueda puede ser un éxito, si se encuentra la información o un fracaso, si no la
encuentra.
La búsqueda se puede aplicar sobre elementos previamente ordenados o sobre
elementos desordenados, en el primer caso la búsqueda es más fácil, en cambio en
el segundo se dificulta un poco más el proceso, sobre todo cuando de se trata de
encontrar una cantidad de elementos similares.
Los métodos de búsqueda se clasifican en:
- Búsqueda interna.
- Búsqueda externa.
Búsqueda interna.
La búsqueda interna es aquella en la que todos los elementos de la estructura
estática (arreglo) o dinámica (lista ligada o árbol) se encuentran almacenados en la
memoria principal de la computadora.
Los métodos de búsqueda interna más importantes son:
- Secuencial o lineal.
- Binaria.
- Hash (transformación de claves)
Secuencial.
El método de búsqueda secuencial consiste en revisar la estructura de datos
elemento por elemento hasta encontrar el dato que estamos buscando, o hasta
llegar al final de la estructura de datos.
Normalmente cuando una función de búsqueda concluye con éxito, lo que interesa
es conocer en qué posición fue encontrado el elemento buscado.
La búsqueda secuencial se puede aplicar a estructuras de datos ordenadas o
desordenadas.
4. Si se aplica a una estructura desordenada y el elemento que se está buscando
existe más de una vez en la estructura, el proceso de búsqueda debe continuar
hasta que se llegue al fin de la estructura.
Ejemplo. Si tenemos una estructura con los elementos 5, 8, 3, 2, 9, 5, 7, 0, 5, 1 y
estamos buscando el número 5, el resultado de la búsqueda nos mostraría las
posiciones 0, 5 y 8 y el proceso terminaría al llegar al numero 1 que es el ultimo de
la lista de elementos.
Elementos 5 8 3 2 9 5 7 0 5 1
Posiciones 0 1 2 3 4 5 6 7 8 9
Posiciones donde
encontró el número 5
√ × × × × √ × × √ ×
Ejercicio. Crear un programa que aplique una búsqueda secuencial de un dato
dentro de un arreglo de elementos desordenados y presenta la o las posiciones
donde encontró el dato.
En cambio con una estructura ordenada al encontrar el elemento por primera vez
podemos suponer que una vez que el elemento ya no sea igual al que estamos
buscando, ya no es necesario llegar hasta el fin de la estructura.
Ejemplo. Si tenemos la estructura anterior pero ordenada 0, 1, 2, 3, 5, 5, 5, 7, 8, 9 y
estamos buscando el mismo número 5, el resultado de la búsqueda nos mostraría
las posiciones 4, 5, y 6, y el proceso terminaría ya que el número 7 no es menor ni
igual al que estamos buscando.
Elementos 0 1 2 3 5 5 5 7 8 9
Posiciones 0 1 2 3 4 5 6 7 8 9
Posiciones donde
encontró el número 5
× × × × √ √ √ ×
Ejercicio. Crear un programa que aplique una búsqueda secuencial de un dato
dentro de un arreglo de elementos ordenados y presenta la o las posiciones donde
encontró el dato.
Binaria.
El método de búsqueda binaria divide el total de los elementos en dos, comparando
el elemento buscado con el central, en caso de no ser iguales, se determina si el
elemento buscado es menor o mayor al central, para determinar si la búsqueda
continua del lado izquierdo (menor) o derecho (mayor) del central, repitiendo el
mismo proceso de división y comparación, hasta encontrar el elemento buscado o
que la división ya no sea posible.
5. Debemos destacar que este método de búsqueda solo funciona con estructuras de
datos previamente ordenadas, dividiendo cada vez a la mitad el proceso de
búsqueda, lo que hace que el método sea más eficiente.
Ejemplo. Si tenemos una estructura ordenada 0, 1, 2, 3, 5, 5, 5, 7, 8, 9 y estamos
buscando el número 5, el resultado de la búsqueda nos mostraría la posicione 4 y
el proceso terminaría ya que el elemento buscado no es diferente al que esta en la
posición central.
Elementos 0 1 2 3 5 5 5 7 8 9
Posiciones 0 1 2 3 4 5 6 7 8 9
Posiciones donde
encontró el número 5
i √ F
Este proceso debe sumar la posición inicial y la final, dividiendo el resultado de la
suma entre dos para obtener la posición central generada por el cociente de la
división, en este caso es (0+9)/2 = 4, esta posición se compara con el elemento que
estamos buscando y como son iguales la búsqueda se detiene mostrando la
posición donde lo encontró.
Ejercicio. Crear un programa que aplique una búsqueda binaria de un dato dentro
de un arreglo de elementos ordenados y presenta la posición donde encontró el
dato.
Hash.
El método de búsqueda hash o por transformación de clave aumenta la velocidad
de búsqueda sin necesidad de que los elementos estén previamente ordenados,
comparándolo con los métodos anteriores. Además tiene la ventaja de que el tiempo
de búsqueda es independiente del número de elementos de la estructura que los
almacena.
Este método permite que el acceso a los datos sea por una llave que indica
directamente la posición donde están guardados los datos que se buscan.
Prácticamente trabaja con una función que transforma la llave o dato clave en una
dirección (índice) dentro de la estructura y que en ocasiones puede generar
una colisión, que se define como una misma dirección para dos o más claves
distintas.
Para trabajar con este método de búsqueda debe elegir previamente dos cosas:
- Una función hash que sea facil de calcular y que distribuya
uniformemente las direcciones.
- Un método para resolver colisiones, generando posiciones alternativas.
6. Para encontrar la función hash no existe una regla que permita determinar cuál será
la función más apropiada para generar un conjunto de claves que aseguren la
máxima uniformidad en la distribución de las mismas. Algunas de las funciones hash
más utilizadas son las siguientes:
- Función módulo (por división).
- Función cuadrada.
- Función plegamiento.
- Función truncamiento.
La función módulo o por división toma el residuo de la división entre la clave y el
total de elementos de la estructura, generando la siguiente fórmula:
dirección = (clave % total elementos)
Para lograr una mayor uniformidad en la distribución de los elementos, se debe
buscar que el valor que se usa en el total de elementos sea un número primo más
cercano al tamaño de la estructura.
Ejemplo. Si tenemos un total de 100 elementos y dos claves que sean 7259 y 9359,
las direcciones generadas son las siguientes:
dirección = (7259%100) = 59
dirección = (9359%100) = 59
Estos dos casos generan una colisión, ya que los dos números no se pueden
asignar dentro de la misma dirección en la estructura, para evitar la colisión, se
cambia el valor de 100 por el numero primo más cercano a él, en este caso seria un
97, lo que generaría las siguientes direcciones:
dirección = (7259%97) = 81
dirección = (9359%97) = 47
La función cuadrada como su nombre lo indica eleva al cuadrado la clave y del
resultado, se toman los dígitos centrales como la dirección. El número de dígitos a
tomar se determina del por el rango del índice de toda la estructura. La fórmula hash
es la siguiente:
dirección = dígitos centrales (clave2)
7. Ejemplo. Si tenemos un total de 100 elementos y dos claves que sean 7259 y 9359,
las direcciones generadas son las siguientes:
dirección = dígitos centrales (72592) = 52693081 = 93
dirección = dígitos centrales (93592) = 87590881 = 90
Como el rango de claves es de 1 a 100 se toman dos dígitos centrales.
La función plegamiento divide la clave en partes de igual número de dígitos (la última
puede tener menos dígitos), tomando como dirección los dígitos menos
significativos, después de realizar una operación entre las partes, ya sea una serie
de sumas o de multiplicaciones. La fórmula seria la siguiente:
dirección = dígitos menos significativos (suma de partes)
dirección = dígitos menos significativos (multiplicación de partes)
Ejemplo. Si tenemos un total de 100 elementos y dos claves que sean 7259 y 9359,
las direcciones generadas son las siguientes:
dirección = dígitos menos significativos (72 + 59) =
dígitos menos significativos (131) = 31
dirección = dígitos menos significativos (93 + 59) =
dígitos menos significativos (152) = 52
Como el rango de claves es de 1 a 100 se toman dos dígitos para las particiones y
para la dirección.
La función truncamiento toma algunos de los dígitos de las claves y forma con ellos
una dirección. La elección de los dígitos es arbitraria, podrían tomarse los de las
posiciones pares o impares para con ellos generar la dirección donde se almacenara
la clave, uniendo los dígitos de izquierda a derecha o de derecha a izquierda, su
fórmula es la siguiente:
dirección = elegir dígitos (unión dígitos)
Ejemplo. Si tenemos un total de 100 elementos y dos claves que sean 7259 y 9359,
las direcciones generadas son las siguientes:
dirección = elegir dígitos (7, 5) = 75
dirección = elegir dígitos (9, 5) = 95
8. Para este caso se tomaron los dígitos impares y se unieron de izquierda a derecha.
Un método para la solución de colisiones es tan importante como la función hash,
este método debe entrar en operación cuando la función hash asigna la misma
dirección a dos o mas claves diferentes.
Algunos de los métodos para la solución de colisiones más utilizados son:
- Reasignación.
- Arreglos anidados.
- Encadenamiento.
El método de reasignación como su nombre lo indica consiste en reasignar otra
dirección de forma alternativa en caso de encontrar una colisión, con alguno de los
siguientes métodos:
- Prueba lineal.
- Prueba cuadrática.
- Doble dirección hash.
La prueba lineal consiste en recorrer la estructura secuencialmente a partir del punto
de colisión, hasta encontrar un lugar vació, la estructura se debe controlar como una
estructura circular, donde el siguiente elemento después del último es el primero.
La prueba cuadrática es similar a la anterior, con la diferencia de que la búsqueda
de un lugar vació no se hace de forma consecutiva, se genera a partir de la elevación
de un valor al cuadrado, donde ese valor inicia con el número 1 y lo suma a la
dirección que se encuentra en colisión (d+i2), si se genera nuevamente una colisión
el valor del número se incrementa, se eleva al cuadrado y se suma a la dirección
inicial (d+1, d+4, d+9, d+16, …, d+i2), este proceso se repite hasta que se encuentre
una dirección vacía. Está generación de direcciones puede llegar a exceder el
tamaño de la estructura, si es así, la dirección inicia en uno y el valor inicial a elevar
es el cero.
La doble dirección hash consiste en generar otra dirección hash, una vez que se
detecta la colisión, la generación de la nueva dirección se hace a partir de la
dirección previamente obtenida más uno. La función hash que se aplique para
generar la nueva dirección puede no ser la misma a la utilizada en el proceso
anterior, para esto no existe una regla establecida, lo que permite utilizar cualquiera
de las funciones hash conocidas hasta ahora.
9. El método de arreglos anidados consiste en que cada elemento de la estructura
contenga otra estructura, en la cual se almacenen los elementos colisionados.
Generando con esto una estructura con dos dimensiones, controlando en la
primera dimensión los elementos iniciales y en la segunda dimensión los
colisionados. Esta alternativa genera otro problema mayor, ¿cuál debe ser el
tamaño de la segunda estructura que controla la segunda dimensión?
Ejemplo. Crear una estructura que almacena 10 elementos que son: 15, 20, 24, 51,
71, 13, 16, 22, 46 y 69, y utiliza la función truncamiento tomando los dígitos pares,
ordenados de izquierda a derecha, la solución seria la siguiente:
Valor Dirección
0 15 1
1 15 13 16 20 2
2 20 24 22 24 2
3 51 5
4 46 71 7
5 51 13 1
6 69 16 1
7 71 22 2
8 46 4
9 69 6
Si nos damos cuenta esta solución tiene un gran costo en cuanto a memoria se
refiere, ya que se desperdician demasiados espacios.
El método de encadenamiento consiste en que cada posición de la estructura
contenga una lista ligada, la cual crecerá con cada elemento que entre en la
estructura, sobre todo con los elementos que generen una colisión. Este es el
método más eficiente debido a que las listas ligadas son dinámicas y evitan tener
tantos lugares libres como el método arreglos anidados. Como desventaja se puede
encontrar que cuando la lista ligada crece demasiado se pierde la facilidad de
acceso directo del método hash.
Ejemplo. Crear una estructura que almacena 10 elementos que son: 15, 20, 24, 51,
71, 13, 16, 22, 46 y 69, y utiliza la función truncamiento tomando los dígitos pares,
ordenados de izquierda a derecha, la solución seria la siguiente:
Valor Dirección
0 15 1
10. 1 15 13 16 null 20 2
2 20 24 22 null 24 2
3 51 5
4 46 null 71 7
5 51 null 13 1
6 69 null 16 1
7 71 null 22 2
8 46 4
9 69 6
Búsqueda externa.
La búsqueda externa es aquella en la que todos los elementos se encuentran
almacenados en un archivo, el cual se encuentra en un dispositivo de
almacenamiento secundario como un disco duro, una cinta o una memoria usb.
Los métodos de búsqueda externa más importantes son:
- Secuencial.
- Binaria.
- Hash (transformación de claves)
11. Conclusión
Podemos concluir que estos métodos son de gran interés e importancia igual.
Por ejemplo: La secuencial es el método que consiste en revisar el archivo
elemento por elemento hasta encontrar el dato que se está buscando, o hasta llegar
al final del archivo. Este método de búsqueda se puede aplicar a archivos ordenadas
o desordenadas.y otra es la binaria este método de búsqueda utiliza el mismo
principio que la búsqueda binaria interna. Divide el total de elementos del archivo
en dos, comparando el elemento buscado con el central, en caso de no ser iguales
se determina si el elemento buscado es menor o mayor al central, para determinar
si la búsqueda continua del lado izquierdo (menor) o derecho (mayor) del central,
repitiendo el mismo proceso de división y comparación, hasta encontrar el elemento
buscado o que la división ya no sea posible.