• Nenhum resultado encontrado

11.AED.TabelasHash

N/A
N/A
Protected

Academic year: 2021

Share "11.AED.TabelasHash"

Copied!
55
0
0

Texto

(1)

2035001

Algoritmos e

Estruturas de Dados

(2)

As tabelas de hash adotam o critério de

converter a chave de pesquisa, por uma relação aritmética, diretamente no índice de um array onde se encontra o valor a ela associado.

 A conversão da chave num valor numérico é

feito por uma função de hash.

Tabelas Hash (dispersão)

2

(3)

São tabelas (arrays) cujos índices são de alguma

forma relacionadas com os conteúdos das posições respectivas.

 O relacionamento é estabelecido por uma função

h:K I, onde:

o domínio K é o espaço de chaves e I é o espaço de índices.

 Considerar |K| = n, o número de possíveis chaves.  Considerar |I| = M.

 Deve-se ter I = {0,1,2,…, M-1} ou I = {1,2,3,…, M}.

Tabelas Hash (dispersão)

3

(4)

 Exemplo:

K é o conjunto de todas as cadeias alfabéticas I é um inteiro entre 0 e 25

h é o código ASCII do primeiro caractere da cadeia

módulo 26:

ASCII( ‘AMORA’) = 65 e h(65) = 13. ASCII (‘VAZO’) = 86 e h(86) = 8.

Tabelas Hash (dispersão)

4

(5)

O valor gerado pela função hash h tem de ser

limitado à dimensão da tabela.

Tabelas Hash (dispersão)

5

(6)

 Se a chave for numérica, e assumindo que o

array tem 10 posições, podemos conceber a

seguinte função de hash: k mod 10, kK:

Tabelas Hash (dispersão)

6

(7)

Chave alfnumérica:

Tabelas Hash (dispersão)

7

(8)

 Resumindo....

 A idéia é obter um método para implementação de

dicionários onde o acesso a uma dada chave pode ser feito em O(1) na média.

 No pior caso, entretanto, o acesso pode ter custo

O(n).

Tabelas Hash (dispersão)

8

(9)

 Idealmente, funções de dispersão deveriam ser

injetivas, isto é, todas as chaves deveriam ser mapeadas por h em um índice distinto.

 Isto só é possível se n  M

 Mesmo assim, pode não ser trivial construir a

função de dispersão

Por exemplo, considere o conjunto S de nomes dos

alunos de um curso. Então

|S| < 100 mas é impossível escrever uma função injetiva para

esse domínio que não leve O(|S|) para ser avaliada

Precisamos considerar como o domínio de h o conjunto de

todas as cadeias alfabéticas (de até 40 caracteres, digamos)

Função Hash (de dispersão)

9

(10)

Um caso trivial é h(x) = x. Isto é conhecido como

tabela de endereço direto (Cormen, 2002).

 Em geral, n >> M

 Quando a função de dispersão não é injetiva,

pode-se ter duas chaves x e y, x ≠ y tais que h(x) = h(y). Se se tentar inserir ambas as chaves na tabela tem-se o que é conhecido como colisão.

Função Hash (de dispersão)

10

(11)

 Em geral, uma boa função de dispersão deve

reunir as seguintes qualidades

 produzir poucas colisões

 Depende de se conhecer algo sobre a distribuição das

chaves sendo acessadas

 Ex.: se as chaves são códigos alfanuméricos que

começam sempre por ‘A’ ou ‘B’, usar o primeiro caractere das chaves pode levar a muitas colisões

 ser fácil de computar

 Típicamente, funções contendo poucas operações

aritméticas

 ser uniforme (espalhar a chave pelo vetor)

 Idealmente, o número máximo de chaves que são

mapeadas num mesmo índice deve ser n/M = 

Função Hash (de dispersão)

11

(12)

Assumindo K = {0 .. n – 1} e I = {0 .. M – 1}, a função

de dispersão é dada por

h(x) = x mod M

Qual deve ser o valor de M?

 não deve ser uma potência de 2

se M = 2k, h(x) = k bits menos significativos de x

 não deve ser um número par (impar),

se M é par (impar) então h(x) é par (impar) x é par(impar)

 na prática, bons resultados são obtidos com:

M = número primo não próximo a uma potência de 2 (a divisão

depende de todos os bits de x)

M = número sem divisores primos menores que 20

Funções de Dispersão – Método da

Divisão

(13)

 Chaves sucessivas são mapeadas em índices

sucessivos. Isso pode acarretar problemas.

 O método da divisão é simples:

Funções de Dispersão – Método da

Divisão

13

int h(int x){

static int M = 1031; //número primo

return abs(x) % M; }

(14)

 Para evitar que chaves sucessivas sejam

mapeadas em índices sucessivos, comumente multiplica-se a chave por uma constante k antes de se fazer a divisão (M e k devem ser primos entre si):

h(x) = x*k mod M

Funções de Dispersão – Método da

Divisão

(15)

 Este método evita usar divisão, já que a divisão é,

em geral, mais lenta que multiplicação inteira.

 Toda a aritmética inteira em um computador é

feita módulo W, onde W = 2w e w é o tamanho da

palavra do computador

 Suponha que M = 2k para algum k ≥ 1.

Para uma chave inteira x, usa-se a seguinte função

de dispersão:

Funções de Dispersão – Método do

Meio do Quadrado

15

 



x W

W M x h 2 mod

(16)

Note que, a razão W/M = 2w-k.

Portanto, para multiplicar (x2 mod W) por M/W

basta movimentar a sequencia de bits de w-k posições a direita.

Sendo assim, está-se retirando k bits do meio do

quadrado da chave.

 Código do método (o resultado estará entre 0 e

M-1):

Funções de Dispersão – Método do

Meio do Quadrado

16

int h(int x){

static int k = 10; //M = 1024

static int w = 32; //tamanho da palavra do computador

return x*x >> (w – k); }

(17)

 Funciona bem quando as chaves são

equiprováveis.

 As chaves que tem um grande número de zeros

significativos (não significativos) vão colidir (h(x)=0).

 Este método evita (em relação ao método da

divisão):

que chaves consecutivas tenha código hash

consecutivos (espalha bem estas chaves).

 que, se M é uma potência de 2, obtenha apenas os

últimas k bits da chave.

Funções de Dispersão – Método do

Meio do Quadrado

(18)

 Variação do método do meio do quadrado que

abranda algumas de suas deficiências.

Neste método, multiplica-se a chave x por uma

constante a cuidadosamente escolhida.

Depois extrai-se os k bits centrais do resultado.

A função de dispersão é:

Qual deve ser o valor de a?

Funções de Dispersão – Método da

Multiplicação

18

 



a x W

W M x h * mod

(19)

a não deve ter grande número de zeros

significativos

a não deve ter grande número de zeros não

significativos

Deve-se escolher a e W primos entre si.

Há muitas escolhas para a. Uma delas, para uma

aritmética de 32 bits (W = 232), é

a = 265.435.769.

Representação binária de a:

00001111 11010010 00111010 01111001

Funções de Dispersão – Método da

Multiplicação

(20)

Este valor de a não possui muitos zeros

significativos e não significativos.

a e W são primos entre si. O trecho de código a

seguir ilustra o método da multiplicação:

Funções de Dispersão – Método da

Multiplicação

20

int h(int x){

static int k = 10; //M = 1024

static int w = 32; //tamanho da palavra do computador

static unsigned a = 265435769; //ou deve ser long

return x*a >> (w – k); }

(21)

 No método de Fibonacci, usa-se o número

chamado razão áurea (ou dourada)  :

 Existe uma relação entre  e a sequencia de

Fibonacci Fn:

Funções de Dispersão – Método de

Fibonacci

21

2045868343

8749894848

1,61803398

2

5

1

n n

n F  ˆ 5 1  

(22)

 Faz-se, então

 A tabela apresenta alguns valores apropriados

para a para diversos w (tamanho da palavra):

 Esta função espalha bem as chaves consecutivas.

Funções de Dispersão – Método de

Fibonacci

22 W aW a W/ 216 40 503 232 2 654 435 769 264 11 400 714 819 323 198 485

(23)

Funções de Dispersão – Método da

Dobra

 Suponha que a chave seja dada por uma

seqüência de dígitos escritos numa folha de papel.

 O método consiste em dobrar sucessivamente a

folha de papel após o j-ésimo dígito somando os dígitos que se superpoem (sem fazer o “vai um”)

5 8 7 3 2 1 3 8 + = 8 5 3 8 3 8 0 4 + = 0 4 23

(24)

Funções de Dispersão – Método da

Dobra

 Uma outra variação consiste em fazer a dobra de

k em k bits, ou seja, considerando os “dígitos” 0 e

1 da representação binária do número. O resultado é um índice entre 0 e 2 k – 1

 Nesse caso, ao invés de somar os bits, utiliza-se

uma operação de ou-exclusivo entre os bits

 Não se usa “e” (“ou”) pois estes produzem

resultados menores (maiores) que os operandos  Exemplo: Suponha k = 5

71 = 00010001112

h(71) = 000102 xor 001112 = 001012 = 5

(25)

Funções de Dispersão –

Implementação

 Todos os métodos vistos dispersão chaves de

valores inteiros.

 Dependendo da aplicação, as chaves podem ser

letras, cadeias de caracteres, números reais, …

 Em geral, dados K e a constante positiva M, uma

função de dispersão tem a forma:

25

0

,

1

,

2

,

,

1

:

K

M

(26)

Funções de Dispersão –

Implementação

Na prática, é conveniente interpretar h como

uma composição de funções f e g, onde:

26

K

f :

0

,

1

,

2

,

,

1

:

M

g

 Assim:

 

f

x

g

f

g

h

:

 1a parte: deve-se encontrar um mapeamento

adequado de conjunto de chaves K para Z.

 2a parte: deve-se encontrar um mapeamento

adequado de inteiros não negativos para [0, M-1]

(27)

Funções de Dispersão –

Implementação

Chaves inteiras (short, int, long, char…)

27

 

x

x

f

Chaves em ponto flutuante (float, double, …)

Todo número real x 0 pode ser escrito na forma

(padrão IEEE 754 para float de 32 bits):

 

s e

m

x

1

2

onde:

 

0

,

1

x

0

,

5

m

1

1

.

023

e

1

.

024

(28)

Funções de Dispersão –

Implementação

28

Podemos ter a seguinte definição para f:

 

       0 2 1 2 0 0 x W m x x f

onde W = 2w tal que w é o tamanho da palavra.

Mostra-se que x e y (duas chaves distintas)

colidem se suas mantissas diferem de

W

2 1

x e -x colidem, pois o sinal não é considerado.

O expoente também não é considerado. Se x e y

(29)

Funções de Dispersão –

Implementação

 Chaves de cadeias de caracteres.

Uma cadeia de caracteres, s, de tamanho n é uma

sequencia de caracteres:

29

s s sn

s0, 1,,

 Uma maneira simples para f é:

 

   1 0 n i i s s f

 Cadeias formadas com os mesmos caracteres

(30)

Funções de Dispersão –

Implementação

Alternativamente, podemos construir f da

seguinte forma (no segundo caso limita-se a faixa de f(s)): 30

 

s B s f

 

s B s W f n i i i n n i i i n mod ou 1 0 1 1 0 1        

       

(31)

Funções de Dispersão –

Implementação

31

int f(char *s, int n){ int result = 0;

for(int i=0; i<n; ++i)

result = result*B + s[i]; return result;}

Código para f usando a regra de Horn:

Onde B pode ser um número primo. Java usa

B=31.

 Pode-se também fazer B = 2b (usa-se shift).

 Valores particularmente bons para B: 33, 37, 39

e 41. Estudos experimentais. (GOODRICH, M. T.; et al. Bookman. 2002. 696 p.)

(32)

Funções de Dispersão –

Implementação

Outra forma é construir f usando números

aleatórios: 32

 

    1 0 n i i i p s s f

Neste caso, pi é um inteiro de um conjunto de

pesos gerados aleatoriamene para 0  i n-1.

 Pode-se gerar um peso para cada um dos 256

caracteres ASCII em cada posição i=0..n-1. Assim, p[n, 256].

(33)

Tratamento de Colisões –

Encadeamento Exterior

 Mesmo com boas funções de dispersão, à

medida que o fator de carga  = n/M (número de chaves armazenadas / número de índices) aumenta, a probabilidade de haver colisões aumenta.

(34)

Tratamento de Colisões –

Encadeamento Exterior

 De maneira geral qualquer tabela de

espalhamento precisa prever algum esquema para tratamento de colisões.

(35)

Tratamento de Colisões –

Encadeamento Exterior

 Uma das maneiras mais empregadas para

lidar com colisões é permitir que cada posição da tabela seja ocupada por mais de uma chave

 Em vez de guardar uma chave, guarda-se uma

lista de chaves

 Na verdade, pode-se usar qualquer estrutura –

uma árvore, por exemplo – mas como a ocorrência de colisões deve ser relativamente rara, uma lista ordenada ou não costuma ser suficiente

(36)

Tratamento de Colisões –

Encadeamento Exterior

36

 Exemplo de tabelas de dispersão usando

(37)

Tratamento de Colisões –

Encadeamento Exterior

 Quantas comparações podemos esperar em

média para um acesso a chaves não presentes (buscas sem sucesso)?

Supomos que h é uma função uniforme, que o

fator de carga da tabela é  e que as listas são não ordenadas

(38)

Tratamento de Colisões –

Encadeamento Exterior

Então a probabilidade de h computar cada índice

i é uniforme e igual a 1/M

 O número de comparações feitas ao se acessar a

entrada i da tabela é o comprimento da lista Li

 Então, Carga de Fator 1 Médio Custo 1 0    

   M n L M M i i 38

(39)

Tratamento de Colisões –

Encadeamento Exterior

 Quantas comparações podemos esperar em

média para um acesso a chaves presentes (buscas bem-sucedidas)?

 Mostra-se que este custo é

39 M 2 1 2 1 CM    

(40)

Tratamento de Colisões –

Encadeamento Exterior

 Portanto, se mantemos o fator de carga baixo

(menor que uma constante ), temos que a complexidade média da busca é O(1)

 A única desvantagem do encadeamento exterior

é que ele requer o uso de estruturas externas e com isso o uso de alocação dinâmica de memória e o “overhead” correspondente

 Para contornar isso pode-se usar encadeamento

interior ou endereçamento externo

(41)

Tratamento de Colisões –

Encadeamento Interior

 A idéia é usar como nós das listas as próprias

entradas da tabela

 Há duas variantes

41

Na primeira, a tabela de M entradas é dividida

em duas porções:

A função de dispersão h retorna apenas índices

na primeira porção – de 0 a p–1. Assim, por exeplo: h(x) = x*k mod p.

A segunda porção – índices de p a M-1 é usada

(42)

Tratamento de Colisões –

Encadeamento Interior

 Na primeira…

Pode acontecer que a área de overflow seja toda

tomada sem que todas as entradas da tabela tenham sido usadas

Pode-se aumentar a área de overflow

diminuindo-se p, mas isso também é ineficiente. No limite, p = 1 e a tabela resume-se a uma lista encadeada

(43)

Tratamento de Colisões –

Encadeamento Interior

 Na primeira…

Pode acontecer que a área de overflow seja toda

tomada sem que todas as entradas da tabela tenham sido usadas

(44)

Tratamento de Colisões –

Encadeamento Interior

 Na segunda variante, todo o espaço de

endereçamento é usado

 O maior problema dessa abordagem é que

pode haver colisões secundárias, isto é colisões entre chaves não sinônimas (h(x)

h(y))

44

Função h: h(x) = x mod 7

Ordem de inclusão das chaves: 28, 35, 14, 70 e 19

(45)

Tratamento de Colisões –

Encadeamento Interior

 Quando ocorre uma colisão, a chave é

armazenada na primeira posição livre após

h(x), a posição d, digamos

Se agora incluirmos y≠x tal que h(y)=d,

teremos a fusão das listas correspondentes a

h(x) e h(y), diminuindo a eficiência do

esquema

(46)

Tratamento de Colisões –

Encadeamento Interior

 Um outro problema refere-se às dificuldades

introduzidas no processo de exclusão:

 Não se pode simplesmente retirar o elemento da

sequência de valores na tabela

 Além do valor de chave especial que indica

“posição vazia”, é preciso criar um valor de chave especial que indica “elemento removido”

 Uma inserção posterior pode reaproveitar

posições marcadas com “elemento removido”. É possível após verificar se o elemento a ser inserido não se encontra na tabela.

(47)

Tratamento de Colisões –

Encadeamento Interior

 Na verdade, encadeamento interior com

espaço de endereçamento único não é uma boa idéia, já que os problemas são os mesmos encontrados no tratamento de colisões por endereçamento aberto, sendo que nesse último temos a vantagem de não precisar de ponteiros.

 No encadeamento interior aproveita-se

melhor o espaço reservado para a tabela (vetor).

(48)

Tratamento de Colisões –

Endereçamento Aberto

 Ao invés de usar ponteiros, utiliza-se uma outra

função de dispersão que indica o próximo índice a ser tentado. Em geral temos a função de dispersão h (x, i) onde

x é a chave

i = 0, 1, 2, …, M-1 é o número da tentativa

h(x, i) tem que ser desenhada de tal forma a

visitar todos os M endereços em M tentativas

No pior caso, M tentativas são feitas

(49)

Tratamento de Colisões –

Endereçamento Aberto

 Tentativa linear:

h (x, i) = (h’ (x) + i) mod M

 Tem a desvantagem de agrupar tentativas

consecutivas 49 Após inclusão das chaves: 26, 72 e 27 Função h: h(x) = x mod 23

(50)

Tratamento de Colisões –

Endereçamento Aberto

 Tentativa quadrática

h (x, i) = (h’ (x) + c1i + c2i2 + c0) mod M

Em geral utiliza-se apenas i2 para o termo

quadrático.

 Resolve o problema do agrupamento primário

chaves x e y tais que h’(x) = h’(y) geram a mesma

seqüência de tentativas.

Teorema (Preiss, 2001): Quando M é um número

primo, as primeiras M/2 tentativas são distintas. Provar (pg 203).

 Pelo teorema, se  ≥ 0.5 então …

(51)

Tratamento de Colisões –

Endereçamento Aberto

 Comparação entre tentativas linear/quadrática

(52)

Tratamento de Colisões –

Endereçamento Aberto

 Dispersão dupla

h (x, i) = (h’ (x) + i h’’ (x)) mod M

 A distribuição das chaves é mais aleatório que os

anteriores.

 As sequencias de tentativas são identicas

somente se h’(x) = h’(y) e h” (x) = h”(y).

 Para que os endereços-base obtidos

correspondam a varredura de toda a tabela,

h”(x) e M devem ser primos entre si.

 Ou, fazer M primo.

(53)

Tratamento de Colisões –

Endereçamento Aberto

 Exemplo: h(x, i) = h’(x) + ih”(x) mod M Onde: M = 7, h’(x) = x mod 7 h”(x) = 1 + x mod 5

 Calcular as posições de cada

chave na figura ao lado.

(54)

 Limitações

A tabela de dispersão é uma estrutura de dados do

tipo dicionário, que não permite armazenar elementos repetidos, recuperar elementos sequencialmente (ordenação), nem recuperar o elemento antecessor e sucessor.

 Para otimizar a função de dispersão é necessário

conhecer a natureza da chave a ser utilizada.

No pior caso, a ordem das operações pode ser O(n),

caso em que todos os elementos inseridos colidirem.

Função Hash (de dispersão)

54

(55)

 Limitações

 As tabelas de dispersão com endereçamento aberto

podem necessitar de redimensionamento.  Suas aplicações incluem:

 Banco de dados;

 implementações das tabelas de símbolos dos

compiladores;

 na programação de jogos para acessar rapidamente

a posição para qual o personagem irá se mover e na implementação de um dicionário.

 Ver algoritmos em (SZWARCFITER, 3ª Ed, 2010)

Função Hash (de dispersão)

Referências

Documentos relacionados

O trabalho de migrantes de Fagundes- PB nas usinas Maravilha e Santa Tereza, em Pernambuco aborda as mudanças estruturais do Sistema Capitalista, que atingem a questão do mercado

A combinação dessas dimensões resulta em quatro classes de abordagem comunicativa, que podem ser exemplificadas da seguinte forma: interativo/dialógico: professor e

De seguida, vamos adaptar a nossa demonstrac¸ ˜ao da f ´ormula de M ¨untz, partindo de outras transformadas aritm ´eticas diferentes da transformada de M ¨obius, para dedu-

Na aplicação das políticas contábeis da Companhia e das controladas, a Administração deve fazer julgamentos e elaborar estimativas a respeito dos valores contábeis

[r]

Tabela de medidas: todas as medidas especificadas na tabela de medida em anexo se referem à peça pronta, já tendo recebido a 1ª lavagem caso haja diferença na peça

Disto pode-se observar que a autogestão se fragiliza ainda mais na dimensão do departamento e da oferta das atividades fins da universidade, uma vez que estas encontram-se

Nessa perspectiva, Shulman (2005) argumenta que o nível de conhecimento sobre a matéria a ser ensinada por um professor interfere diretamente na sua maneira de interagir em sala