データ構造のハッシュ:関数、手法[例付き]
公開: 2021-05-02目次
序章
ハッシュは、データを効率的に検索して配列に格納するという問題を解決するために設計された重要なデータ構造です。 たとえば、20000の番号のリストがあり、そのリストで検索する番号を指定した場合、一致するものが見つかるまでリスト内の各番号をスキャンします。
リスト全体を検索してその特定の番号を見つけるには、かなりの時間がかかります。 この手動スキャンプロセスは、時間がかかるだけでなく、非効率的でもあります。 データ構造にハッシュを使用すると、検索を絞り込んで数秒以内に数を見つけることができます。
このブログでは、ハッシュメソッド、ハッシュテーブル、および例を使用した線形プロービングについて、より深く理解することができます。
データ構造のハッシュとは何ですか?
データ構造のハッシュは、ハッシュ関数を使用してデータの大きなチャンクを小さなテーブルにマッピングする手法です。 メッセージダイジェスト機能とも呼ばれます。 これは、類似したアイテムのコレクションから特定のアイテムを一意に識別する手法です。
ハッシュテーブルを使用して、データを配列形式で格納します。 配列の各値には、一意のインデックス番号が割り当てられています。 ハッシュテーブルは、配列形式で格納された値ごとにこれらの一意のインデックス番号を生成する手法を使用します。 この手法はハッシュ手法と呼ばれます。
データを見つけるのではなく、目的のアイテムのインデックスを見つけるだけで済みます。 インデックスを使用すると、リスト全体をすばやくスキャンして、必要なアイテムを取得できます。 インデックス付けは、特定の場所にデータを挿入する必要がある場合の操作の挿入にも役立ちます。 テーブルの大きさに関係なく、数秒でデータを更新および取得できます。
データ構造のハッシュは2段階のプロセスです。
- ハッシュ関数は、アイテムを小さな整数またはハッシュ値に変換します。 この整数は、元のデータを格納するためのインデックスとして使用されます。
- データをハッシュテーブルに保存します。 ハッシュキーを使用して、データをすばやく見つけることができます。
データ構造でのハッシュの例
以下は、データ構造でのハッシュの実際の例です–
- 学校では、教師が各生徒に一意のロール番号を割り当てます。 後で、教師はそのロール番号を使用して、その生徒に関する情報を取得します。
- 図書館には無数の本があります。 図書館員は、各本に一意の番号を割り当てます。 この一意の番号は、本棚上の本の位置を識別するのに役立ちます。
チェックアウト:データ構造での並べ替え
ハッシュ関数
データ構造のハッシュ関数は、任意のサイズのデータを固定サイズのデータにマップします。 次の値を返します:小さな整数値(ハッシュ値とも呼ばれます)、ハッシュコード、およびハッシュ合計。
hash = hashfunc(key)
インデックス=ハッシュ%array_size
has関数は、次の要件を満たす必要があります。
- 優れたハッシュ関数は簡単に計算できます。
- 優れたハッシュ関数は、クラスタリングでスタックすることはなく、ハッシュテーブル全体にキーを均等に分散します。
- 優れたハッシュ関数は、2つの要素またはアイテムが同じハッシュ値に割り当てられた場合の衝突を回避します。
ハッシュ表
データ構造のハッシュでは、ハッシュテーブルを使用してキーと値のペアを格納します。 次に、ハッシュテーブルはハッシュ関数を使用してインデックスを生成します。 ハッシュは、この一意のインデックスを使用して、挿入、更新、および検索操作を実行します。
データ構造のハッシュはどのように機能しますか?
ハッシュでは、ハッシュ関数は文字列または数値を小さな整数値にマップします。 ハッシュテーブルは、ハッシュ関数を使用してリストからアイテムを取得します。 ハッシュ手法の目的は、データをアレイ全体に均等に分散することです。 ハッシュは、すべての要素に一意のキーを割り当てます。 ハッシュテーブルはこのキーを使用して、リスト内のデータにアクセスします。
ハッシュテーブルは、データをキーと値のペアで格納します。 キーは、ハッシュ関数への入力として機能します。 次に、ハッシュ関数は、格納されている値ごとに一意のインデックス番号を生成します。 インデックス番号は、そのキーに対応する値を保持します。 ハッシュ関数は、出力として小さな整数値を返します。 ハッシュ関数の出力はハッシュ値と呼ばれます。
例を挙げて、データ構造のハッシュについて理解しましょう。 30個のセルを持つハッシュテーブル内にいくつかのアイテム(キーと値のペアで配置)を格納する必要があると想像してください。
値は次のとおりです。(3,21)(1,72)(40,36)(5,30)(11,44)(15,33)(18,12)(16,80)(38,99)
ハッシュテーブルは次のようになります。
シリアルナンバー | 鍵 | ハッシュ | 配列インデックス |
1 | 3 | 3%30 = 3 | 3 |
2 | 1 | 1%30 = 1 | 1 |
3 | 40 | 40%30 = 10 | 10 |
4 | 5 | 5%30 = 5 | 5 |
5 | 11 | 11%30 = 11 | 11 |
6 | 15 | 15%30 = 15 | 15 |
7 | 18 | 18%30 = 18 | 18 |
8 | 16 | 16%30 = 16 | 16 |
9 | 38 | 38%30 = 8 | 8 |
また読む: Pythonのデータ構造のタイプ
衝突解決技術
2つのキーにハッシュテーブルで同じインデックス番号が割り当てられている場合、データ構造のハッシュは衝突に陥ります。 ハッシュテーブルの各インデックスは1つの値のみを格納することになっているため、衝突によって問題が発生します。 データ構造のハッシュでは、いくつかの衝突解決手法を使用して、ハッシュテーブルのパフォーマンスを管理します。
線形プロービング
データ構造をハッシュすると、値を格納するためにすでに占有されている配列インデックスが生成されます。 このような場合、ハッシュは検索操作を実行し、次の空のセルを線形にプローブします。
線形プロービングの例
サイズ30のハッシュテーブル内にいくつかのアイテムを格納するように求められたとします。アイテムはすでにキーと値のペアの形式で並べ替えられています。 与えられた値は次のとおりです:(3,21)(1,72)(63,36)(5,30)(11,44)(15,33)(18,12)(16,80)(46,99) 。
hash(n)はハッシュ関数を使用して計算されたインデックスであり、Tはテーブルサイズです。 スロットインデックス=(hash(n)%T)がいっぱいの場合、1((hash(n)+ 1)%T)を追加して次のスロットインデックスを探します。 (hash(n)+ 1)%Tもいっぱいの場合は、(hash(n)+ 2)%Tを試します。(hash(n)+ 2)%Tもいっぱいの場合は、(hash( n)+ 3)%T。
ハッシュテーブルは次のようになります。
シリアルナンバー | 鍵 | ハッシュ | 配列インデックス | 線形プロービング後の配列インデックス |
1 | 3 | 3%30 = 3 | 3 | 3 |
2 | 1 | 1%30 = 1 | 1 | 1 |
3 | 63 | 63%30 = 3 | 3 | 4 |
4 | 5 | 5%30 = 5 | 5 | 5 |
5 | 11 | 11%30 = 11 | 11 | 11 |
6 | 15 | 15%30 = 15 | 15 | 15 |
7 | 18 | 18%30 = 18 | 18 | 18 |
8 | 16 | 16%30 = 16 | 16 | 16 |
9 | 46 | 46%30 = 8 | 16 | 17 |
ダブルハッシュ
ダブルハッシュ手法は、2つのハッシュ関数を使用します。 2番目のハッシュ関数は、最初の関数が衝突を引き起こしたときに使用されます。 値を格納するためのオフセットインデックスを提供します。
ダブルハッシュ手法の式は次のとおりです。
(firstHash(key)+ i * secondHash(key))%sizeOfTable
ここで、iはオフセット値です。 このオフセット値は、空のスロットが見つかるまで増分され続けます。
たとえば、h1とh2の2つのハッシュ関数があります。 空のスロットを見つけるには、次の手順を実行する必要があります。
- hash1(key)が空かどうかを確認します。 はいの場合、このスロットに値を保存します。
- hash1(key)が空でない場合は、hash2(key)を使用して別のスロットを見つけます。
- hash1(key)+ hash2(key)が空かどうかを確認します。 はいの場合、このスロットに値を保存します。
- カウンターをインクリメントし続け、空のスロットが見つかるまで、hash1(key)+ 2hash2(key)、hash1(key)+ 3hash2(key)などを繰り返します。
ダブルハッシュの例
サイズ20のハッシュテーブル内にいくつかのアイテムを格納する必要があると想像してください。与えられた値は次のとおりです:(16、8、63、9、27、37、48、5、69、34、1)。
h1(n)= n%20
h2(n)= n%13
nh(n、i)=(h1(n)+ ih2(n))mod 20
n | h(n、i)=(h'(n)+ i 2 )%20 |
16 | I = 0、h(n、0)= 16 |
8 | I = 0、h(n、0)= 8 |
63 | I = 0、h(n、0)= 3 |
9 | I = 0、h(n、0)= 9 |
27 | I = 0、h(n、0)= 7 |
37 | I = 0、h(n、0)= 17 |
48 | I = 0、h(n、0)= 8 I = 0、h(n、1)= 9 I = 0、h(n、2)= 12 |
5 | I = 0、h(n、0)= 5 |
69 | I = 0、h(n、0)= 9 I = 0、h(n、1)= 10 |
34 | I = 0、h(n、0)= 14 |
1 | I = 0、h(n、0)= 1 |
結論
ダブルハッシュは計算コストが高くなりますが、線形プロービング方式よりも高速に次の空きスロットを検索します。 この記事に記載されている例は、説明のみを目的としています。 要件に応じて、上記のステートメントを変更できます。 このブログでは、データ構造におけるハッシュの概念について学びました。
この例を試して、データ構造の知識を強化することができます。 データ構造について詳しく知りたい場合は、フルスタック開発コースのupGradExecutivePGプログラムを確認してください。 このコースは、働く専門家向けに設計されており、トップ企業との厳格なトレーニングと就職を提供します。
ハッシュテーブルとは何ですか?
ハッシュテーブルは、抽象データ型(ADT)を実装するためにコンピュータープログラミングで使用される構造である連想配列の実装です。 抽象データ型では、プログラマーはデータ型の実装の詳細(データがメモリに格納される方法など)について知る必要はなく、データ型で実行できる操作のみを知る必要があります。 ハッシュテーブルは、ハッシュ関数を使用して、バケットまたはスロットの配列へのインデックスを計算します。この配列から、目的の値を見つけることができます。 ハッシュテーブルは、データ構造のようなマップを実装するために使用されます。 ハッシュテーブルは、辞書(pythonのように)、連想配列(phpのように)、javaハッシュテーブルなどを実装するために最近のコンピューターで非常に使用されています。ハッシュテーブルは通常、キーでソートされた値の配列として言語で実装されます。 これにより、データが体系的にメモリに保存されるため、検索および挿入/削除操作が非常に高速になります。
ハッシュ関数のアプリケーションは何ですか?
ハッシュ関数は、暗号化やドキュメントフィンガープリントなど、コンピュータサイエンスのいくつかのアプリケーションで使用されます。 ハッシュ関数の主な目的は、大量の入力を固定長の出力にマップすることです。 暗号化では、メッセージまたはドキュメントが改ざんされていないことを確認するためにハッシュが使用されます。 ドキュメントまたはメッセージが何らかの方法で変更された場合(1文字でも)、ハッシュ値も変更されます。 したがって、特定のハッシュ値を使用してドキュメントまたはメッセージを作成することはほとんど不可能です。
ハッシュの衝突解決手法とは何ですか?
ハッシュの衝突解決手法は、ハッシュの衝突を解決するために使用されます。 衝突解決技術は、連鎖またはオープンアドレス法のいずれかです。 チェーンでは、古い要素を所定の位置に保持し、次に使用可能なスペースに新しい要素を挿入します。 これは衝突解決の簡単な方法ですが、パフォーマンスが低下するという欠点があります。 オープンアドレッシングでは、古い要素を新しい要素に置き換え、古い要素を衝突としてマークします。