_______________________
| ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄
|★ハッシュ関数
|
| ハッシュテーブルとは?
|
| ハッシュテーブルは、キーと値の組(エントリ)を複数個格納し、
| キーに対応する値をすばやく参照するためのデータ構造
| by wikipedia
|
| 。/ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄
ΛΛ / | 再開するかもぜ(’A`)
(,,゚Д゚)⊃ ∠___________________
~/U /___________________Ellヨ__
| ̄ ̄|  ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄
 ̄ ̄ ̄ ̄
_______________________
| ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄
|★でっていう
| どういうときに使うかというと
|
| ヤマダ -> 170cm
| タナカ -> 175cm
| サイトウ-> 185cm
|
| このように 名前に関連付けてデータを扱いたいときに
| 使います
| 。/ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄
ΛΛ / | オナカスイタ
(,,゚Д゚)⊃ ∠___________________
~/U /___________________Ellヨ__
| ̄ ̄|  ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄
 ̄ ̄ ̄ ̄
_______________________
| ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄
|★普通に構造体配列使えばよくね?
|
| そうですが、ハッシュの魅力は、配列に
| 順番に入れるよりもすばやく処理できることに
| あります
|
| / ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄
| | 三項演算・ビット演算・配列の参照にx+1
| 。| #define a int とか typedef
ΛΛ / | みたいな事すると 読み難いコードが出来上がるぜ
(,,゚Д゚)⊃ ∠___________________
~/U /___________________Ellヨ__
| ̄ ̄|  ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄
 ̄ ̄ ̄ ̄
_______________________
| ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄
|★んじゃどうすんの?
|
| ①入力された「名前」に対して 配列のサイズに合わせて
| 数字を割り当てます
|
| ②その数字の位置にデータを入れます。
| ③(゚д゚)ウマー
|
| 。/ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄
ΛΛ / | ①をハッシュ関数っていうんだぜ。
(,,゚Д゚)⊃ ∠___________________
~/U /___________________Ellヨ__
| ̄ ̄|  ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄
 ̄ ̄ ̄ ̄
_______________________
| ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄
|★①についてkwsk
|
| つまり、配列の何番目に入れるかを計算で決めます。
| 例えば「ヤマダ」だと「3」を返すようにすると
|
| 0 1 2 3
| [ ][ ][ ][ ]
| ↑
| ここがヤマダのデータ
|
| のようになります。
| ただし、上の場合だと「3」より大きい値を返すと
| Segmentation Fault 配列のサイズ以上の
| 領域にデータをいれようとするのでエラーが出ます。
|
| 。/ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄
ΛΛ / | MD5・SHAを返すのとかもハッシュ関数なんだぜ。
(,,゚Д゚)⊃ ∠___________________
~/U /___________________Ellヨ__
| ̄ ̄|  ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄
 ̄ ̄ ̄ ̄
_______________________
| ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄
|★いいから①のハッシュ関数作れよ
|
| 最も簡単なのは、名前を整数にして、
| Mで割り、その余りをハッシュ値とすることです
| この場合、ハッシュ値は 「0~M-1」のどれかになるよね!
|
| 例えば、M=4、ヤマダ=11だとすると
|
| ヤマダ(11) % M(4) = 3
|
| 0 1 2 3 M-1
| [ ][ ][ ][ ]・・・・・・[ ]
| ↑
| ここがヤマダのデータ
|
| 。/ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄
ΛΛ / | ハッシュ値とはハッシュ関数が返す値だぜ。
(,,゚Д゚)⊃ ∠___________________
~/U /___________________Ellヨ__
| ̄ ̄|  ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄
 ̄ ̄ ̄ ̄
_______________________
| ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄
|★ちょwwwwやばいwwwww
|
| タナカ=7にするとヤバイwwwww
|
| そうです、M=4、タナカ=7、ヤマダ=11だとすると
|
| ヤマダ(11) % M(4) = 3
| タナカ(7) % M(4) = 3
|
| 0 1 2 3 M-1
| [ ][ ][ ][ ]・・・・・・[ ]
| ↑
| タナカ?ヤマダ?どっち?
|
| 。/ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄
ΛΛ / | これを衝突というんだぜ。
(,,゚Д゚)⊃ ∠___________________
~/U /___________________Ellヨ__
| ̄ ̄|  ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄
 ̄ ̄ ̄ ̄
_______________________
| ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄
|★衝突した時どうすんの?
|
| 衝突は絶対に起きるものです。
| そのような時は、適当な計算をしてあらたな
| ハッシュ値を与えましょう
|
| 今回は、「配列の右端(M-1)ー余り」でやってみます。
| ●M=4、タナカ=7、ヤマダ=11だとすると
|
| ヤマダ(11) % M(4) = 3
| タナカ(7) % M(4) = 3 ←被ったww
| タナカ→ 右端(3)-3 = 0
|
| 0 1 2 3
| [ ][ ][ ][ ]
| ↑ ↑
| タナカ ヤマダ
| / ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄
| 。| 新たなハッシュ値が配列の右端より大きかっ
ΛΛ / | たら駄目だぜ
(,,゚Д゚)⊃ ∠___________________
~/U /___________________Ellヨ__
| ̄ ̄|  ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄
 ̄ ̄ ̄ ̄
_______________________
| ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄
|★で、なんの為にしてたんだっけ?
|
| このようにして、配列の身長を入れることが出来ました!
|
| [160cm][ ][ ][175cm]
| ↑ ↑
| タナカ ヤマダ
|
| そして、次にデータを取り出すときには
| 「名前」をハッシュ値にすればいいわけですね。
|
| ( ゚∀゚)彡ヤマダ!ヤマダ!
| となったら
|
| ゚Д゚)y~~< ヤマダ(11) % M(4) = 3 だぜ
|
| ( ゚∀゚)彡ヤマダ=3! ヤマダ=3! ←パスワードを入力します。
| yamada = sincyo[3]; のようにすればおk!
|
| 。/ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄
ΛΛ / | これで、配列の中身から名前検索しなくて済むだろ
(,,゚Д゚)⊃ ∠___________________
~/U /___________________Ellヨ__
| ̄ ̄|  ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄
 ̄ ̄ ̄ ̄
_______________________
| ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄
|★補足1
|
| 実際はヤマダ=11なんてできないので、
| 大抵はコード番号を使います。
|
| ASCIIコードを使って
| A=65 ですね。
|
| これならC言語でも簡単に扱えます。
|
|
| 。/ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄
ΛΛ / | Hash('A'); とするんだゴルァ
(,,゚Д゚)⊃ ∠___________________
~/U /___________________Ellヨ__
| ̄ ̄|  ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄
 ̄ ̄ ̄ ̄
_______________________
| ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄
|★補足2
|
| ●衝突して、新しい値でも衝突したら?
|
| また、新しい値を与えます。
|
|
| 。/ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄
ΛΛ / | 新しい値は前と違う値になるようにしろよ
(,,゚Д゚)⊃ ∠___________________
~/U /___________________Ellヨ__
| ̄ ̄|  ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄
 ̄ ̄ ̄ ̄
_______________________
| ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄
|★では、実際に作ってみましょう!
|
| 身長と名前 をハッシュテーブルに登録する
| プログラムを作ってみます。
|
| 。/ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄
ΛΛ / | 需要があるのか無いのか分からねぇぞゴルァ
(,,゚Д゚)⊃ ∠___________________
~/U /___________________Ellヨ__
| ̄ ̄|  ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄
 ̄ ̄ ̄ ̄
_______________________
| ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄
|★では、実際に作ってみましょう!
|
| まず、データの構造体を用意します。
|
| struct list {
| char name[MAX_NAME]; // ←名前
| int height; // ←身長
| }
| / ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄
| | 構造体の中に
| 。| struct list *next;
ΛΛ / | として衝突時の次の値を参照する方法もあるぞ
(,,゚Д゚)⊃ ∠___________________
~/U /___________________Ellヨ__
| ̄ ̄|  ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄
 ̄ ̄ ̄ ̄