ハッシュ検索の概念:ハッシュ検索:レコードのストレージアドレスとそのキーの間に明確な対応を確立します。比較せずに、チェックした要素の検索方法を1回のアクセスで取得できます。
ハッシュ関数:記録されたキーと記録されたストレージアドレスの間に確立された対応する関係は、ハッシュ関数と呼ばれます。
ハッシュテーブル:ハッシュ関数を適用し、レコードのキーでテーブルに記録されているアドレスを判別し、このアドレスにレコードを入れます。このようにして形成されたテーブルをハッシュテーブルと呼びます。
ハッシュ関数を使用して検索するプロセスは、ハッシュ検索と呼ばれます。
競合:さまざまなキーワードki、kjの場合。ki!= kjの場合、ただしH(ki)= H(kj)現象。
ハッシュ関数の設計要件:シンプルで、結果を短時間で計算できる必要があります。そして、すべてのキーワードを保存できます。
一般的に、ハッシュ関数の設計として、余りを分割して残す方法を使用します。つまり、H(key)= key%p(p <= m、mはテーブルの長さ、pはm以下の素数、または20未満の素因数を含まない)です。この設計は次のとおりです。競合の可能性を減らします。
たとえば、次の一連のキーワードがあります。
12 39 18 24 33 21 ,若p = 9,则他们对应的哈希函数值为:
3 3 0 6 6 3
12、39、21の間で競合が発生し、24と33の間で競合が発生します。対立の可能性が高まります。
残りの方法に加えて、競合現象に対処するため。39、24、33、21を配置するルールを設定する必要があります。一般的に、次のルールがあります
。1。オープンアドレス法。
2.再ハッシュ。
3.チェーンアドレス方式。
オープンアドレス方式:
競合するアドレスのアドレスシーケンスを取得しますH(key):H0、H1 ... HS
Hi = [H(key)+ di]%m、ここでmはハッシュテーブルの長さです。
diが1、2、3 ... m-1の場合、線形検出および再ハッシュと呼ばれ
ます。diが1、-1,4、-4、9、-9、25 ...の場合、二次検出および再散乱と呼ばれます。列
diが乱数をとる場合、それは疑似ランダム検出および再ハッシュと呼ばれます。
キーワードセットが{19,1,23,14,55,68,11,82,36}、m = 11 [テーブル長]であり
、線形検出とハッシュを使用すると、最終結果は次のようになります。
0 1 2 3 4 5 6 7 8 9 10
55 1 23 14 68 11 82 36 19
查找次数 1 1 2 1 3 6 2 5 1
2つの検出とハッシュを使用すると、最終結果は次のようになります。
0 1 2 3 4 5 6 7 8 9 10
55 1 23 14 36 82 68 19 11
疑似乱数とは、乱数を生成してから検出することです。原理は上記の2つの方法と似ているので、繰り返しません。
チェーンアドレス方式:
同じリンクリスト内の同じハッシュアドレスを持つすべてのレコードをリンクします。上記のキーワードセットを再度想定します。テーブルの後に挿入する方法を使用します。
テーブルヘッダーを挿入する方法:一般的に、テーブルの後に挿入する方法を
検索する必要があり、テーブルヘッダーの挿入は不要であるため、テーブルヘッダーの挿入方法が一般的に採用されます。時間の消費を減らすために
ハッシュ関数がモジュロのキーワードであると仮定すると、ハッシュテーブルはチェーンアドレス方式を使用して競合を解決します。以下に、アルゴリズムの実装を示します。
// 链
class List {
Node head;
}
// 链中结点
class Node {
int data;
Node next;
}
// 用于创建哈希链表
public static List[] createHash(int[] a) {
List[] lists = new List[11];
for (int i = 0; i < lists.length; i++) {
lists[i] = new List();
lists[i].head = new Node();
}
for (int i = 0; i < a.length; i++) {
int model = a[i] % 11;
Node next = new Node();
next.data = a[i];
Node head = lists[model].head;
Node node = head.next;
next.next = node;
head.next = next;
}
return lists;
}
// 查找关键字,返回查找次数
public static int findKey(List[] lists, int key) {
int index = 0;
for (int i = 0; i < lists.length; i++) {
Node head = lists[i].head;
Node next = head.next;
while (next != null) {
if(next.data == key)
return index;
index ++;
next = next.next;
}
}
return -1;
}
int[] a = new int[] { 19, 1, 23, 14, 55, 68, 11, 82, 36 };
int key = 55;
List[] lists = createHash(a);
System.out.println("哈希表内容为:");
for (int i = 0; i < lists.length; i++) {
Node head = lists[i].head;
Node next = head.next;
while (next != null) {
System.out.print(next.data + "->");
next = next.next;
}
System.out.println();
}
int position = findKey(lists, key);
System.out.println("查找次数为:" + position);
プログラムの実行結果:
哈希表内容为:
11->55->
23->1->
68->
36->14->
82->
19->
查找次数为:1