O documento descreve tabelas hash, que mapeiam chaves para valores através de uma função hash. Colisões ocorrem quando chaves diferentes mapeiam para o mesmo índice. Várias estratégias tratam colisões, incluindo usar a primeira posição livre, uma segunda função hash, ou listas encadeadas nos índices. Funções hash devem espalhar chaves e serem eficientemente avaliadas para minimizar colisões.
O documento descreve tabelas hash, que mapeiam chaves para valores através de uma função hash. Colisões ocorrem quando chaves diferentes mapeiam para o mesmo índice. Várias estratégias tratam colisões, incluindo usar a primeira posição livre, uma segunda função hash, ou listas encadeadas nos índices. Funções hash devem espalhar chaves e serem eficientemente avaliadas para minimizar colisões.
O documento descreve tabelas hash, que mapeiam chaves para valores através de uma função hash. Colisões ocorrem quando chaves diferentes mapeiam para o mesmo índice. Várias estratégias tratam colisões, incluindo usar a primeira posição livre, uma segunda função hash, ou listas encadeadas nos índices. Funções hash devem espalhar chaves e serem eficientemente avaliadas para minimizar colisões.
Tabelas de dispersão: conceito, funcionamento, funções de dispersão e
tratamento de colisões. Uma Tabela Hash, também conhecida como tabela de dispersão é uma estrutura de dados especial, que associa chaves e valores. Seu objetivo é a partir de uma chave simples, fazer uma busca rápida e obter o valor desejado. Através da aplicação de uma função conveniente, a chave é transformada em um endereço de uma tabela. A idéia central do Hash é utilizar uma função, aplicada sobre parte da informação (chave), para retornar o índice onde a informação deve ou deveria estar armazenada. Um exemplo onde pode-se usar tabela hash, seria em um numero de matricula de um aluno, no qual os números possuem significados especias, como: 9711234–4 97 o ano de ingresso, 1 período de ingresso, 1234 indicadores seqüenciais, e 4 digito de controle. é comum existirem vários alunos com o mesmo ano e período de ingresso. Portanto, esses três primeiros dígitos não são bons candidatos para identificar individualmente cada aluno. os números sequenciais mais significativos são os últimos, pois o dígito que representa a unidade varia mais do que o dígito que representa o milhar. Desta forma, podemos usar um número de matrícula parcial, de acordo com a dimensão que queremos que tenha nossa tabela (ou nosso vetor). Para acessarmos o nome do aluno matriculado, usamos como índice da tabela apenas os dois últimos dígitos da matricula. O problema que surge é que provavelmente existirão dois ou mais alunos da turma que apresentarão os mesmos últimos dois dígitos no número de matrícula. Dizemos que há uma colisão, pois alunos diferentes são mapeados para o mesmo índice da tabela. A função de dispersão (função de hash) mapeia uma chave de busca num índice da tabela. No exemplo da matricula, adotamos como função de hash a utilização dos dois últimos dígitos do número de matrícula. A implementação dessa função recebe como parâmetro de entrada a chave de busca e retorna um índice da tabela. Uma função de hash deve, sempre que possível, apresentar as seguintes propriedades: Ser eficientemente avaliada: isto é necessário para termos acesso rápido, pois temos que avaliar a função de hash para determinarmos a posição onde o elemento se encontra armazenado na tabela. Espalhar bem as chaves de busca: isto é necessário para minimizarmos as ocorrências de colisões. Como veremos, o tratamento de colisões requer um procedimento adicional para encontrarmos o elemento. Se a função de hash resulta em muitas colisões, perdemos o acesso rápido aos elementos. Um exemplo de função de hash ruim seria usar, como índice da tabela, os dois dígitos iniciais do número de matrícula – todos os alunos iriam ser mapeados para apenas três ou quatro índices da tabela. Para minimizar o número de colisões, a dimensão da tabela deve guardar uma folga em relação ao número de elementos efetivamente armazenados. Como regra empírica, não se deve permitir que a tabela tenha uma taxa de ocupação superior a 75%. Existem diversas estratégias para tratarmos as eventuais colisões que surgem quando duas ou mais chaves de busca são mapeadas para um mesmo índice da tabela de hash. Estratégias para tratamento de colisão: Uso da primeira posição consecutiva livre: simples de implementar tende a concentrar os lugares ocupados na tabela Uso de uma segunda função de dispersão: evita a concentração de posições ocupadas na tabela usa uma segunda função de dispersão para re-posicionar o elemento Uso de listas encadeadas: simples de implementar cada elemento da tabela hash representa um ponteiro para uma lista encadeada No uso da primeira posição consecutiva livre, os elementos que colidem são armazenados em outros índices, ainda não ocupados, da própria tabela. se a função de dispersão mapeia para um índice já ocupado, procuramos o próximo (usando incremento circular) índice livre da tabela para armazenar o novo elemento. os índices da tabela que não têm elementos associados são preenchidos com o valor NULL. Como a ocupação máxima devera ser de 75%, pode-se garantir que sempre existirá uma posição livre na tabela. Para realizar uma operação de busca, suponha que uma chave x for mapeada pela função de hash h para um determinado índice h(x). Procure a ocorrência do elemento a partir de h(x), até que o elemento seja encontrado ou que uma posição vazia seja encontrada. Operação de busca: Entrada: a tabela e a chave de busca Saída: o ponteiro do elemento, se encontrado. NULL, se o elemento não for encontrado. Na Operação de inserção e modificação: Suponha que uma chave x for mapeada pela função de hash h para um determinado índice h(x). Procure a ocorrência do elemento a partir de h(x), até que o elemento seja encontrado ou que uma posição vazia seja encontrada. Se o elemento existir, modifique o seu conteúdo, se não existir, insira um novo na primeira posição livre que encontrar na tabela, a partir do índice mapeado. No Uso de uma segunda função de dispersão, para evitar a concentração de posições ocupadas na tabela, essa estratégia faz uma variação na forma de procurar uma posição livre a fim armazenar o elemento que colidiu. Utilizando uma segunda função hash (h’) procuramos uma posição livre na tabela com incrementos. Dois cuidados devem ser tomados na escolha dessa segunda função de dispersão: primeiro, ela nunca pode retornar zero, pois isso não varia com que o índice fosse incrementado; segundo, de preferência, ela não pode retornar um número divisor da dimensão da tabela, pois isso limitaria a procura de uma posição livre a um sub- conjunto restrito dos índices da tabela. se a dimensão da tabela for um número primo, garante-se automaticamente que o resultado da função não será um divisor. O Uso de listas encadeadas, consiste em fazer com que cada elemento da tabela hash represente um ponteiro para uma lista encadeada. Todos os elementos mapeados para um mesmo índice seriam armazenados na lista encadeada. os índices da tabela que não têm elementos associados representam listas vazias. Com essa estratégia, cada elemento armazenado na tabela será um elemento de uma lista encadeada. Por isso, a estrutura da informação deve prever um ponteiro adicional para o próximo elemento da lista.