Dicionários Prof. César Melo
Definição Estruturas que permitem a recuperação da informação a partir do seu valor; Contrasta com filas e pilhas que é posicional; Três operações: Inserção(k, d), chave k; remoção(k, d), chave x; busca(k, d), item associado a chave k;
As operações São classificados de acordo com as operações que implementam Estáticos; Somente Busca, e.g ED vetor Semi-estáticos; Inserção e Busca, e.g Hash com endereçamento aberto; Dinâmicos. Todas, e.g árvore de busca, Hash com encadeamento.
TABELAS DE DISPERSÃO (HASH)
Introdução Os métodos de busca visto até momento: buscam informações com base na comparação de suas chaves. algoritmos eficientes consideram os elementos ordenados e tiram proveito disso. O algoritmo mais eficientes tem custo computacional O(log n). A busca baseada em hashing (tabela de dispersão ou espalhamento) é mais eficiente. Na média, é possível encontrar a chave com apenas K COMPARAÇÕES, onde k é beemmm menor que o tamanho do conjunto de chaves.
Introdução Vetores utilizam índices para armazenar as informações. Através do índice as operações sobre vetores são realizadas no tempo O(1)=constante. Vetores Não fornecem mecanismos para calcular o índice a partir de uma informação armazenada. A pesquisa não é O(1). Família 1 José Maria 2 Leila 3 Artur 4 Jolinda 5 Gisela 6 Alciene Família[1] = José Maria Família[3] = Artur Família[2] = Leila Em qual posição está Alciene?
Introdução A forma de resolver o problema de acesso a partir de uma chave, e ainda garantir eficiência, é através do uso de tabelas de dispersão (hash table)
Conceitos Esquema da Tabela Hash K4 K1 K5 K3 K2 Função Hash Tabela Hash
Conceitos h(k 4 ) Conjunto de Chaves Busca Possíveis K 4 K 3 K 5 K 1 K 2 h(k 3 ) h(k 5 ) h(k 1 ) h(k 2 ) Tabela Hash
Conceitos: exemplo Tabela Hash 000.000.001-01 19 143.576.342-23 37 Função de 345.365.768-93 50 Hashing 879.094.345-45 85 999.999.999-99 20 19 123.456.781-00; Fausto Silva; Av. Canal. Nº 45. 20... 37 143.576.342-23; Carla Perez; Rua Celso Oliva. Nº 27.... 50 345.365.768-93; Gugu Liberato; Av. Atlântica. S/N.... 85 879.094.345-45 ; Hebe Camargo; Rua B. Nº 100....
Funções Hash
Funções Hash Uma função de dispersão (função hash) mapeia uma chave de busca para um índice da tabela. O ideal é que a função forneça índices únicos para o conjunto de chaves. A função de Hashing é extremamente importante, pois ela é responsável por distribuir as informações pela Tabela Hash. A implementação da função de Hashing tem influência direta na eficiência das operações da Hash. Quanto melhor for o espalhamento mais eficiênte serão as operações Tipos de Funções Hash Método da Divisão Método da Multiplicação
Propriedades Propriedades de Boas Funções Hash Ser eficientemente avaliada (fácil implementação). Devem espalhar bem as chaves de busca (evitar colisões).
Método da Divisão h (k) = k resto m Potências de 2 deve ser evitada para valores de m. m deve ser um número primo distante de pequenas potências de 2 (m grande). O fator de carga da tabela é um bom parâmetro para iniciar a busca por m.
Método da Divisão Exemplo : k = 10028 m = 5013 (m é o tamanho da tabela) h (10028) = 10028 resto 5013 h (10028) = 2
Método da Divisão Exemplo de Função Hash #define N 101 int hash (int mat) { return (mat%n); }
Método da Multiplicação h(k) = (m * (ka resto 1)) A escolha de m não é Tão relevante; A é uma constante : 0<A<1 Extrair a parte fracionária de ka, ou seja, ka resto 1. Utilizar o piso(floor) do resultado A = 0.6180339887...
Método da Multiplicação Exemplo : k = 123456 m = 1024 A = 0.61803... h(k) = 1024*(123456*0.61803... resto 1) = 1024*(76300,0041151... resto 1) = 1024*0,0041151... = 4.21386... h(k)= 4
Funções de Conversão Conversão de Strings para Inteiros Método da Adição; Método dos 3 primeiros caracteres; Método da ponderação.
Método da Adição Os valores dos caracteres da string correspondentes na tabela ASCII são somados. A chave é o resultado dessa soma.
Método da Adição Exemplo : String = aed2 m = 256 ( tamanho da tabela) aed2 = 97 + 101 + 100 + 50 (valores dos caracteres na tabela ASCII) h (348) = 348 resto 256 = 92
Método dos 3 primeiros caracteres h(k)= (chave[0]*b 0 + chave[1]*b 1 + chave[2]*b 2 ) resto m m é o tamanho da tabela chave[ ] são os caracteres da string B um base qualquer
Método dos 3 primeiros caracteres Exemplo : String = Joseph M=10007 ( tamanho da tabela) B=53 h(joseph) = (74*1 +111* 53 +115 *2809) resto M = 8768
Método da Ponderação N K= i=1 chave[i] p[i ] onde, n é o número de caracteres da chave; chave[i] corresponde à representação ASCII do i-ésimo caractere da chave. p[i] é um inteiro de um conjunto de pesos gerados de forma aleatória.
Método da Ponderação Exemplo : String = Joseph M=10007 ( tamanho da tabela) pesos[] = {102, 15, 151, 32, 89, 501, 21, 70} h(joseph) = (74*102 +111*15 +115*151 + 101*32+112*89 + 104*501 ) resto M = 1819
Hashing Perfeito
Hashing Perfeito Característica: Para quaisquer chaves x e y diferentes e pertencentes a A, a função utilizada fornece saídas diferentes
Hashing Perfeito: Exemplo Como construir a Tabela Hash para armazenar as informações dos alunos de uma determinada turma de um curso específico? Identificando as partes significativas da chave. Analisando a chave: Desconsiderando o último dígito (controle), temos outros dígitos com significados especiais:
Hashing Perfeito Portanto, podemos considerar no cálculo de endereço parte do número da matrícula. Esta parte mostra a dimensão que a Tabela Hash deverá ter. Dimensionando a tabela com 100 elementos, qual a função que aplicada sobre matrículas de alunos retorna os índices dessa tabela? R: Depende qual é a turma e o curso específico dos alunos que devem ser armazenados.
Hashing Perfeito Supondo que a turma seja do 2º semestre de 2011 (código 112) e do curso de Corte e Costura (código 35). Qual seria a função de hashing perfeito!? #define N 100 int h(int mat) { return (mat 1123500)%N; }
Hashing Imperfeito
Hashing Imperfeito Características: Existem chaves x e y diferentes e pertencentes a A, onde a função Hash utilizada fornece saídas iguais;
Hashing Imperfeito Suponha que queiramos armazenar as seguintes chaves: C, H, A, V, E e S em um vetor de P = 7 posições (0..6) conforme a seguinte função h(k) = ascii(k)%p. Tabela ASCII: C (67); H (72); A (65); V (86); E (69) e S (83).
Hashing Imperfeito
Hashing Imperfeito Se aumentássemos o tamanho da tabela para P=13 (0..12) C = 67 = 2 H = 72 = 7 A = 65 = 0 V = 86 = 8 E = 69 = 4 S = 83 = 5
Hashing Imperfeito Se aumentássemos o tamanho da tabela para P=14 (0..13) C = 67 = 11 H = 72 = 2 A = 65 = 9 V = 86 = 2 E = 69 =13 S = 83 = 13
Hashing Imperfeito Conclusões Escolher o tamanho da tabela é fundamental; Uma tabela mau dimensionada pode gera um grande número de colisões; Não existe formula perfeita mas existe boas práticas
Tratamento de Colisões
Colisões Colisão é o mapeamento de duas (ou mais) chaves para um mesmo posição no vetor. Colisão 11 1 Um bom método de resolução de colisões é essencial, pois não importa a qualidade da função de hashing, colisões são sempre muito prováveis de acontecer. Métodos para o tratamento de colisões: Encadeamento Direto (chaining); Endereçamento aberto (open adressing).
Colisões Encadeamento Direto (chaining) Armazena em listas encadeadas as chaves que sofreram colisão. 10 20 30 4 14 6 12 Tabela Hash 25
Colisões Encadeamento Direto (Chaining) Vantagens: Número ilimitado de elementos e colisões; Não é necessário prever antecipadamente a quantidade de elementos a serem inseridos. Desvantagens: Devido ao número ilimitado de elementos que podem ser inseridos, o desempenho da tabela hash fica prejudicado.
Colisões Endereçamento Aberto (open addressing) Neste método as chaves que sofreram colisão são inseridas na própria tabela. Algumas Técnicas Linear Probing Quadratic Probing Double Hashing
Colisões Linear Probing O valor do índice correspondente a chave que sofreu colisão é incrementado até que uma posição disponível seja encontrada, nova_posição=(h(x)+i mod M). 11 Colisão h(x)+i Probing 1 1 11 5 Tabela hash 5 Tabela após a aplicação de linear probing
Colisões Linear Probing Vantagens Método simples e fácil de implementar, que pode gerar bons resultados. Desvantagens Faz surgir o fenômeno Clustering. 21 Colisão Probing h(x)+1 1 11 3 5 21 Colisão Probing h(x)+2 1 11 3 5 21 Colisão Probing h(x)+3 1 11 3 5 1 11 3 21 5
Colisões Resultado final da Tabela Hash
Quadratic Probing Colisões Comportamento parecido com Linear Probing, só que agora, o incremento é quadrático, nova_posição= (h(x) + i 2 mod M) 21 Colisão Probing h(x) + 1 i=1; 1 2 21 Colisão Probing h(x) + 4 i=2; 1 2 2 1 Tabela Hash Tabela Hash 21 Tabela após a aplicação de quadratic probing
Colisões Quadratic Probing Vantagens É uma alternativa ao linear probing, pois evita o clustering primário. Desvantagens Poderá surgir o clustering secundário, no entanto, este é menos severo que o primário.
Colisões Double Hashing Utiliza duas funções hashing para tratar a colisão, a primeira é a mesma utilizada para o mapeamento da chave e a segunda é uma espécie de função incremento, nova_posição= (h(x)+ig(x) mod m). x=21; m=5; h(x)= x mod m; g(x)= 2+(x mod (m - 2)); nova_posição=h(x) + g(x). Calculando: h(x)= 21 mod 5 = 1; g(x)= 2+(21 mod (5-2)) = 2; nova_posição=1 + 2 = 3 mod 5 = 3. 0 21 Colisão 1 1 1 1 Probing g(x)+h(x) 2 3 4 Tabela Hash 0 2 3 4 21 Tabela após a aplicação de Double Hashing
Colisões Double Hashing Vantagens: É uma técnica eficiente, que nos permite a livre escolha da função incremento. Desvantagens: Maior nível de complexidade; Se a função incremento for mal escolhida, ela nunca percorrerá todos os espaços da tabela.