目次
1.優れたハッシュ関数
ハッシュテーブルを作成する前に、データをハッシュするためのハッシュ関数が必要です。
では、このハッシュ関数をどのように実装するのでしょうか?ハッシュテーブルを理解するための以前のブログ[JSデータ構造]によると、ハッシュテーブルとは何か、なぜハッシュ関数を設計する必要があるのかはすでに理解しています。
実際、それは2つの目標を達成することです。
- すばやく計算してhashCodeをすばやく取得する機能
- 要素をハッシュテーブルに均等に分散させます。
1.累乗の連続乗算
前述のデータストレージの場合、1つの方法は、乗算の力を使用してhashCodeを取得することです。
与える= 7 * 27 ^ 3 + 9 * 27 ^ 2 + 22 * 27 + 5 = 144941
このように、これは実際には多項式であり、次のように減らすことができます。
ここでの乗算の数は次のとおりです。n+(n-1)+ ... + 1 = n(n + 1)/ 2回
追加回数はN回です。
得られる時間計算量は(N ^ 2 + N)/ 2であり、これはO(N ^ 2)です。
2.ホルネルの法則(秦九霞アルゴリズム)
ホルネルの法則は多項式の最適化であり、乗算の数が減り、hashCodeをすばやく取得できるようになります。これは、次の形式に変換されます。
例として挙げてください
ここでの乗算の回数は次のとおりです。N回。
追加回数はN回です。
得られる時間計算量は(N + N)またはO(N)です。
したがって、ホルネルの法則を使用すると、効率が大幅に向上し、計算時間が短縮されます。
3.一様分布を実現する方法。
ハッシュテーブルを設計するとき、同じ添え字値へのマッピングを処理するための2つの方法がすでにあります。つまり、競合を解決するために、1つはチェーンアドレス方式で、もう1つはオープンアドレス方式です。
方法に関係なく、データをハッシュテーブルに均等に分散させることをお勧めします。
したがって、定数を使用する場合は、素数を使用する必要があります
1.ハッシュテーブルの長さ。
2. N乗の底(37がよく使用されます)。
素数は非常に重要です。テーブルの長さが10(添え字の値は0〜9)であると仮定します。
特定のキーワードが添え字値が0、ステップサイズが5の位置にマップされると、探索のシーケンスは0-5-0-5になり、サイクルが続行されます。
テーブルの長さが11の場合、探索されるシーケンスは0-5-10-4-9-3-8-2-7-1-6であるため、ループは発生せず、データは次のようになります。ハッシュテーブル内で均等に分散されます。
次に、ハッシュ関数を実装します
ハッシュ関数の設計
1.文字列を比較的大きな数値に変換して、hashCodeを取得します。
2.この多数のhashCodeを配列サイズの範囲に圧縮します。
2つのパラメータを渡す必要があります。1つは文字列で、もう1つはハッシュテーブルの長さです。
function hashFunc(str, size){
//定义一个变量来存储hashCode
var hashCode = 0;
// 利用霍纳法则计算出hashCode的值
// give -> Unicode编码
for (var i = 0; i < str.length; i++) {
hashCode = 37 * hashCode + str.charCodeAt(i);
}
// 利用hashCode与哈希表的长度取余得到下标值
var index = hashCode % size;
return index;
}
テストコード:
//测试
alert(hashFunc('abc', 7)); // 4
alert(hashFunc('cla', 7)); // 2
alert(hashFunc('nbr', 7)); // 1
alert(hashFunc('kba', 7)); // 0
概要:優れたハッシュ関数は、データをできるだけ早くさまざまな場所にマップすることです。