Uma boa maneira de examinar as tabelas de hash é como uma tabela de pesquisa com um intervalo infinito de índices (bem, não muito infinitos, você ainda está limitado pelo limite de valor da chave que está usando).
Digamos que você esteja tentando armazenar alguns valores específicos de sqrt (x) em uma tabela de pesquisa em que X é um número inteiro, seria algo como isto:
[1] = 1
[3] = 1.732
[10000] = 100
Isso resulta em um enraizamento quadrado muito barato, pois, em vez do cálculo expencive, você pode simplesmente buscar o valor da matriz. No entanto, é um uso muito ineficiente da memória porque [2] e [4 - 9999] estão vazios.
Para o resgate, vem a função hash, o objetivo de uma função hash nesse contexto é transformar o índice em algo que realmente se encaixa em uma matriz de tamanho razoável; portanto, por exemplo, isso pode ser feito:
(1) = [5] = 1
(3) = [2] = 1.732
(10000) = [3] = 100
agora todos os três valores se encaixam em uma matriz do tamanho de 6.
Como a função hash consegue isso? A função hash mais básica é (Index% ArraySize), o operador módulo divide o índice que você escolheu pelo tamanho da matriz e fornece o restante, sempre menor do que o tamanho da matriz.
Mas e se vários índices hash para o mesmo resultado? Isso é chamado de colisão de hash e existem diferentes maneiras de lidar com isso. O mais simples deles é armazenar cada valor junto com seu Índice original na matriz, se esse slot da matriz for obtido, avance 1 até que um slot vazio seja encontrado. Ao recuperar o valor, vá para o local indicado pela função hash e faça um loop pelos elementos até encontrar aquele com índice original adequado.
É por isso que uma boa função de hash também é ótima para dispersar os dados, de modo que, se os índices recebidos são seqüenciais ou aleatórios, o resultado do hash deve ser o mais amplamente possível, para manter o custo de acessar dados relativamente constante.
É claro que quanto maior a matriz subjacente, menos colisões você terá, portanto é uma troca entre velocidade e eficiência de tamanho. As tabelas de hash modernas geralmente enchem até ~ 70% e têm menos de 10 colisões por acesso. Juntamente com a função hash, isso significa que cada busca de dados custa aproximadamente 20 ciclos, o que é (para alguns propósitos) um bom compromisso entre velocidade (tabela de pesquisa) e eficiência (lista).
hash % table size
deveria ser distribuído uniformemente, não o hash em si.