Tabelas de Dispersão
Algoritmos e Estruturas de Dados
Verão 2012
Cátia Vaz
1
Tabelas de endereçamento directo
n 
Endereçamento directo é usado quando o
universo de chaves é pequeno e todas as chaves
são distintas:
n 
Cada posição k, contêm (referência) o elemento com
chave k. Caso esse elemento não exista, T[k]=null.
Cátia Vaz
2
Tabelas de endereçamento directo:
desvantagens
n 
n 
n 
Se o universo U é muito grande, armazenar uma tabela T
de tamanho |U| é impraticável.
O conjunto K de chaves que de facto foi armazenado pode
ser tão pequeno relativamente à dimensão do universo U
que a maior parte do espaço alocado para T está a ser
desperdiçado.
Alternativa: tabelas de dispersão.
n  Embora procurar por um elemento numa tabela de
dispersão possa demorar o mesmo do que procurar um
elemento numa lista ligada ( Θ(N) no pior caso ), sob
certas condições, o tempo expectável para procurar
por um elemento numa tabela de dispersão é O(1).
Cátia Vaz
3
Tabelas de Dispersão
n 
As tabelas de dispersão (hash tables) são
estruturas de dados que associam chaves a valores.
n 
n 
Cada chave é transformada pela função de dispersão
num número que é utilizado para indexar num array para
encontrar os valores associados aquela chave.
As tabelas de dispersão utilizam:
n 
n 
n 
tabela base de indexação;
funções de dispersão (hash functions);
algoritmos para resolução de colisões (se necessário).
Cátia Vaz
4
Tabela Base
n 
Dispersão com índices livres:
n 
n 
n 
Quando o número de elementos pode
ser estimado à partida em N
Tabela de M elementos (M > N)
Dispersão por separação em
listas:
n 
n 
0
Quando o número de elementos a
guardar (N) é desconhecido
Tabela de M listas de elementos
(M < N)
M-1
0
...
...
...
...
...
M-1
...
Cátia Vaz
5
Função de Dispersão
n 
Uma função de dispersão:
n 
n 
n 
n 
n 
n 
Transforma a chave num inteiro [0;M-1] (M tamanho do
array);
Deve distribuir as chaves de forma uniforme e quase
aleatória;
Deve ser rápida de calcular;
Diferentes funções devem ser usadas para diferentes tipos
de dados.
Definição: Colisão - ocorre quando a função de
dispersão devolve o mesmo valor para chaves
distintas
Definição: Função de dispersão ideal - a
probabilidade de ocorrer uma colisão para duas
chaves distintas é 1/M.
Cátia Vaz
6
Função de Dispersão
n 
A função de dispersão mais usada é a divisão:
n 
Chaves pequenas (representáveis por uma palavra
de memória):
n 
n 
n 
tratar as chaves como inteiros (k)
h(k) = k % M
usar um número primo para M.
Cátia Vaz
7
Função de Dispersão
Chave k k%1000 k%1024 k%1021
32699
699
955
027
15114
114
778
820
41502
502
542
662
30444
444
748
835
81699
699
803
019
30651
651
955
021
23670
670
118
187
12219
219
955
988
75745
745
993
191
Cátia Vaz
8
Função de Dispersão
n 
Chaves longas (String)
n 
n 
n 
n 
usar cada caracter como um inteiro (valor da representação
ASCII)
h(k) = k % M
dar um peso a cada caracter correspondente à sua posição na
cadeia
usar um número primo para o tamanho da tabela
static int hash(String s, int M){
int h=0; a=127;
for(int i=0;i<s.length();i++){
h=(a*h + s.charAt(i))%M;
}
return h;}
Cátia Vaz
9
Resolução de Colisões
n 
Para uma tabela de tamanho M, quantas inserções
podem ser feitas até à primeira colisão?
Os algoritmos de resolução de colisões depende do tipo de tabela base
escolhido.
Cátia Vaz
n 
10
Resolução de colisões
n 
Algoritmos de resolução de colisões:
n 
n 
Dispersão com separação em listas, denominado
encadeamento externo (Separate Chaining).
Dispersão com índices livres, denominado
encadeamento interno (Open Addressing ):
n 
n 
n 
Procura Linear (Linear Probing);
Procura Quadrática (Quadratic Probing);
Dupla Dispersão (Double Hashing).
Cátia Vaz
11
Resolução de Colisões:
Encadeamento Externo (Separate Chaining)
n 
n 
n 
Cada posição da tabela tem uma referência para uma lista
Colisões são resolvidas adicionando o elemento ao início da
lista
Remoções são resolvidas removendo o elemento da lista
Ordem de inserção:
77
14
70
70, 72, 14, 77, 19, 75
72
75
hash(k) = k mod 7
19
12
Resolução de colisões:
Encadeamento Externo (Separate Chaining)
13
Resolução de colisões:
Encadeamento Externo (Separate Chaining)
public interface HashFunction<E> {
int hashCode(E e);
boolean equals(E e1, E e2);}
/*Função Hash por omissão*/
public class HashDefaultFunction implements HashFunction<Object> {
private static HashFunction<Object> instance = null;
public static HashFunction<Object> getDefaultInstance(){
if(instance == null) instance = new HashDefaultFunction();
return (HashFunction<Object>)instance;}
public int hashCode(Object o){ return o.hashCode(); }
public boolean equals(Object o1, Object o2){
return o1 == null ? o2 == null : o1.equals(o2);}
private HashDefaultFunction(){}
}
Cátia Vaz
14
Resolução de colisões:
Encadeamento Externo (Separate Chaining)
public class ChainingHashTable<E> {
static class Node<T>{
T value;
Node<T> next;
Node(T v){ value = v;}
}
Node<E>[] v;
int m;
HashFunction<E> ho;
public ChainingHashTable(int len){
this(len,(HashFunction<E>)HashDefaultFunction.getDefaultInstance());}
public ChainingHashTable(int len, HashFunction<E> ho){
v = (Node<E>[]) new Node[len];
m = len;
this.ho = ho; } //(...)}
Cátia Vaz
15
Resolução de colisões:
Encadeamento Externo (Separate Chaining)
public class ChainingHashTable<E> {
//(...)
public class ChainingHashTable<E> {
//(...)
private final int index(E e){
int h=ho.hashCode(e)% m;
return (h<0)?h+m:h;}
public final E search(E key){
int i = index(key);
Node<E> curr = v[i];
while(curr != null){
if(ho.equals(key,curr.value))
return curr.value;
curr = curr.next;
}
return null;
}
public final void insert(E e){
int i = index(e);
Node<E> n = new Node<E>(e);
n.next = v[i];
v[i] = n;}
//(...)}
//(...)}
Cátia Vaz
16
Resolução de colisões:
Encadeamento Externo (Separate Chaining)
public class ChainingHashTable<E> {
//(...)
public final boolean delete(E e){
int i = index(e);
Node<E> curr = v[i];
Node<E> prev = null;
while(curr != null){
if(ho.equals(curr.value,e)){
if(prev == null){ v[i] = v[i].next;}
else{ prev.next = curr.next; }
return true;
}
prev = curr; curr = curr.next;
}
return false;
}//(...)}
Cátia Vaz
17
Encadeamento Externo (Separate
Chaining): análise
n 
n 
Pior Caso do Encadeamento Externo: todas as N
chaves têm o mesmo hash, criando uma lista de
comprimento N. θ(N).
Caso Médio. A performance da dispersão depende de
como a função de dispersão distribui as chaves a
serem armazenadas pelas M posições.
Para o análise do caso médio assume-se o princípio de
dispersão uniforme simples. O algoritmo de procura é:
n 
n 
n 
θ(1 + N/M).
se N=O(M) então O(1 + N/M)=O(1)
18
Resolução de colisões:
Encadeamento interno (Open Addressing )
Inserção: examinar
(probe) sucessivamente
a tabela de dispersão
até encontrar uma
posição vazia. A
sequência de posições
examinadas dependente
da chave a ser inserida.
A função de dispersão
inclui o número de vezes
que a tabela foi
examinada para aquela
chave
19
Resolução de colisões:
Encadeamento interno (Open Addressing )
Procura: examinar a
mesma sequência de
posições que o algoritmo
de inserção examinou
para uma dada chave. A
procura termina ou
quando: ou encontra a
chave; ou examinou M
posições; ou encontra
um espaço livre.
20
Resolução de colisões:
Encadeamento interno (Open Addressing )
Eliminação.
n  Não se pode colocar simplesmente a null na
posição da chave a ser eliminada.
algoritmo de procura inconsistente.
n 
Uma solução será colocar a posição da chave a
ser eliminada com um valor especial ao invés
de ser eliminada.
n 
implica modificação do algoritmo inserção
anterior.
n 
21
Algoritmos de resolução de colisões
Encadeamento interno (Open Addressing )
n 
Procura Linear (Linear Probing);
n 
Procura Quadrática (Quadratic Probing);
n 
Dupla Dispersão (Double Hashing).
h1 e h2, caso se use um m primo, poderão ser:
22
Resolução de Colisões:
Encadeamento Interno-Procura Linear
n 
N < M : método com índices livres.
n 
n 
Dado que há sempre posições livres na tabela, procurar
outra posição.
Procura linear:
n 
se a posição correspondente ao índice devolvido pela
função de dispersão estiver ocupada, ir incrementando o
índice até se encontrar uma posição livre.
0
70
1
14
2
72
3
77
Ordem de inserção: 70, 72, 14, 77, 19, 75
hash(k) = k mod 7
4
5
19
6
75
Cátia Vaz
23
Resolução de Colisões
Procura Linear (Linear Probing)
n 
Desempenho:
n 
n 
n 
n 
n 
os elementos tendem a ficar agrupados (clusters);
os agrupamentos grandes tendem a crescer ainda mais;
o tempo médio de procura tende a crescer para M à
medida que a tabela enche;
operações na tabela de dispersão tornam-se demasiado
lentas quando a tabela atinge 70% - 80% da sua
capacidade.
existem m sequências de examinação (probe) diferentes
24
Resolução de Colisões
Procura Quadrática (Quadratic Probing)
n 
Desempenho:
n 
tem melhores resultados que a procura linear;
n 
A função de hash inicial define a sequência;
n 
n 
elementos que têm a mesma função de hash têm
a mesma sequência logo também tendem a ficar
agrupados (secondary clusters);
Em caso de colisão, existem m sequências de
examinação (probe) diferentes
25
Resolução de Colisões
Dupla Dispersão (Double Hashing)
26
Resolução de Colisões
Dupla Dispersão (Double Hashing)
n 
Desempenho:
n 
é um dos melhores métodos de resolução;
n 
a sequência também depende da chave;
n 
elementos que têm a mesma função de hash têm sequências
distintas
n 
Em caso de colisão, existem m2 sequências de exame (probe)
diferentes
n 
n 
cada par possível (h1(k),h2(k)) assegura uma sequência de
examinação diferente.
Tem que se garantir que a tabela é pesquisada na totalidade:
n 
Usando um m que seja potencia de dois e desenhando h2(k) para produzir
sempre um número impar.
n 
Usando um m primo e desenhando h2(k) para produzir sempre um número
menor que m.
27
Download

Tabelas de Dispersão