データの探索アルゴリズムの一つに**「ハッシュ法」**という手法がありますが、
このハッシュ(探索)法とは
私自身の解釈として、(おおまかでありますが、)
-
探索したいデータをハッシュ関数で計算する
-
ハッシュ値(キー値。アドレスみたなもの?)を出力する。
-
出力したハッシュ値を元に、データ列にあるハッシュ表から直接該当するハッシュ値(キー値)にアクセス(探索)する。
このような感じであると私自身思いますが、つまり、「ハッシュ探索法」は
「出力したハッシュ値を元にデータ列にあるハッシュ表から直接アクセスしてデータを探索する」
ということなんでしょうか?(大雑把ですが・・・)
何か所々解釈が間違っていると思いますが、その解釈でいいのでしょうか?
よろしくお願いします。
(ちなみに掲載されている図はあくまで例であることを御了承いただけばと思います。)
気になる質問をクリップする
クリップした質問は、後からいつでもMYページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
回答4件
0
他の回答者も書いていますが「ハッシュ関数」の衝突を補足します。
ハッシュ関数の出力は衝突する
『世界標準MIT教科書 Python言語によるプログラミングイントロダクション第2版』近代科学社より引用。
『ハッシュ関数は大きな集合から小さな集合への写像である。ハッシュ関数を用いることで、大きな集合の属するキーを小さな集合に属する整数へと変換できる。ハッシュ関数の出力の集合は入力の集合に比べて小さいため、ハッシュ関数は、多対1写像 (many-to-one mapping) を生成する。2つの入力が同一の出力へ写像される場合を衝突 (collision) という。衝突がなるべく起きないようにするには、各出力が均等に発生するような一様分布 (uniform distribution) を作り出すハッシュ関数を考案しなければならない。』
- ハッシュ関数は、多対1写像 (many-to-one mapping)
ミカンとリンゴを入力とすると、同じ値が出力されることがある。
- 2つの入力が同一の出力へ写像される場合を衝突 (collision) という。
一つの指定席に二人(以上)の人が座りたいということが起る。衝突をできるだけ回避するために出力を一様分布にしたい。
ハッシュテーブルの実装
衝突を考えると、配列に格納するために工夫が必要になります。
- 同じハッシュ値のエントリを隣に置く
本来隣は別のハッシュ値の指定席なので、どんどんずれる。空席に出会うまで衝突かどうか線形探索する必要がある。
- 指定席自体を配列や連結リストにして衝突を格納できる構造にする。
質問の図のような単純な配列ではなく、配列の配列や、結合リストの配列にする。
入力のビットの数を数えて偶数なら0奇数なら1というハッシュ関数をつくると出力値は2つ。大量の衝突が起きる。衝突の中からめざす値(リンゴかミカンか、...)を発見するのにリストをさらに線形探索する。このようにハッシュ関数が悪いと非効率。
ハッシュ関数の実装
上の本にはハッシュ関数の実装について書かれていません。以下の本を読んでください。
『世界標準MIT教科書 アルゴリズムインロダクション第3版 第1巻』近代科学社
衝突の起きるハッシュ関数だけでなく、衝突の起きない「完全ハッシュ法」も紹介されています。
ハッシュ関数の応用
パスワード、電子署名など様々な分野で使われています。wikipediaを読んでみましょう。
【追記(2019-04-28)】
キーと値
ハッシュ値(配列の添字)が「キー」と思われているようですが間違いです。キーは「リンゴ」「ミカン」になります。英語の辞書に例えると、英単語が「キー」単語の説明が「値」に相当します。質問の例は「キー」と「値」が同じ辞書です。ハッシュテーブルを「辞書」「連想配列」「ハッシュ」と呼ぶことがあります。
ハッシュテーブルのエントリ
通常は(キー、値)のペアになります。理由は、衝突リストに格納されたエントリを識別するのにキーの同値判定が必要だから。
投稿2019/04/27 10:05
編集2019/04/28 00:30総合スコア1081
0
抽象的な記述なので、なんとも言いがたいですが、おそらく間違っています。
データを格納するテーブルサイズをN
とすると、データ中のキーとなる値(質問の例だと果物名)のハッシュ値を求め、その値に何らかの演算を行って0
~N-1
の添え字を求めます。
テーブルのその添え字の場所に、データを格納します。実際は、データへのポインタを格納すると思いますが。
当然、異なるキー値に対して、添え字の重複が発生します。重複した場合(=求めた添え字の場所に既にデータが格納済みである場合)は、その近くの添え字の場所にデータを格納したり、添え字の場所から、線形リストで、同じ添え字になったデータをつなげたりします。
参照の場合は、求めた添え字の場所のキー値が等しければそれ。異なれば近くを探すか、リストをたどります。
データが増えてテーブルサイズがN
で足りなくなった場合は、テーブルの拡張が必要です。そのあたりを実装したことないですが、おそらく、ハッシュ値から添え字を求め直して、データ(のポインタ)を移動させるんじゃないでしょうか。移動しないで済む方法もありそうな気もしますが。
投稿2019/04/20 17:42
総合スコア84499
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2019/04/27 10:46
2019/04/27 11:55
2019/04/27 16:26
2019/04/27 16:48
0
実装とかはotnさんの回答されいてるようなことだと思いますが…
キーが付与されていない大きめのデータを効率よく探索したい
てのが要点なんじゃないかなあ。
例示されたような小さいものだとハッシュ値がかぶりまくりで
うまく運用するのは難しいと思います。
投稿2019/04/20 23:30
総合スコア7458
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。