107
Hashing Estrutura de Dados II Jairo Francisco de Souza Árvores B

Cap. 3 - Os Elementos de C++ - ufjf.br · Representação hexadecimal e binária do código ASCII. Hashing – Compressão de chaves alfanuméricas ... 3 8 13 0 4 4 14 6 5 0 15 2

Embed Size (px)

Citation preview

Hashing

Estrutura de Dados IIJairo Francisco de Souza

Árvores B

Tabelas - conceitos

Operações usuaisCriaçãoDestruiçãoInserção de registroExclusão de registroAlteração de registrosConsulta de registros

Tabelas - conceitos

Ordenação pode ser feita fisicamenteMétodo mais intuitivo

Exemplo:

NÚMERO NOME DT-NASCIMENTO SALÁRIO

10130 José 19600725 2500

10850 Paulo 19521203 1200

12700 Marcos 19740303 2860

12800 Antônio 19780523 1950

... ... ... ...

Tabelas - conceitos

Ordenação pode ser feita fisicamenteMétodo mais intuitivo

A tabela pode também ser encadeadaUm marcador para o início da tabela e percurso

circular

NÚMERO NOME DT-NASCIMENTO SALÁRIO

82800 Amilton 19780523 1950

10130 José 19600725 2500

10850 Paulo 19521203 1200

12700 Marcos 19740303 2860

... ... ... ...

2início

Tabelas - conceitos

Ordenação pode ser feita utilizando o encadeamento com o fornecimento de um elo entre os registrosComo uma lista encadeada

NÚMERO Demais campos... Elo

25 7

12 6

71 5

56 3

93 0

17 1

42 4

2início

Tabelas - conceitos

Ordenação pode ser feita utilizando um Vetor Indireto de Ordenação (VIO)

Exemplo:

NÚMERO Demais campos...

25

12

71

56

93

17

42

VIO

2

6

1

7

4

3

5

Tabelas - conceitos

VIOCaso a tabela não possa ser totalmente

disponível em memória principal, é conveniente fazer a carga de todo o VIO ou elo para garantir um bom processo de recuperação da informação da tabela

É possível, e às vezes muito recomendado, ter a tabela ordenada por mais de uma chaveMatrícula Nome

Em muitos casos, também é interessante ordená-la utilizando chaves compostasData de nascimento + Nome

Pesquisa sequencial

ProcedimentoElementos pesquisados sucessivamenteComparação determina se o elemento foi

encontrado ou nãoExemplo: buscar 4 (Arrays e lista encadeada)Importância no número médio de

comparações

5 2 6 1 7 8 4 9

5 2 6 1 4

Pesquisa sequencial

Número médio de comparações

5 2 6 1 7 8 4 9

5 2 6 1 4

Tempo de busca: O(n)

Comparações: (n + 1) / 2

Comparações = 1 + 2 + 3 + .... n = n ((n+1)/2) = n + 1 n n 2

Busca sequencial

Pesquisa sequencial em vetor não ordenado

Necessário pesquisar em todo o vetorfor i := 1 to tamanho_vetor { if vetor[i] == chave then retorna chave}

5 2 6 1 7 8 4 9

5 2 6 1 4

Tempo de busca: O(n)

Comparações: (n + 1) / 2

Busca sequencial

Pesquisa sequencial em vetor ordenadoCaso encontre um número maior que o

buscado, pare.for i := 1 to tamanho_vetor { if vetor[i] > chave then return -1 elseif vetor[i] == chave then retorna chave}

1 2 4 5 6 7 8 9

1 2 4 5 6

Tempo de busca: O(n)

Comparações: (n + 1) / 2

Ainda assim...

Busca sequencial usando frequência

E se alguns valores foram mais acessados que outros?Neste caso, podemos ordenar pela frequência

de recuperação que uma chave possui. Ou seja, a cada busca de uma chave, aumentamos sua frequência e ordenamos pela frequência...

4 8 14 5 3 7 0 9

Tempo de busca: O(n)Ainda assim...

0,50 0,16 0,15 0,04 ...

4 14 8 5 3 7 0 90,48 0,20 0,14 0,03 ...

Busca sequencial usando frequência

Número de comparações usando frequênciaExemplo:

Entrada FRA

1 0,50

2 0,30

3 0,15

4 0,04

5 0,01

EE = 1*0,50 + 2*0,30 + 3*0,15 + 4*0,04 + 5*0,01 = 1,76

EE = 1*0,01+ 2*0,04 + 3*0,15 + 4*0,30 + 5*0,50 = 4,24

Número médio de endereços examinados para a localização de uma entrada, considerando-se que elas aparecem nessa seqüência dentro da tabela:

Se as entradas estivessem distribuídas na ordem inversa (o caso mais desfavorável), o número médio de endereços examinados seria:

Busca sequencial usando frequência

Necessidade de conhecer previamente a frequência ou calculá-la utilizando um histórico de buscas bem-sucedidas

Auto-organização (numa abordagem mais simples):Armazenar o número de buscas, ao invés da

frequênciaAlterar a posição das chaves dado o número de

acessos em cada chave

4 8 14 5 3 7 0 950 42 23 ...

4 14 8 5 3 7 0 950 43 43 23 ...

43

Abordagem diferenteCalcular a posição da chave na tabela baseado no

valor da chave

Posição na tabela pode ser acessada diretamenteNão há necessidade de testesComplexidade é reduzida para O(1)

Busca sequencial: complexidade é O(n)Busca binária: complexidade é O(lg n)

Chave1

Chave2

Chave3

Chave4

Chave5

....

Chaven

h(chave) = posição

HashingSegundo o Webster's New World Dictionary, significa:

Fazer picadinho de carne e vegetais para cozinhar;Fazer uma bagunça

Qualquer que seja a função de transformação, colisões irão acontecer

O Paradoxo do aniversário (Feller, 1968, p.33) diz que em um grupo de 23 pessoas juntas ao acaso, existe uma chance maior do que 50% de que 2 pessoas comemorem aniversário no mesmo dia.

Assim, se for utilizada uma função de transformação uniforme que enderece 23 chaves randômicas em uma tabela de tamanho 365, a probabilidade de que haja colisões é maior do que 50%.

Paradoxo do aniversárioA probabilidade p de se inserir N itens consecutivos

sem colisão em uma tabela de tamanho M é:

Paradoxo do aniversárioAlguns valores de p para diferentes valores de N,onde

M=365.

Para N pequeno a probabilidade p pode ser aproximada por p ≈ N*(N −1) / 730. Por exemplo, para N=10 então p ≈ 87,7%.

HashingA função h deve ser tal que

Transforma uma chave em um índice na tabelaChave pode ser: cadeia de caracteres, um número, um

registro ... Função h é chamada de função hashing ou de

escrutínio.Universo de chaves mapeado em posições

Hashing A função h deve ser tal que

Transforma uma chave em um índice na tabela Chave pode ser: cadeia de caracteres, um número, um

registro ... Função h é chamada de função hashing ou de escrutínio. Universo de chaves mapeado em posições Colisões podem ocorrer:

HashingFunção de hashing perfeita

Transforma diferentes chaves em diferentes posições sem colisões

Para criar função perfeitaTabela tem que conter mesmo número de

posições que o número de elementos que sofreram hashing

Quais são os problemas?Pode-se não conhecer a priori o número total de

elementosO número possível de elementos pode ser muito maior

do que o número total de elementos

HashingExemplo: Armazenamento dos empregados de

uma empresa em um arrayQuantas posições o array terá que ter?Considerando que o número máximo de

funcionários possíveis é igual à quantidade de CPFs diferentes que podem existir. Quantas posições o array terá que ter?

HashingExemplo: Empregados identificados por CPF

Class Empregado{int cpf;char nome[80];char end[120];

...}

CPF como índice: 1 bilhão de entradas 000 000 000 a 999 999 999emp vet[1000000000]

Reservar espaço para o total de possíveis empregadosMas, se empresa possui apenas 500 empregados,

temos desperdício enorme de memória.

DivisãoCompressão de chaves alfanuméricasMultiplicaçãoEnlaçamento

Deslocado Limite

Função Meio-QuadradoExtraçãoTransformação da Raiz

Funções Hashing

Hashing - DivisãoManeira mais simplesUsar módulo da divisãoTSize = sizeof(table)h(k) = k mod TSize, caso k seja um númeroMelhor se Tsize é um número primo

Números primos tendem a distribuir os restos das divisões de maneira mais uniforme do que números não primos.

Se TSize não é um número primo pode-se utilizar função:h(k) = (k mod p) mod TSize, onde p é um número primo

maior que TSize

Divisores não primos podem trabalhar bem com a condição que não tenham fatores não primos maiores do que 20 (Lum et al., 1971).

Hashing – Compressão de chaves alfanuméricas

Utilizado quando as chaves são alfanuméricasChaves são representadas utilizando sua

representação interna

Muitas vezes surge a necessidade de comprimir uma chave, dado sua representação numérica excessivamente grandeUma idéia útil é utilizar o operador XOR (ou exclusivo)

B R A S I L

C2 D2 C1 D3 C9 CC

11000010 11010010 11000001 11010011 11001001 11001100

Representação hexadecimal e binária do código ASCII

Hashing – Compressão de chaves alfanuméricas

Utilização do XOR

Comprimindo a chave BRASIL para um total de 16 bits:

O cálculo final do endereço é feito a partir do valor comprimido, por exemplo, utilizando uma tabela com 521 entradas:

A B A xor B

0 0 0

0 1 1

1 0 1

1 1 0

(BR) 1100001011010010(AS) 1100000111010011(IL) 1100100111001100xor 1100101011001101 = 51917(10)

(51917 mod 521) + 1 = 338

Hashing – Compressão de chaves alfanuméricas

Problema do método:Chaves com permutações de grupos de

letras/dígitos irão produzir colisões.BRASIL, BRILAS, ASBRIL, ILBRAS irão produzir o

mesmo endereçoUma forma de contornar esse problema é

executar uma operação de rotação de bits de cada grupoRotação de 1 bit no segundo grupoRotação de 2 bits no terceiro grupo...

Hashing - MultiplicaçãoEste método utiliza uma propriedade do número

conhecido como inverso da relação áurea (ø-1), cujo valor é:

Se calcularmos K= , 1<= i<= 20:

i k i k1 6 11 72 2 12 43 8 13 04 4 14 65 0 15 26 7 16 87 3 17 58 9 18 19 5 19 710 1 20 3

Há permutação perfeita nas 10 primeiras posições

Quase acontece o mesmo nas demais posições!

Hashing - MultiplicaçãoPodemos generalizar, como função de endereçamento,

o valor

Considerando m o tamanho da tabela e i o valor da chave.

A função produzirá endereços no intervalo [0, m-1]Problema:

Computação lenta para cálculo da chaveDonald Knuth apresentou uma solução alternativa e

igualmente satisfatória

Hashing - MultiplicaçãoSegundo Donald Knuth [1973], ao invés de utilizar ø-1,

ele propõe que seja usado um valor onde w equivale ao tamanho da palavra do computador e A um inteiro tal que A e w sejam primos entre si.Por exemplo, considerando A = 19 e um computador

de 32 bits, temos:

O método deve ser aplicado em tabelas com 2k espaços

Nesse exemplo, o cálculo do endereço “e” no qual deve ser instalada a chave de valor C numa tabela de 2k registros é feito pela execução da seguinte seqüência de comandos:

e := C * A/we := e mod tamanho_tabela

Hashing - EnlaçamentoChave é dividida em diversas partesPartes são combinadas ou enlaçadas e

frequentemente transformadas para produzir endereço alvo

TiposEnlaçamento deslocadoEnlaçamento limite

Hashing – Enlaçamento deslocadoEnlaçamento deslocado

Chave é dividida em partesUma parte é colocada embaixo da outraChaves são processadas a seguir

Exemplo: código pessoal 123-45-6789Dividir em partes e colocar uma embaixo da outra

123456789

Processamento: adicionar partes

123+456+789 = 1368dividir em módulo TSize

Supondo TSize = 10001368 mod 1000 = 368

Hashing – Enlaçamento limiteEnlaçamento limite

Chave é dividida em partesCada parte predeterminada será colocada em ordem inversa

Exemplo: código pessoal 123-45-6789Dividir em partes e colocar uma embaixo da outra

123456789

Processamento, 456 é considerado na ordem inversaadicionar partes

123+654+789 = 1566dividir em módulo TSize

Supondo TSize = 10001566 mod 1000 = 566

Hashing – Função Meio-Quadrado

A chave é elevada ao quadrado e parte do resultado é usada como endereço.

Exemplo: chave 312131212 = 9740641Considerando TSize igual a 1000 e parte do meio para

endereçamentoh(3121) = 406

9740641

Uma máscara binária pode ser utilizada para obter posiçãoSe tamanho da tabela é 1024 (em binário 10000000000)31212 em binário é igual a 10010100101000010110000010101000010 , que é igual a 322, pode ser extraído usando

máscara e uma operação de deslocamento

ExtraçãoParte da chave é usada para calcular o endereçoExemplo:

Código 123-45-6789Pode-se utilizar

primeiros quatro dígitos: 1234Últimos quatro dígitos: 6789Dois primeiros dígitos combinados com os dois últimos: 1289...

Parte escolhida deve produzir boa distribuição das chavesParte descartada deve distinguir pouco as chavesExemplo:

Universidade onde os primeiros 3 dígitos iguais a 999 indica estudante estrangeiroEstes dígitos podem ser omitidos

Transformação da RaizMudar a base do número, por exemplo, de

base 10 para base nonal e dividir em módulo TSize

Exemplo:345 em decimal é igual a 423 em base nonalSe TSize igual a 100

h(345) = 23

Não evita colisões

onde é uniformemente randômico.

Hashing Universal Qualquer função de hash está sujeita ao problema de criar

chaves iguais para elementos distintos. Um estratégia para minimizar as colisões é escolher

aleatoriamente (em tempo de execução) uma função hash a partir do conjunto de funções cuidadosamente desenhado.

Para strings, por exemplo, podemos assumir Deitzfelbinger et al (1992) trata a string x como os

coeficientes de um polinômio módulo um primo. Em , seja um primo, definimos:

Resolução de colisõesColisões podem ocorrer

Mais de uma chave atribuída para a mesma posição

Exemplo: hashing que considera a primeira letra de cada nomeNomes que comecem com a mesma letra teriam conflitos

Função hashing e tamanho da tabela pode ajudar a diminuir o número de colisões

Resolução de colisões

Endereçamento abertoRe-hashingEncadeamento

SeparadoCoalescidoCoalescido com porão

Endereçamento em balde

Endereçamento AbertoUsar próxima posição vaziaInserimos chave u, x, v, w, y e z na tabela:

Inserir u e v h(u)=423 e h(x)=425.

Inserir v h(v)=423 (colisão com u h(u)=423)Próxima posição vazia é 424

Inserir w h(w)=423 (onde inserir w?)

Inserir y e z h(y)=h(z)=425

Endereçamento AbertoResultado da inserção de u, x, v, w, y e z

• Suponha que deseja-se procurar n, onde h(n)=424

• É necessário ir até o 429 para concluir que não n não está presente

• Remoção com endereçamento aberto também leva a inconsistência. Se x for removido, acessos a w, y e z estariam perdidos

• Em alguns casos, não há remoção quando se usa “hashing”

Re-hashingSe houver colisão, usar outra função para

encontrar próxima posição Exemplo: utilizar r(x) para resolver colisão

Posições para uma chave x são encontradas da seguinte forma:p1 = h(x)

p2 = h(x)+r(x),

p3 = h(x)+2*r(x)Etc

De forma mais geral:h(k, i) = (h

1(k) + ih

2(k)) mod m

Re-hashingConsidere a tabela abaixo com 13 espaçosConsidere incluir o valor 14 na tabela, com

h1(k) = k mod 13

h2(k) = 1+(k mod 11)

Em qual posição k=14 será inserida?

0

1 79

2

3

4 69

5 98

6

7 72

8

9

10

11 50

12

Re-hashingConsidere a tabela abaixo com 13 espaçosConsidere incluir o valor 14 na tabela, com

h1(k) = k mod 13

h2(k) = 1+(k mod 11)

Em qual posição k=14 será inserida?posição 9!

0

1 79

2

3

4 69

5 98

6

7 72

8

9

10

11 50

12

Re-hashingVantagem de usar outra função r diferente de h:

se h(x)=h(y)=h(z)=i, é pouco provável que r(y)=r(z), logox fica em i;y fica em i+r(y); e z em i+2*r(z)

busca por z é mais rápida, pois evita calcular r(y) Identificação de que não está presente, quando

encontra-se posição vaziaTem problemas também para remoção

Encadeamento (separado)Cada posição da tabela está associada com uma lista ligadaExemplo:

Este método é chamado de encadeamento separadoNeste método a tabela nunca irá transbordarAumento do comprimento da lista pode degradar o

desempenho da recuperaçãoPode-se ordenar os registros presentes na lista ligada

Não será executada busca exaustivaNecessidade de espaço adicional para os ponteiros

Encadeamento (coalescido) Cada posição na tabela possui espaço para a chave (ou info) e para um

ponteiro que aponta para a posição da próxima chave Método quando ocorre colisão

Encontrar primeira posição disponível Armazenar índice dessa posição com a chave que já está na tabela da

lista ligada Exemplo:

Inserir A2, A3, A5 0

1

2 A2

3 A3

4

5 A5

6

7

8

9

Encadeamento (coalescido) Cada posição na tabela possui espaço para a chave (ou info) e para um

ponteiro que aponta para a posição da próxima chave Método quando ocorre colisão

Encontrar primeira posição disponível Armazenar índice dessa posição com a chave que já está na tabela da

lista ligada Exemplo:

Inserir A2, A3, A5

Inserir B5

Colisão com A5

0

1

2 A2

3 A3

4

5 A5

6

7

8

9

Encadeamento (coalescido) Cada posição na tabela possui espaço para a chave (ou info) e para um

ponteiro que aponta para a posição da próxima chave Método quando ocorre colisão

Encontrar primeira posição disponível Armazenar índice dessa posição com a chave que já está na tabela da

lista ligada Exemplo:

Inserir A2, A3, A5

Inserir B5

Colisão com A5

Inserir B5 na posição vazia a partir do final da tabela

0

1

2 A2

3 A3

4

5 A5 9

6

7

8

9 B5

Encadeamento (coalescido) Cada posição na tabela possui espaço para a chave (ou info) e para um

ponteiro que aponta para a posição da próxima chave Método quando ocorre colisão

Encontrar primeira posição disponível Armazenar índice dessa posição com a chave que já está na tabela da

lista ligada Exemplo:

Inserir A2, A3, A5

Inserir B5

Colisão com A5

Inserir B5 na posição vazia a partir do final da tabela

Inserir A9 (Colisão com B5)

0

1

2 A2

3 A3

4

5 A5 9

6

7

8

9 B5

Encadeamento (coalescido) Cada posição na tabela possui espaço para a chave (ou info) e para um

ponteiro que aponta para a posição da próxima chave Método quando ocorre colisão

Encontrar primeira posição disponível Armazenar índice dessa posição com a chave que já está na tabela da

lista ligada Exemplo:

Inserir A2, A3, A5

Inserir B5

Colisão com A5

Inserir B5 na posição vazia a partir do final da tabela

Inserir A9 (Colisão com B5) Inserir na próxima posição vazia e apontar

0

1

2 A2

3 A3

4

5 A5 9

6

7

8 A9

9 B5 8

Encadeamento (coalescido) Cada posição na tabela possui espaço para a chave (ou info) e para um

ponteiro que aponta para a posição da próxima chave Método quando ocorre colisão

Encontrar primeira posição disponível Armazenar índice dessa posição com a chave que já está na tabela da

lista ligada Exemplo:

Inserir A2, A3, A5

Inserir B5

Colisão com A5

Inserir B5 na posição vazia a partir do final da tabela

Inserir A9 (Colisão com B5) Inserir na próxima posição vazia e apontar Inserir B2 (Colisão com A2)

0

1

2 A2

3 A3

4

5 A5 9

6

7

8 A9

9 B5 8

Encadeamento (coalescido) Cada posição na tabela possui espaço para a chave (ou info) e para um

ponteiro que aponta para a posição da próxima chave Método quando ocorre colisão

Encontrar primeira posição disponível Armazenar índice dessa posição com a chave que já está na tabela da

lista ligada Exemplo:

Inserir A2, A3, A5

Inserir B5

Colisão com A5

Inserir B5 na posição vazia a partir do final da tabela

Inserir A9 (Colisão com B5) Inserir na próxima posição vazia e apontar Inserir B2 (Colisão com A2) Inserir na próxima posição vazia e apontar

0

1

2 A2 6

3 A3

4

5 A5 9

6 B2

7

8 A9

9 B5 8

Encadeamento (coalescido)Posições disponíveis podem ser marcadas, por

exemplo, -2 em next-1 pode ser usado para indicar o final de uma

cadeia0 -2

1 -2

2 A2 6

3 A3 -1

4 -2

5 A5 9

6 B2 -1

7 -2

8 A9 -1

9 B5 8

Encadeamento (coalescido)Posições disponíveis podem ser marcadas, por

exemplo, -2 em next-1 pode ser usado para indicar o final de uma

cadeiaExemplo:

Inserir A7

Inserir C2

Colisão com A2

Segue-se para posição 6Posição 6 está ocupada Next indica fim da cadeia (-1)

0 -2

1 -2

2 A2 6

3 A3 -1

4 -2

5 A5 9

6 B2 -1

7 A7 -1

8 A9 -1

9 B5 8

Encadeamento (coalescido)Posições disponíveis podem ser marcadas, por

exemplo, -2 em next-1 pode ser usado para indicar o final de uma

cadeiaExemplo:

Inserir A7

Inserir C2

Colisão com A2

Segue-se para posição 6Posição 6 está ocupada Next indica fim da cadeia (-1)Achar nova posição vazia

a partir do finalposição 4

0 -2

1 -2

2 A2 6

3 A3 -1

4 -2

5 A5 9

6 B2 -1

7 A7 -1

8 A9 -1

9 B5 8

Encadeamento (coalescido)Posições disponíveis podem ser marcadas, por

exemplo, -2 em next-1 pode ser usado para indicar o final de uma cadeiaExemplo:

Inserir A7

Inserir C2

Colisão com A2

Segue-se para posição 6Posição 6 está ocupada Next indica fim da cadeia (-1)Achar nova posição vazia

a partir do finalposição 4

Inserir C2

Montar cadeia (posição 6 aponta para 4)

0 -2

1 -2

2 A2 6

3 A3 -1

4 C2 -1

5 A5 9

6 B2 4

7 A7-1

8 A9 -1

9 B5 8

Encadeamento (coalescido com porão)

Uso de área de transbordamento para armazenar chaves quando não há mais espaço na tabela.Esta área pode ser alocada dinamicamente

Exemplo:Inserir A2, A3 e A5

0

1

2 A2

3 A3

4

5 A5

6

7

8

9

10

11

12

Porão

Encadeamento (coalescido com porão)

Uso de área de transbordamento para armazenar chaves quando não há mais espaço na tabela.Esta área pode ser alocada dinamicamente

Exemplo:Inserir A2, A3 e A5

Inserir B5 (colisão com A5)Achar posição no porão

0

1

2 A2

3 A3

4

5 A5

6

7

8

9

10

11

12

Porão

Encadeamento (coalescido com porão)

Uso de área de transbordamento para armazenar chaves quando não há mais espaço na tabela.Esta área pode ser alocada dinamicamente

Exemplo:Inserir A2, A3 e A5

Inserir B5 (colisão com A5)Achar posição no porãoIncluir link entre as posições

0

1

2 A2

3 A3

4

5 A5 12

6

7

8

9

10

11

12 B5

Porão

Encadeamento (coalescido com porão)

Uso de área de transbordamento para armazenar chaves quando não há mais espaço na tabela.Esta área pode ser alocada dinamicamente

Exemplo:Inserir A2, A3 e A5

Inserir B5 (colisão com A5)Achar posição no porãoIncluir link entre as posiçõesInserir B2 (colisão com A2)

0

1

2 A2

3 A3

4

5 A5 12

6

7

8

9

10

11

12 B5

Porão

Encadeamento (coalescido com porão)

Uso de área de transbordamento para armazenar chaves quando não há mais espaço na tabela.Esta área pode ser alocada dinamicamente

Exemplo:Inserir A2, A3 e A5

Inserir B5 (colisão com A5)Achar posição no porãoIncluir link entre as posiçõesInserir B2 (colisão com A2)Achar posição no porãoIncluir link entre as posições

0

1

2 A2 11

3 A3

4

5 A5 12

6

7

8

9

10

11 B2

12 B5

Porão

Encadeamento (coalescido com porão)

Uso de área de transbordamento para armazenar chaves quando não há mais espaço na tabela.Esta área pode ser alocada dinamicamente

Exemplo:Inserir A2, A3 e A5

Inserir B5 (colisão com A5)Achar posição no porãoIncluir link entre as posiçõesInserir B2 (colisão com A2)Achar posição no porãoIncluir link entre as posiçõesInserir A9 e B9

0

1

2 A2 11

3 A3

4

5 A5 12

6

7

8

9

10

11 B2

12 B5

Porão

Encadeamento (coalescido com porão)

Uso de área de transbordamento para armazenar chaves quando não há mais espaço na tabela.Esta área pode ser alocada dinamicamente

Exemplo:Inserir A2, A3 e A5

Inserir B5 (colisão com A5)Achar posição no porãoIncluir link entre as posiçõesInserir B2 (colisão com A2)Achar posição no porãoIncluir link entre as posiçõesInserir A9 e B9

0

1

2 A2 11

3 A3

4

5 A5 12

6

7

8

9 A9 10

10 B9

11 B2

12 B5

Porão

Encadeamento (coalescido com porão)

Uso de área de transbordamento para armazenar chaves quando não há mais espaço na tabela.Esta área pode ser alocada dinamicamente

Exemplo:Inserir A2, A3 e A5

Inserir B5 (colisão com A5)

Achar posição no porãoIncluir link entre as posiçõesInserir B2 (colisão com A2)

Achar posição no porãoIncluir link entre as posiçõesInserir A9 e B9

Inserir C2

0

1

2 A2 11

3 A3

4

5 A5 12

6

7

8

9 A9 10

10 B9

11 B2

12 B5

Porão

Encadeamento (coalescido com porão)

Uso de área de transbordamento para armazenar chaves quando não há mais espaço na tabela.Esta área pode ser alocada dinamicamente

Exemplo:Inserir A2, A3 e A5

Inserir B5 (colisão com A5)

Achar posição no porãoIncluir link entre as posiçõesInserir B2 (colisão com A2)

Achar posição no porãoIncluir link entre as posiçõesInserir A9 e B9

Inserir C2

0

1

2 A2 11

3 A3

4

5 A5 12

6

7

8 C2

9 A9 10

10 B9

11 B2 8

12 B5

Porão

Encadeamento (coalescido com porão)

Uso de área de transbordamento para armazenar chaves quando não há mais espaço na tabela.Esta área pode ser alocada dinamicamente

Exemplo:Inserir A2, A3 e A5

Inserir B5 (colisão com A5)

Achar posição no porãoIncluir link entre as posiçõesInserir B2 (colisão com A2)

Achar posição no porãoIncluir link entre as posiçõesInserir A9 e B9

Inserir C2

0 -2

1 -2

2 A2 11

3 A3 -1

4 -2

5 A5 12

6 -2

7 -2

8 C2 -1

9 A9 10

10 B9 -1

11 B2 8

12 B5 -1

Usando:-2 para posição vazia-1 para fim da cadeia

Porão

Endereçamento em baldeArmazenar na mesma posição os elementos que colidemAssociação de um balde a cada endereçoBalde

Bloco de espaço grande o suficiente para armazenar múltiplos itens

Não evita colisãoSe o balde está cheio

Próximo elemento pode ser armazenado no próximo balde vazioÁrea de transbordamento também pode ser utilizada

Neste caso, cada balde deve ser marcado para indicar se a busca deve ser continuada nessa áreaMarcador sim/não

Em conjunto com o marcador pode-se utilizar um ponteiro para indicar onde a lista inicia na área de transbordamento

Endereçamento em baldeExemplo: Balde e sondagem linear pela

próxima posição vaziaInserir A5, A2, A3, B5, A9, B2, B9, C2

Endereçamento em baldeExemplo: Balde e sondagem linear pela

próxima posição vaziaInserir A5, A2, A3, B5, A9, B2, B9, C2

0

1

2 A2

3 A3

4

5 A5

6

7

8

9

Endereçamento em baldeExemplo: Balde e sondagem linear pela

próxima posição vaziaInserir A5, A2, A3, B5, A9, B2, B9, C2

0

1

2 A2

3 A3

4

5 A5 B5

6

7

8

9

Endereçamento em baldeExemplo: Balde e sondagem linear pela

próxima posição vaziaInserir A5, A2, A3, B5, A9, B2, B9, C2

0

1

2 A2

3 A3

4

5 A5 B5

6

7

8

9 A9

Endereçamento em baldeExemplo: Balde e sondagem linear pela

próxima posição vaziaInserir A5, A2, A3, B5, A9, B2, B9, C2

0

1

2 A2 B2

3 A3

4

5 A5 B5

6

7

8

9 A9

Endereçamento em baldeExemplo: Balde e sondagem linear pela

próxima posição vaziaInserir A5, A2, A3, B5, A9, B2, B9, C2

0

1

2 A2 B2

3 A3

4

5 A5 B5

6

7

8

9 A9 B9

Endereçamento em baldeExemplo: Balde e sondagem linear pela

próxima posição vaziaInserir A5, A2, A3, B5, A9, B2, B9, C2

0

1

2 A2 B2

3 A3 C2

4

5 A5 B5

6

7

8

9 A9 B9

Endereçamento em baldeExemplo: Balde e transbordamento

Inserir A5, A2, A3, B5, A9, B2, B9, C2

Ao inserir C2 o balde está cheio, logo este é inserido na área de transbordamento

0

1

2 A2 B2

3 A3

4

5 A5 B5

6

7

8

9 A9 B9

C2

Área de transbordamento

Remoção Com um método de encadeamento

Remover elemento leva à remoção de um nó da lista ligada que contém o elemento

Para outros métodosRemoção pode exigir tratamento mais cuidadoso da resolução de

colisões, exceto no caso raro de uma função hashing perfeita ser utilizada

Exemplo:

Remover A4

0

1 A1

2 A2

3 B1

4

5 B4

6

7

8

9

Pesquisar B4

leva a resposta errada

0

1 A1

2 A2

3 B1

4 A4

5 B4

6

7

8

9

Remoção Com um método de encadeamento

Remover elemento leva à remoção de um nó da lista ligada que contém o elemento

Para outros métodosRemoção pode exigir tratamento mais cuidadoso da resolução de

colisões, exceto no caso raro de uma função hashing perfeita ser utilizada

Exemplo:

Remover A2

0

1 A1

2

3 B1

4

5 B4

6

7

8

9

Pesquisar B1

leva a resposta errada

0

1 A1

2 A2

3 B1

4

5 B4

6

7

8

9

RemoçãoPossível solução

Manter chaves removidas, marcando as posições como elementos não válidos

Busca não termina prematuramenteAo inserir nova chave, ela sobrescreve posição com

elemento não válido0

1 A1

2 A2 x

3 B1

4 A4 x

5 B4

6

7

8

9

RemoçãoPossível solução

Manter chaves removidas, marcando as posições como elementos não válidos

Busca não termina prematuramenteAo inserir nova chave, ela sobrescreve posição com

elemento não válido0

1 A1

2 A2 x

3 B1

4 A4 x

5 B4

6

7

8

9

Para muitas remoções e poucas inserções•A tabela se torna sobrecarregada de registros removidos•Necessidade de testar os elementos removidos

Registros devem ser expurgados depois de certo tempo e tabela reorganizada

RemoçãoPossível solução

Manter chaves removidas, marcando as posições como elementos não válidos

Busca não termina prematuramenteAo inserir nova chave, ela sobrescreve posição com

elemento não válido0

1 A1

2 B1

3

4 B4

5

6

7

8

9

Para muitas remoções e poucas inserções•A tabela se torna sobrecarregada de registros removidos•Necessidade de testar os elementos removidos

Registros devem ser expurgados depois de certo tempo e tabela reorganizada

Hashing para arquivos extensíveis

Todos os métodos anteriores previam tamanho fixo para alocação das chaves.

Existem várias técnicas propostas para implementar hashing em arquivos, os quais possuem tamanhos variáveis, com inserções e deleções constantes.

Podem ser divididas em Técnicas que usam diretórios

hashing expansível (Knott, 1971)hashing dinâmico (Larson, 1978)hashing extensível (Fagin et al, 1979)

Técnicas que não usam diretórioshashing virtual (Litwin, 1978)hashing linear (Litwin, 1980)

Hashing extensível Situação: balde (página primária) fica cheio. Porque não reorganizar o ficheiro duplicando o número de

baldes? Ler e escrever todas as páginas é dispendioso! Idéia: usar um diretório de ponteiros para baldes, duplique o

número de baldes através da duplicação do diretório, particionando justamente o balde que transbordou!

Um diretório é muito menor que um ficheiro, de modo que duplicá-lo é muito menos dispendioso. Só uma página de verbetes de dados é particionada.

O truque reside em como a função de hashing é ajustada!

Hashing extensível A função do diretório é conter informações que indiquem a

localização do balde de interesse.Um diretório é um arranjo de 2d endereços de baldes em

que d é profundidade global (profundidade do diretório).

O tamanho de cada balde é fixo O valor inteiro correspondente

aos primeiros d bits de uma

chave são utilizados.Supondo a profundidade do

diretório igual a 2 e a pseudo-chave igual a 101110, procuraremos na posição 10 pelo endereço do balde que contém a informação desejada.

Hashing extensível É possível ter mais de uma entrada no diretório apontando

para o mesmo balde. Cada balde armazena a informação de sua profundidade

A profundidade do balde é chamada de profundidade local.

A profundidade local indica quantos primeiros bits de cada pseudo-chave são comum a todos os elementos do balde.

A profundidade do balde pode ser menor ou igual à profundidade do diretório.

Hashing extensível Quando necessário, um diretório pode ser expandido

Isto ocorre quando “estoura” o espaço de endereços do diretório, ou seja, cada entrada aponta para um balde diferente de forma que não há como referenciar um novo balde.

Neste caso, o diretório dobra de tamanhoOu seja, a profundidade é incrementada em 1.

Inserção:Após obtida a pseudo-chave, pega-se os p primeiros

dígitos mais significativos da chave como índice para acessar uma posição do diretório.Por exemplo, se a pseudo-chave é 10100110 e a

profundidade é 3, acessaremos a posição 101, ou seja, 5 em decimal.

Daí, teremos 3 casos durante a inserção...

Hashing extensível: inserção Melhor caso

Há espaço no baldeA pseudo-chave é simplesmente inseridaExemplo: inserção da pseudo-chave 111010

Hashing extensível: inserção Caso intermediário

Não há espaço no balde encontrado, mas ele pode ser dividido, visto que mais de uma entrada no diretório faz referência ao balde no qual estamos tentando inserir.Equivalentemente, p do balde é menor que p do

diretórioUm novo balde é criado.As pseudo-chaves são redistribuídas entre o novo balde e

o originalA profundidade local dos dois baldes serão iguais à do

balde original incrementado de 1.

Hashing extensível: inserção Caso intermediário

Exemplo: inserção de 001100

Hashing extensível: inserção Caso intermediário

Exemplo: inserção de 001100

Hashing extensível: inserção Pior caso

Não há espaço no baldeEntrada no diretório faz referência única e exclusivamente

a um baldeOu seja, profundidade local é igual a profundidade

global.O diretório dobra de tamanho

Ou seja, profundidade global é incrementada de 1As pseudo-chaves são distribuídas entre os baldes do

novo diretório

Hashing extensível: inserção Pior caso

Exemplo: Inserção de 100010

Hashing extensível: inserção Pior caso

Exemplo: Inserção de 100010

Hashing extensível: remoção Ao remover uma entrada, temos que fazer duas verificações

Se é possível fundir o balde com um balde amigoSe o tamanho do diretório pode ser reduzido

Encontrando balde amigoPara haver um único balde amigo, a profundidade do

balde tem que ser a mesma do diretório.Dado um índice para o balde, o balde amigo é aquele que

difere apenas no último bit do índiceExemplo: Se um balde tem índice 000 e sua profundidade

é 3 e igual a do diretório, o balde amigo tem índice 001.Quando fundir?

Critério a cargo do programadorPode-se sempre tentar fundir os baldesPode-se definir um número mínimo de informação em

cada balde

Hashing extensível: remoção Reduzindo o diretório

Depois de fundir o balde, talvez o diretório possa ser reduzido

É possível quando cada balde é referenciado por pelo menos duas entradas do diretórioIsto é, todo p local é menor que o p global

Exercício Considere as seguintes pseudo-chaves já geradas por uma

função de hash h()00011, 10011, 11011, 01100, 00110, 00100, 01011, 11100, 10100

Pede-seMostrar a inserção, em ordem, de cada chave usando

abordagem de hashing extensívelMostrar a remoção das chaves 00100, 01100, 10100

ConsidereDiretório com profundidade 1 e balde com tamanho 2.

DicaNo início somente balde é criado e todas as entradas para

do diretório apontam para esse balde. A profundidade local é inicialmente 0.

Hashing linear O hashing extensível cresce de forma exponencial no

momento que cada balde precisa de mais registros Além disso, é necessário um dicionário para armazenar o

endereço de cada balde

O hashing linear cresce de forma mais lentaÉ criado um balde a cada momento que a tabela cresceNão é necessária uma tabela de enderaçamento

Dessa forma, não é necessário também refazer todos os indíces a cada crescimento

FuncionamentoManipulação de espaços através de diferentes funções de

hash aplicadas nos espaços disponíveis

Hashing linear Essa abordagem usa buckets que são estruturas com espaços

para mais de um registroEquivale a “baldes alocados em uma estrutura sequencial”

Cada bucket possui um tamanho fixo M, ou seja, armazena M chaves. Inicia-se a estrutura com um número fixo de buckets.

Caso o espaço do bucket estoure, é utilizado um bucket de overflow que pode ser implementado como uma lista encadeada

Um ponteiro p determina qual o bucket a ser duplicado

Hashing linear A criação de novo bucket é determinado pelo fator de carga da

estruturaOu seja, vários buckets podem conter mais registros do que

o espaço determinado e fazer uso de buckets de overflowA cada inserção, é verificado o fator de carga. Caso seja

maior do que um limite estipulado, um novo espaço de alocação é determinado.

O fator de carga é dado pela quantidade de registros inseridos divididos pela soma dos espaços possíveis nos buckets: FatorCarga = Total(registros) / M * Total(buckets)

Hashing linear: inserção Sendo N o tamanho da tabela hash (número inicial de

buckets), a inserção é dada pela fórmula h(k) = k mod 2g * N, sendo g iniciado de 0.

Ao inserir uma nova chave, aloca-a no bucket determinado pela fórmula acima

Caso o bucket esteja cheio, a chave é alocada no bucket de overflow.

Quando o fator de carga ultrapassa o máximo valor estabelecido, duplica-se o bucket apontado por p. O novo bucket é alocado no final da tabela e p é incrementado.

Os buckets duplicados são reorganizados e todos os dados dos dois buckets passam a obedecer a fórmula h

1(k)=k mod 2g+1 * N.

Hashing linear: inserção Suponha M=3, N=3 e fator de carga = 80%. Suponha a tabela

abaixo já preenchida com algumas chaves e p (ponteiro split) apontando para o índice 0 da tabela.

Como a tabela ainda não sofreu expansão (N=3 é o valor inicial), todas as chaves foram alocadas com a função

h(k) = k mod 2g * N, ou seja

h(k) = k mod 20 * 3 = k mod 3

Fator de carga da tabela é 75% = 9 chaves / 3 buckets com 3 espaços e 1 overflow em cada bucket.

Pode-se também calcular o fator de carga em relação ao número de espaços em buckets somente, sem o bucket de overflow.

Hashing linear: inserção Inserindo 10, o fator de carga vai para 83% (10/12)

Torna-se necessário criar um novo bucketO novo bucket é alocado no final da tabela. As chaves dos dois buckets são redistribuídas com a fórmula

h1(k) = k mod 2g+1 * N, ou seja

h1(k) = k mod 21 * 3 = k mod 6

O ponteiro p (split) é incrementado.

Hashing linear: inserção Inserindo 21, 36 e 25.

O fator de carga vai para 87%

Hashing linear: inserção Inserindo 21, 36 e 25.

O novo bucket é alocado no final da tabela. As chaves dos dois buckets são redistribuídas com a fórmula

h1(k) = k mod 2g+1 * N, ou seja

h1(k) = k mod 21 * 3 = k mod 6

O ponteiro p (split) é incrementado.

Hashing linear: inserção Inserindo 27 e 37.

O fator de carga vai para 83%.As chaves dos dois buckets são redistribuídas com a fórmula

h1(k) = k mod 2g+1 * N, ou seja

h1(k) = k mod 21 * 3 = k mod 6

O ponteiro p (split) volta para a posição inicial.

Índice de p deve ser sempre menor que N!

Exercício Considere uma tabela com 4 buckets de tamanho 3 e fator de

carga 70%. Insira as seguintes chaves:

4, 8, 5, 9, 6, 7, 11, 13, 17, 15, 3, 18, 16, 36, 37

Assuma o fator de carga como sendo a razão entre os registros inseridos pela soma dos espaços dos buckets (sem contar os espaços dos buckets de overflow)