Il racconto che le tabelle di hash vengono ammortizzate Θ ( 1 )è una bugia una semplificazione eccessiva.
Questo è vero solo se:
- La quantità di dati di hash per articolo è banale rispetto al numero di K eys e la velocità di hash di un K ey è alta -K.
- Il numero di C ollisions è piccolo -c.
- Noi non prendiamo in considerazione il tempo necessario per R esize tabella hash -r.
Stringhe di grandi dimensioni per l'hash
Se il primo presupposto è falso, il tempo di esecuzione aumenteràΘ ( k ).
Questo è sicuramente vero per le stringhe di grandi dimensioni, ma per le stringhe di grandi dimensioni un semplice confronto avrebbe anche un tempo di esecuzione diΘ ( k ). Quindi un hash non è asintoticamente più lento, sebbene l'hash sia sempre più lento di un semplice confronto, perché il confronto ha una rinuncia anticipata ergoO ( 1 ), Ω ( k ) e l'hash deve sempre eseguire l'hashing della stringa completa O ( k ), Ω ( k ).
Si noti che i numeri interi crescono molto lentamente. 8 byte possono memorizzare valori fino a1018; 8 byte è una quantità banale di hash.
Se vuoi conservare le origini, pensa a loro come a stringhe.
Algoritmo di hash lento
Se l'hashing di spesa di importo non è banale rispetto alla memorizzazione dei dati, ovviamente ilΘ ( 1 )l'ipotesi diventa insostenibile.
A meno che non venga utilizzato un hash crittografico, questo non dovrebbe essere un problema.
Ciò che conta è quello n > > K. Finché ciò valeΘ ( 1 ) è una buona dichiarazione.
Molte collisioni
Se la funzione di hashing è scarsa, o la tabella hash è piccola, o la dimensione della tabella hash è scomoda, le collisioni saranno frequenti e il tempo di esecuzione andrà aO ( l o g( n ) ).
La funzione di hashing dovrebbe essere scelta in modo che le collisioni siano rare pur essendo il più veloci possibile, in caso di dubbio optare per un minor numero di collisioni a spese di hashing più lento.
Una regola empirica è che la tabella di hashing deve essere sempre piena per meno del 75%.
E la dimensione della tabella di hashing non dovrebbe avere alcuna correlazione con la funzione di hashing.
Spesso le dimensioni della tabella di hashing sono (relativamente) prime.
Ridimensionamento della tabella hash
Poiché una tabella hash quasi piena genererà troppe collisioni e una tabella hash grande (vuota) è uno spreco di spazio, molte implementazioni consentono alla tabella hash di crescere (e ridursi!) Secondo necessità.
La crescita di una tabella può comportare una copia completa di tutti gli elementi (e possibilmente un rimpasto), poiché l'archiviazione deve essere continua per motivi di prestazioni.
Solo in casi patologici il ridimensionamento della tabella hash sarà un problema, quindi i ridimensionamenti (costosi ma rari) vengono ammortizzati in molte chiamate.
Tempo di esecuzione
Quindi il vero tempo di esecuzione di una tabella hash èΘ ( k c r ).
Ciascuno diK, c, r in media si presume che sia una (piccola) costante nel tempo di esecuzione ammortizzato e quindi lo diciamo Θ ( 1 ) è una buona dichiarazione.
Per tornare alle tue domande
Per favore, scusami per parafrasare, ho cercato di estrarre diversi insiemi di significati, sentiti libero di commentare se mi sono perso alcuni
Sembra che tu sia preoccupato per la lunghezza dell'output della funzione hash. Chiamiamo questom (n è generalmente considerato il numero di elementi da sottoporre a hash). m sarà l o g( n )perché m deve identificare in modo univoco una voce nella tabella hash.
Ciò significa che m cresce molto lentamente. A 64 bit il numero di voci della tabella hash occuperà una parte considerevole della RAM disponibile in tutto il mondo. A 128 bit supererà di gran lunga la memoria disponibile su disco sul pianeta terra.
Produrre un hash a 128 bit non è molto più difficile di un hash a 32 bit, quindi no , il tempo di creare un hash non èO ( m ) (o O ( l o g( n ) ) se vorrai).
La funzione hash sta passando l o g( n ) ci vorranno pezzi di elementi Θ (log( n ) ) tempo.
Ma la funzione hash non passal o g( n )pezzi di elementi.
Per un articolo (!!), tuttavia, vale soloO ( k )dati.
Anche la lunghezza dell'input (k) non ha alcuna relazione con il numero di elementi. Questo è importante, perché alcuni algoritmi non di hashing devono esaminare molti elementi nella raccolta per trovare un elemento (non) corrispondente.
La tabella hash esegue in media solo 1 o 2 confronti per elemento considerato prima di giungere a una conclusione.
Perché le tabelle hash sono efficienti per la memorizzazione di elementi a lunghezza variabile?
Perché indipendentemente dalla lunghezza dell'input (K) la lunghezza dell'uscita (m) è sempre lo stesso, le collisioni sono rare e il tempo di ricerca è costante.
Tuttavia, quando la lunghezza della chiaveK cresce rispetto al numero di elementi nella tabella hash (n) la storia cambia ...
Perché le tabelle hash sono efficienti per l'archiviazione di stringhe di grandi dimensioni?
Le tabelle hash non sono molto efficienti per stringhe molto grandi.
Se n o t n > > k (ovvero la dimensione dell'input è piuttosto grande rispetto al numero di elementi nella tabella hash) quindi non possiamo più dire che l'hash ha un tempo di esecuzione costante, ma dobbiamo passare a un tempo di esecuzione di Θ ( k )soprattutto perché non è possibile uscire presto. È necessario per l'hash della chiave completa. Se stai memorizzando solo un numero limitato di articoli, potresti essere molto meglio usando una memoria ordinata, perché durante il confrontok 1 ≠ k 2 puoi annullare l'iscrizione non appena viene rilevata una differenza.
Tuttavia, se conosci i tuoi dati, puoi scegliere di non eseguire l'hashing della chiave completa, ma solo la parte volatile (nota o presunta), ripristinando il Θ ( 1 ) proprietà mantenendo sotto controllo le collisioni.
Costanti nascoste
Come tutti dovrebbero sapereΘ ( 1 )significa semplicemente che il tempo per elemento elaborato è una costante. Questa costante è un po 'più grande per l'hashing che per un semplice confronto.
Per le tabelle piccole una ricerca binaria sarà più veloce di una ricerca hash, perché ad esempio 10 confronti binari potrebbero benissimo essere più veloci di un singolo hash.
Per piccoli insiemi di dati dovrebbero essere prese in considerazione alternative alle tabelle hash.
È su grandi set di dati che le tabelle hash brillano davvero.