Sunteți pe pagina 1din 26

Tabelas Hash

Tabelas Hash
O uso de listas ou rvores para organizar informaes interessante e produz resultados bastante bons. Entretanto, em nenhuma dessa estruturas se obtm o acesso direto a alguma informao, a partir do conhecimento de sua chave. Uma maneira de organizar dados, que apresenta bons resultados na prtica, conhecida como hashing , baseada na idia de distribuir os dados em posies aleatrias de uma tabela. PodePode-se construir uma tabela de forma a facilitar a busca, colocandocolocandose cada elemento numa posio pr-determinada. prUma tabela hash construda atravs de um vetor de tamanho n, no qual se armazenam as informaes. Nele, a localizao de cada informao dada a partir do clculo de um ndice atravs de uma funo de indexao, a funo de hash.

Tabelas Hash
A posio de um elemento obtida aplicando-se ao elemento a aplicandofuno de hash que devolve a sua posio na tabela. Da basta verificar se o elemento realmente est nesta posio. O objetivo ento transformar a chave de busca em um ndice na tabela. Exemplo: Construir uma tabela com os elementos 34, 45, 67, 78, 89. SupeSupe-se uma tabela com 10 elementos e uma funo de hash x%10 (resto da diviso por 10).
i
0 1 2 3 4 5 6 7 8 9

A[i] -1 -1 -1 -1 34 45 -1 67 78 89

-1 indica que no existe elemento naquela posio.

Tabelas Hash
int hash(int x) { return x % 10; } void insere(int a[], int x) { a[hash(x)] = x; } int busca_hash(int a[], int x) { int k; k = hash(x); if (a[k] == x) return k; return 1; }

Funes de Hash
H muitas maneiras de determinar uma funo de hash. hash. Diviso
 Uma funo de hash precisa garantir que o valor retornado seja um

ndice vlido para uma das clulas da tabela.

 A maneira mais simples usar o mdulo da diviso como h(k) = k%S,

sendo K um nmero e S o tamanho da tabela. sobre as chaves.

 O mtodo da diviso bastante adequado quando se conhece pouco

Enlaamento
 Neste mtodo a chave dividida em diversas partes que so

combinadas ou enlaadas e transformadas para criar o endereo. limite.

 Existem 2 tipos de enlaamento: enlaamento deslocado e enlaamento

Funes de Hash
 Enlaamento deslocado
As partes da chave so colocadas uma embaixo da outra e processadas. Por exemplo, um cdigo 123-45-6789 pode ser dividido em 3 partes: 123123-45123456456-789 que so adicionadas resultando em 1368. Esse valor pode usar o mtodo da diviso valor%S, ou se a tabela contiver 1000 posies pode-se usar os 3 primeiros nmeros para compor podeo endereo.

 Enlaamento limite
As partes da chave so colocadas em ordem inversa. Considerando as mesmas divises do cdigo 123-456-789. 123-456AlinhaAlinha-se as partes sempre invertendo as divises da seguinte forma 321321654654-987. O resultado da soma 1566.

Funes de Hash
MeioMeio-quadrado
 A chave elevada ao quadrado e a parte do resultado usada como

endereo.

Extrao
 Neste mtodo somente uma parte da chave usada para criar o endereo.  Para o cdigo 123-45-6789 pode-se usar os primeiros ou os ltimos 4 dgitos 123-45pode-

ou outro tipo de combinao como 1289.

 Somente uma poro da chave usada.

Transformao da raiz
 A chave transformada para outra base numrica.  O valor obtido aplicado no mtodo da diviso valor%S para obter o

endereo.

Tabelas Hash
Suponha agora os elementos 23, 42, 33, 52, 12, 58. Com a mesma funo de hash, tem-se mais de um elemento hash, tempara determinadas posies (42, 52 e 12; 23 e 33). PodePode-se usar a funo x%17, com uma tabela de 17 posies. A funo de hash pode ser escolhida vontade de forma a atender da melhor forma a distribuio.
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16

-1 52 -1 -1 -1 -1 23 58 42 -1 -1 -1 12 -1 -1 -1 33

Tabelas Hash
A escolha da funo a parte mais importante. sempre melhor escolher uma funo que use uma tabela com um nmero razovel de elementos. No exemplo se houvesse a informao adicional que todos os elementos esto entre 0 e 99, poderia se usar tambm uma tabela com 100 elementos onde a funo de hash o prprio elemento. Mas seria uma tabela muito grande para uma quantidade pequena de elementos. A escolha da funo um compromisso entre a eficincia na busca o gasto de memria. A idia central das tcnicas de hash sempre espalhar os elementos de forma que os mesmos sejam rapidamente encontrados.

Colises Lista Linear


No caso geral, no h informaes sobre os elementos e seus valores. comum conhecer apenas a quantidade mxima de elementos que a tabela conter. Problema: Como tratar os elementos cujo valor da funo de hash o mesmo? Chamamos tal situao de colises. Para tratar as colises, pode-se colocar o elemento na primeira podeposio livre seguinte e considerar a tabela como circular (o elemento seguinte ao ltimo a[n-1] o primeiro a[0]. Isso se aplica tanto na a[ninsero de novos elementos quanto na busca. Esta tcnica conhecida como Lista Linear, Linear Probing ou Sondagem.

Colises Lista Linear


Considere os elementos do exemplo anterior e a funo x%10. x%10.
0 1 2 3 4 5 6 7 8 9 i A[i] -1 -1 42 23 33 52 12 -1 58 -1

Esta forma de tratamento de colises tem uma desvantagem que a tendncia de formao de grupos de posies ocupadas consecutivas, fazendo com que a primeira posio vazia, na prtica, possa ficar muito longe da posio original, dada pela funo de hash. Para inserir um determinado valor x na tabela, ou para concluir que o valor no se encontra na tabela, necessrio encontrar a primeira posio vazia aps a posio h(x).

Colises
int hash(int x) { return x % 10;} int insere(int a[], int x, int n) { int i, cont = 0; i = hash(x); while (a[i] != -1) // procura a prxima posio livre {if (a[i] == x) return 1; // valor j existente na tabela if (++cont == n) return 2; // tabela cheia if (++i == n) i = 0; // tabela circular } a[i] = x; // achou uma posio livre return i; } int busca_hash(int a[], int x, int n) { int i, cont = 0 ; i = hash(x); // procura x a partir da posio i while (a[i] != x) {if (a[i] == -1) return 1; // no achou x if (++cont == n) return 2; // a tabela est cheia if (++i == n) i = 0; // tabela circular }// encontrou return i;

A funo de Hash Critrios de escolha


A operao resto da diviso por (mdulo % em C) a maneira mais direta de transformar valores em ndices. Exemplos:
 Se o conjunto de inteiros e a tabela de M elementos, a funo

de hash pode ser simplesmente x%M. x%M.

 Se o conjunto de valores fracionrios entre 0 e 1 com 8 dgitos

significativos, a funo de hash pode ser x*108%M. x*108%M.

 Se so nmeros entre s e t, a funo pode ser ((x-s)/(t-s))*M ((x-s)/(t-

A escolha bastante livre, mas o objetivo sempre espalhar ao mximo dentro da tabela os valores da funo para eliminar as colises.

A funo de Hash
A funo de hash deve ser escolhida de forma a atender melhor a particularidade da tabela com a qual se trabalha. Os elementos procurados, no precisam ser somente nmeros para se usar hashing. hashing. Uma chave com caracteres pode ser transformada num valor numrico.

Colises - Duplo hashing ou rehash


Quando a tabela est muito cheia a busca seqencial pode levar a um nmero muito grande de comparaes antes que se encontre o elemento ou se conclua que ele no est na tabela. No pior caso, no qual a lista est completa (N elementos ocupados), deve-se (N devepercorrer os N elementos antes de encontrar o elemento ou concluir que ele no est na tabela. A grande desvantagem da Lista Linear o aparecimento de agrupamentos. Uma forma de permitir um espalhamento maior fazer com que o deslocamento em vez de 1 seja dado por uma segunda funo de hash. hash. Essa segunda funo de hash tem que ser escolhida com cuidado. No deve gerar um valor nulo (loop infinito). (loop Deve ser tal que a soma do ndice atual com o deslocamento (mdulo N) d sempre um nmero diferente at que os N nmeros sejam verificados. Para isso N e o valor desta funo devem ser primos entre si.

Colises - Duplo hashing ou rehash


Uma maneira escolher N primo e garantir que a segunda funo de hash tenha um valor K menor que N. Dessa forma N e K so primos entre si. Existem duas funes de Hash: Uma para usar normalmente e outra para Hash: usar quando h colises.
 h1(x)=( x % N ) = C1  h2(x) = ( x % N-1 )+1 = C2 p usada quando h colises N Para calcular o primeiro ndice usa-se C1; usa- C1;  Para calcular o segundo ndice (se existir colises) usa-se (C1+C2) %N usa- (C1+C2)  Para calcular o terceiro ndice usa-se (C1+2C2) %N, depois (C1+3C2) %N, usa- (C1+2C2) %N, (C1+3C2) %N,

etc.

N e N-1 so primos entre si, para que o resto entre os 2 seja diferente de 0.

Colises - Duplo hashing ou rehash


Exemplo: Inserir os elementos 5, 10, 12 e 19 na tabela com N=7. N=7.
h1( x) = x % 7 = C1 h2( x ) = ( x % 6 ) +1 = C2
 5

p h1 ( 5 ) = 5 p 5 est vazio; vazio;

 10 p h1 ( 10 ) = 3 p 3 est vazio; vazio;  12 p h1 ( 12 ) = 5 p 5 est ocupado, faz-se h2; faz 12 p h2 ( 12 ) = 1 p (C1+C2)%7 p 6 est vazio;  19 p h1 ( 19 ) = 5 p 5 est ocupado, faz-se h2; faz 19 p h2 ( 19) = 2 p (C1+2C2)%7 p 0 p (5+2*1)%7=0

0 1 2 3 4 5 6

19

10

5 12

Colises - Duplo hashing ou rehash


Como a seleo da segunda funo de hash livre pode-se escolher podeum valor fixo. Exemplo : Inserir os elementos 25, 37, 48, 59, 32, 44, 70, 81 (nesta ordem) com N=11. N=11.
h1( x) = x % 11 = C1 h2( x ) = 3 = C2
 25 p h1 ( 25 ) = 3 p est vazio; vazio;  37 p h1 ( 37 ) = 4 p est vazio; vazio;  48 p h1 ( 48 ) = 4 p est ocupado, h2 = (4+3)=7 p est vazio; vazio;  59 p h1 ( 59 ) = 4 p est ocupado, h2 = (4+2*3)= 10 p est

vazio; vazio;

Exerccio: Completar a tabela com os nmeros restantes.

Colises - Hash com Lista encadeada


Podemos criar uma lista ligada com os elementos que tem a mesma chave em vez de deix-los todos na mesma tabela. deixCom isso pode-se at diminuir o nmero de chaves possveis geradas pela funo podede hash. hash. TemTem-se, dessa forma, um vetor de ponteiros. Considere uma tabela de inteiros e como funo de hash x%10. x%10.
50 31 92 99 30 1 81

. . .

19

79

29

A funo pode ser melhorada:


 S inserir se j no estiver na tabela. Para isso seria necessrio percorrer a lista at o

final;

 Inserir elemento de modo que a lista fique em ordem crescente.

Colises
Cada um dos mtodos apresentados tem seus prs e contras:
 A Lista linear o mais rpido se o tamanho de memria permite

que a tabela seja bem esparsa.

 O Duplo hash usa melhor a memria mas depende tambm de um

tamanho de memria que permita que a tabela continue bem esparsa. de memria.

 A Lista ligada interessante, mas precisa de um alocador rpido

A escolha de um ou outro depende da anlise particular do caso.

Colises
Em particular, a probabilidade de coliso pode ser reduzida usando uma tabela suficientemente grande em relao ao nmero total de posies a serem ocupadas. Por exemplo, uma tabela com 1000 entradas para uma empresa que deseja armazenar 500 posies haveria uma probabilidade de 50% de coliso, se fosse feita a insero de uma nova chave. ConsideraConsidera-se que, em uma tabela hash bem dimensionada, devemos ter 1,5 acessos tabela, em mdia, para encontrar um elemento. Isto corresponde a uma situao em que metade dos acessos feita diretamente, e, para a outra metade, ocorre uma coliso.

Hash perfeita
O ideal para a funo hash que sejam sempre fornecidos ndices nicos para as chaves de entrada. A funo perfeita (hash perfeita) seria a que, para quaisquer (hash entradas A e B, sendo A diferente de B, fornecesse sadas diferentes. A tabela deve conter o mesmo nmero de elementos. Nem sempre o nmero de elementos conhecido a priori. Na prtica, funes hash perfeitas ou quase perfeitas so encontradas apenas onde a coliso intolervel (por exemplo, nas funes hash da criptografia, ou quando se conhece previamente o contedo da tabela armazenada.

Exerccios
1. Escolha uma boa funo de hash e o nmero de elementos da tabela para os nmeros:
1.2 1.7 1.3 1.8 1.42 1.51

2. Idem para os nmeros:


7 nmeros entre 0.1 e 0.9 (1 casa decimal) 15 nmeros entre 35 e 70 (inteiros) 10 nmeros entre -42 e -5 (inteiros)

3. Idem com um mximo de 1.000 nmeros entre 0 e 1 com no mximo 5 algarismos significativos. 4. Usando a funo: h(K) =K%13 insira as chaves:
18, 41, 22, 44, 59, 32, 31, 73

5. Insira as mesmas chaves usando Double Hashing com as seguintes funes:


h1(K) =K%13 h2(K) =8 - K%8

Remoo
Normalmente no se utilizam tabelas hash em situaes em que elementos devem ser removidos, pelas dificuldades impostas pelos esquemas de tratamento de colises. Quando se remove um elemento, a tabela perde sua estrutura de hash. hash. Suponha que a tabela hash a seguir trata colises por Lista Linear e o elemento x removido.

Com a remoo de x apenas u e v continuariam acessveis: o acesso a w, y e z seria perdido. Para remover x, de forma correta, seria necessrio mudar diversos outros elementos de posio na tabela.

Remoo
Uma tcnica simples, que cria bastante desperdcio, a de marcar a posio do elemento removido como apagada (mas no livre). Isso evita a necessidade de movimentar elementos na tabela mas cria muito lixo. Uma melhoria nessa tcnica reaproveitar as posies marcadas como removidas no caso de novas inseres. eficiente se a freqncia de inseres for equivalente de remoes. Em casos extremos necessrio refazer o hashing completo dos elementos.

Tabelas Hash
Embora permita o acesso direto ao contedo das informaes, o mecanismo das tabelas hash possui uma desvantagem em relao a listas e rvores. Numa tabela hash virtualmente impossvel estabelecer uma ordem para os elementos,ou seja, a funo de hash faz indexao, mas no preserva ordem.