@@ -6,6 +6,27 @@ import LinkedList from '../linked-list/LinkedList';
6
6
// are being handled.
7
7
const defaultHashTableSize = 32 ;
8
8
9
+ // This is the table used for the Pearson hashing.
10
+ // Which contains shuffled number from 0 to 255.
11
+ const table = [
12
+ 84 , 124 , 126 , 180 , 160 , 221 , 178 , 97 , 71 , 13 , 102 , 167 , 209 , 153 , 232 , 237 ,
13
+ 243 , 24 , 205 , 228 , 182 , 83 , 111 , 245 , 86 , 99 , 59 , 26 , 172 , 225 , 9 , 94 ,
14
+ 37 , 179 , 138 , 250 , 154 , 142 , 132 , 36 , 134 , 233 , 188 , 100 , 29 , 57 , 161 , 17 ,
15
+ 41 , 136 , 198 , 61 , 241 , 46 , 201 , 137 , 214 , 10 , 45 , 109 , 145 , 204 , 15 , 119 ,
16
+ 21 , 16 , 252 , 170 , 47 , 12 , 95 , 246 , 249 , 116 , 7 , 64 , 149 , 219 , 171 , 120 ,
17
+ 212 , 216 , 80 , 74 , 186 , 192 , 210 , 190 , 85 , 78 , 196 , 181 , 150 , 110 , 176 , 127 ,
18
+ 140 , 22 , 98 , 82 , 18 , 53 , 230 , 240 , 139 , 62 , 70 , 151 , 157 , 159 , 213 , 207 ,
19
+ 56 , 81 , 147 , 168 , 49 , 229 , 189 , 235 , 152 , 130 , 222 , 215 , 141 , 6 , 175 , 2 ,
20
+ 244 , 28 , 224 , 96 , 91 , 27 , 129 , 227 , 199 , 251 , 69 , 242 , 223 , 158 , 8 , 23 ,
21
+ 19 , 31 , 236 , 25 , 68 , 254 , 112 , 247 , 208 , 148 , 38 , 114 , 40 , 55 , 88 , 231 ,
22
+ 32 , 93 , 163 , 253 , 90 , 30 , 89 , 146 , 113 , 200 , 177 , 101 , 135 , 169 , 128 , 48 ,
23
+ 174 , 66 , 4 , 155 , 14 , 166 , 60 , 193 , 162 , 0 , 58 , 79 , 92 , 239 , 72 , 203 ,
24
+ 123 , 115 , 67 , 217 , 106 , 52 , 173 , 20 , 35 , 50 , 5 , 44 , 11 , 143 , 206 , 73 ,
25
+ 42 , 34 , 75 , 131 , 184 , 220 , 125 , 156 , 202 , 238 , 164 , 103 , 77 , 248 , 195 , 183 ,
26
+ 211 , 65 , 226 , 105 , 43 , 191 , 3 , 54 , 234 , 187 , 194 , 117 , 121 , 107 , 1 , 218 ,
27
+ 185 , 76 , 133 , 33 , 39 , 255 , 197 , 63 , 51 , 144 , 122 , 87 , 104 , 118 , 165 , 108 ,
28
+ ] ;
29
+
9
30
export default class HashTable {
10
31
/**
11
32
* @param {number } hashTableSize
@@ -25,20 +46,32 @@ export default class HashTable {
25
46
* @return {number }
26
47
*/
27
48
hash ( key ) {
28
- // For simplicity reasons we will just use character codes sum of all characters of the key
29
- // to calculate the hash.
49
+ // Using Pearson hashing algorithm to generate the hash number.
30
50
//
31
- // But you may also use more sophisticated approaches like polynomial string hash to reduce the
51
+ // But you may also use other approaches like polynomial string hash to reduce the
32
52
// number of collisions:
33
53
//
34
54
// hash = charCodeAt(0) * PRIME^(n-1) + charCodeAt(1) * PRIME^(n-2) + ... + charCodeAt(n-1)
35
55
//
36
56
// where charCodeAt(i) is the i-th character code of the key, n is the length of the key and
37
57
// PRIME is just any prime number like 31.
38
- const hash = Array . from ( key ) . reduce (
39
- ( hashAccumulator , keySymbol ) => ( hashAccumulator + keySymbol . charCodeAt ( 0 ) ) ,
40
- 0 ,
41
- ) ;
58
+ let hash = 0 ;
59
+
60
+ // Produce a 32-bits hash number.
61
+ for ( let i = 0 ; i < 4 ; i += 1 ) {
62
+ // charCodeAt may return number from 0 to 65536,
63
+ // should remap to range 0 to 255.
64
+ let hashPerRound = table [ ( key . charCodeAt ( 0 ) + i ) % 256 ] ;
65
+ for ( let j = 1 ; j < key . length ; j += 1 ) {
66
+ hashPerRound = table [ hashPerRound ^ ( key . charCodeAt ( j ) % 256 ) ] ;
67
+ }
68
+
69
+ // Left shift by 8-bits and OR the per-rounded hash.
70
+ hash = ( hash << 8 ) | hashPerRound ;
71
+ }
72
+
73
+ // Unsigned right shift to avoid negative number.
74
+ hash >>>= 1 ;
42
75
43
76
// Reduce hash number so it would fit hash table size.
44
77
return hash % this . buckets . length ;
0 commit comments