Costuma-se dizer que a pesquisa de tabela de hash opera em tempo constante: você calcula o valor do hash, que fornece um índice para uma pesquisa de matriz. No entanto, isso ignora colisões; na pior das hipóteses, todos os itens chegam ao mesmo balde e o tempo de pesquisa se torna linear ( ).
Existem condições nos dados que podem tornar a pesquisa de tabela de hash verdadeiramente ? Isso é apenas em média, ou uma tabela de hash pode ter pesquisa de pior caso?O ( 1 )
Nota: Estou vindo da perspectiva de um programador aqui; quando eu armazeno dados em uma tabela de hash, quase sempre são cadeias de caracteres ou algumas estruturas de dados compostas, e os dados são alterados durante a vida útil da tabela de hash. Portanto, embora eu aprecie respostas sobre hashes perfeitos, eles são fofos, mas engraçados e não são práticos do meu ponto de vista.
Acompanhamento do PS: Para que tipo de dados são as operações da tabela de hash O (1)?
fonte
Respostas:
Existem duas configurações nas quais você pode obter pior caso.O(1)
Se sua configuração for estática, o hash do FKS obterá as garantias pior das hipóteses . Mas, como você indicou, sua configuração não é estática.O(1)
Se você usar hash Cuckoo, as consultas e exclusões serão pior caso, mas a inserção é apenas esperada. O hash do cuco funciona muito bem se você tiver um limite superior no número total de pastilhas e definir o tamanho da tabela para ser aproximadamente 25% maior.O ( 1 )O(1) O(1)
Há mais informações aqui .
fonte
Esta resposta resume partes do TAoCP Vol 3, Ch 6.4.
Suponha que temos um conjunto de valores , dos quais queremos armazenar em uma matriz do tamanho . Empregamos uma função de hash ; tipicamente,. Chamamos o factor de carga de . Aqui, assumiremos o natural ; em cenários práticos, temos , porém, e tem que mapear até nós mesmos.n A m h : V → [ 0 .. M ) M ≪ | V | α = nV n A m h:V→[0..M) M≪|V| Am=Mm≪Mmα=nm A m=M m≪M m
A primeira observação é que, mesmo que tenha características uniformes¹, a probabilidade de dois valores terem o mesmo valor de hash é alta; este é essencialmente um exemplo do infame paradoxo do aniversário . Portanto, geralmente teremos que lidar com conflitos e podemos abandonar a esperança do pior caso de tempo de acesso.O ( 1 )h O(1)
Mas e o caso médio? Vamos supor que todas as chaves de ocorram com a mesma probabilidade. O número médio de entradas marcadas (pesquisa bem-sucedida) resp. (pesquisa malsucedida) depende do método de resolução de conflitos usado.C S n C U n[0..M) CSn CUn
Encadeamento
Cada entrada da matriz contém (um ponteiro para o início) uma lista vinculada. Essa é uma boa idéia, pois o tamanho esperado da lista é pequeno ( ), mesmo que a probabilidade de ter colisões seja alta. No final, obtemos Isso pode ser melhorado um pouco, armazenando as listas (parcial ou completamente) dentro da tabela. C S n ≈1+αnm
Sondagem linear
Ao inserir (resp. Pesquisando um valor) , verifique as posições nesta ordem até uma posição vazia (resp. ) for encontrado. A vantagem é que trabalhamos localmente e sem estruturas de dados secundárias; no entanto, o número médio de acessos diverge de : Para , no entanto, o desempenho é comparável ao encadeamento².v
Hashing Duplo
Semelhante a sondagem linear mas o tamanho do passo de pesquisa é controlada por uma segunda função hash que é coprime para . Nenhuma derivação formal é fornecida, mas observações empíricas sugerem Este método foi adaptado por Brent; sua variante amortiza os custos de inserção com pesquisas mais baratas.M
Observe que a remoção de elementos e a extensão de tabelas tem graus variados de dificuldade para os respectivos métodos.
Bottom line, você tem que escolher uma implementação que se adapte bem aos seus casos de uso típicos. O tempo esperado de acesso em é possível se nem sempre garantido. Dependendo do método usado, manter baixo é essencial; você precisa trocar o tempo de acesso (esperado) versus a sobrecarga de espaço. Uma boa escolha para também é central, obviamente.O(1) α h
1] Como programadores desinformados arbitrariamenteh
burrospodem fornecer , qualquer suposição sobre sua qualidade é um exagero na prática. 2] Observe como isso coincide com as recomendações para o uso de Java .Hashtable
fonte
Uma função hash perfeita pode ser definida como uma função injetiva de um conjunto para um subconjunto dos números inteiros . Se existir uma função de hash perfeita para suas necessidades de dados e armazenamento, você poderá obter facilmente o comportamento . Por exemplo, você pode obter desempenho de uma tabela hash para a seguinte tarefa: dado um array de inteiros e um conjunto de inteiros, determine se contém para cada . Uma etapa de pré-processamento envolveria a criação de uma tabela de hash em , seguida pela verificação de cada elemento de contra ele emS {0,1,2,...,n} O(1) O(1) l S l x x∈S O(|l|) S O(|S|) . No total, este é . Uma implementação ingênua usando pesquisa linear pode ser ; usando a pesquisa binária, é possível executar (observe que esta solução é o espaço , pois a tabela de hash deve mapear números inteiros distintos em para compartimentos distintos.O(|l|+|S|) O(|l||S|) O(log(|l|)|S|) O(|l|) l
EDIT: Para esclarecer como a tabela de hash é gerada em :O(|l|)
A lista contém inteiros a partir de um conjunto finito , possivelmente, com repetições, e . Queremos determinar se está em . Para fazer isso, pré-calculamos uma tabela de hash para elementos de : uma tabela de pesquisa. A tabela de hash codificará uma função . Para definir , inicialmente assumir para todos . Em seguida, varra linearmente os elementos de , configurando . Isso leva tempo el U⊂N S⊆U x∈S l l h:U→{true,false} h h(x)=false x∈U y l h(y)=true O(|l|) O(|U|) espaço.
Observe que minha análise original assumiu que continha pelo menos elementos distintos. Se ele contiver menos elementos distintos (por exemplo, ), o requisito de espaço poderá ser maior (embora não seja mais que ).l O(|U|) O(|1|) O(|U|)
EDIT2: A tabela de hash pode ser armazenada como uma matriz simples. A função hash pode ser a função identidade em . Observe que a função de identidade é trivialmente uma função perfeita de hash. é a tabela de hash e codifica uma função separada. Estou sendo desleixado / confuso em algumas das opções acima, mas tentarei melhorá-lo em breve.U h
fonte
Uma função de hash perfeita resultará em pesquisa de pior caso.O(1)
Além disso, se o número máximo de colisões possível for , pode-se dizer que a consulta à tabela de hash é no pior caso. Se o número esperado de colisões for , a consulta da tabela de hash poderá ser no caso médio.O ( 1 ) O ( 1 ) O ( 1 )O(1) O(1) O(1) O(1)
fonte