ProgramacionFacil

8.1.3 Búsqueda Hash

En este método se requiere que los elementos estén ordenados.

El método consiste en asignar el índice a cada elemento mediante una transformación del elemento, esto se hace mediante una función de conversión llamada función hash. Hay diferentes funciones para transformar el elemento y el número obtenido es el índice del elemento.

La principal forma de transformar el elemento es asignarlo directamente, es decir al 0 le corresponde el índice 0, al 1 el 1, y así sucesivamente pero cuando los elementos son muy grandes se desperdicia mucho espacio ya que necesitamos arreglo grandes para almacenarlos y estos quedan con muchos espacios libres, para utilizar mejor el espacio se utilizan funciones mas complejas.

La función de hash ideal debería ser biyectiva, esto es, que a cada elemento le corresponda un índice, y que a cada índice le corresponda un elemento, pero no siempre es fácil encontrar esa función, e incluso a veces es inútil, ya que puedes no saber el número de elementos a almacenar. La función de hash depende de cada problema y de cada finalidad, y se pueden utilizar con números o cadenas, pero las más utilizadas son:

1.- Restas sucesivas:

Esta función se emplea con claves numéricas entre las que existen huecos de tamaño conocido, obteniéndose direcciones consecutivas. Un ejemplo serian los alumnos de ingeniería en sistemas que entraron en el año 2005 sus números de control son consecutivos y esta definido el numero de alumnos.

05210800 -05210800»» 0

05210801 -05210800»» 1

05210802 -05210800»» 2

05210899 -05210800»» 99

2.- Aritmética modular:

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 dos o más elementos pueden producir el mismo residuo y un índice puede ser señalado por varios elementos. A este fenómeno se le llama colisión. Si el número N es el 7, los números siguientes quedan transformados en:

1679 »> 6

4567 »> 3

8471 »> 1

0435 »> 1

5033 »> 0

Mientras mas grande sea número de elementos es mejor escoger un número primo mayor para seccionar el arreglo en más partes. El número elegido da el número de partes en que se secciona el arreglo, y las cada sección esta compuesta por todos los elementos que arrojen el mismo residuo, y mientras mas pequeñas sean las secciones la búsqueda se agilizara mas que es lo que nos interesa.

3.- Mitad del cuadrado:

Consiste en elevar al cuadrado la clave y coger las cifras centrales. Este método también presenta problemas de colisión.

709^2=502681 –> 26

456^2=207936 –> 79

105^2=11025 –> 10

879^2=772641 –> 26

619^2=383161 –> 31

Nota: en caso de que la cifra resultante sea impar se toma el valor número y el anterior.

4.- Truncamiento:

Consiste en ignorar parte del número y utilizar los elementos restantes como índice. También se produce colisión. Por ejemplo, si un número de 7 cifras se debe ordenar en un arreglo de elementos, se pueden tomar el segundo, el cuarto y el sexto para formar un nuevo número:

5700931 »> 703

3498610 »> 481

0056241 »> 064

9134720 »> 142

5174829 »> 142

5.- 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 el número de 7 cifras en 2, 2 y 3 cifras y se suman, dará otro número de tres cifras (y si no, se toman las tres últimas cifras): 5700931 »> 57 + 00 + 931 = 988

3498610 »> 34 + 98 + 610 = 742

0056241 »> 00 + 56 + 241 = 297

9134720 »> 91 + 34 + 720 = 845

5174929 »> 51 + 74 + 929 = 1054

Nota: Estas solo son sugerencias y que con cada problema se pude implementar una nueva función hash que incluso tu puedes inventar o formular.

Tratamiento de colisiones

Hay diferentes maneras de solucionarlas pero lo más efectivo es en vez de crear un arreglo de número, crear un arreglo de punteros, donde cada puntero señala el principio de una lista enlazada. Así, cada elemento que llega a un determinado índice se pone en el último lugar de la lista de ese índice. El tiempo de búsqueda se reduce considerablemente, y no hace falta poner restricciones al tamaño del arreglo, ya que se pueden añadir nodos dinámicamente a la lista.

PRUEBA LINEAL

Consiste en que una vez detectada la colisión se debe recorrer el arreglo secuencialmente a partir del punto de colisión, buscando al elemento. El proceso de búsqueda concluye cuando el elemento es hallado, o bien cuando se encuentra una posición vacía. Se trata al arreglo como a una estructura circular: el siguiente elemento después del último es el primero. La función de rehashing es, por tanto, de la forma: R(H(X)) = (H(X) + 1) % m (siendo m el tamaño del arreglo) Ejemplo: Si la posición 397 ya estaba ocupada, el registro con clave 0596397 es colocado en la posición 398, la cual se encuentra disponible. Una vez que el registro ha sido insertado en esta posición, otro registro que genere la posición 397 o la 398 es insertado en la posición siguiente disponible.

Ejemplo:

Tomando en cuenta los datos de la sección 2 de este tema crea un programa que mediante búsqueda hash encuentre los datos requeridos y asegurate de tratar las colisiones.

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.IO;

namespace WindowsApplication1
{
    public partial class Form1 : Form
    {
        private int[] datos = new int[5] {1679, 4567, 8471, 0435, 5033 };
        private int[] hash = new int[7];
        private int[] enlace = new int[7];
        public Form1()
        {
            InitializeComponent();
            for (int b = 0; b <= 6; b++)
            {
                enlace[b] = -9999;
            }
            //Reacomodo por hash
            int r, aux=0;
            for (int i = 0; i <= 4; i++)
            {
                r= datos[i] % 7;
                if (datos[i] == 0)
                {
                    hash[r] = datos[i];
                }
                else
                {
                    for(int s=0;s<=6;s++)
                    {
                        if(hash[s]==0)
                        {
                            aux=s;
                        }
                    }
                    hash[aux]=datos[i];
                    enlace[r] = aux;
                }
            }
        }

        private void buscar_Click(object sender, EventArgs e)
        {
            int temp,r;
            temp = int.Parse(textBox1.Text.ToString());
            r = temp % 7;
            if (temp == hash[r])
            {
                MessageBox.Show("Se encuentra en \nel renglon:" + r.ToString(), "Resultado");
            }
            else 
            {
                while(enlace[r] != -9999)
                {
                    if (temp == hash[enlace[r]])
                    {
                        MessageBox.Show("Se encuentra en \nel renglon:" + enlace[r].ToString(), "Resultado");
                        r = enlace[r];
                    }
                }
            }
        }
    }
}

Imagenes de programa corriendo:

:estructura_datos_csharp:8.1.3a.jpg

:estructura_datos_csharp:8.1.3b.jpg

 




 


Recent changes RSS feed Donate Powered by PHP Valid XHTML 1.0 Valid CSS Driven by DokuWiki

Politica de Privacidad