ハッシュ法と衝突の扱い
ハッシュ法とは何かを他の検索方式と見分けられ、ハッシュ値の計算・衝突の判定・衝突時の格納位置のたどり方を、手を動かして自力で答えられるようになる。
ハッシュ法は「キーから一発で置き場所を計算する」ので、データが何件あってもほぼ一定の時間で探せます。試験では「定義を選ぶ問題」と「計算して位置を出す問題」が交互に、ほぼ同じ文面で繰り返し出ます。
このレッスンで稽古する(用語チェック・過去問)結論:ハッシュ法は「キーを計算して置き場所を決める」方法
ハッシュ法とは、データのキー(会員番号など、探すときの目印になる値)をハッシュ関数(決まった計算式)に入れ、出てきた値(ハッシュ値)を格納場所(アドレス)として使う方法です。探すときも同じ計算をすれば置き場所がすぐに分かるので、表を端から順に見る必要がありません。
たとえるなら、ロッカーの番号を「誕生日の日にちの数字」で決めるルールです。15日生まれの人は15番のロッカーと決まっているので、名簿をめくらずに一発でたどり着けます。
前回の探索アルゴリズムと比べると、違いがはっきりします。
| 探索方法 | 探し方 | 探索時間 |
|---|---|---|
| 線形探索 | 先頭から順に見る | データ数に比例して増える |
| 2分探索 | 整列済みの表を半分ずつ絞る | データ数が増えてもゆっくりしか増えない(log n) |
| ハッシュ法 | キーを計算して置き場所に直行 | 表の大きさにほぼ関係なく一定(衝突が少なければ) |
「ハッシュ法の説明はどれか」で混ぜられる方式
定義を問う問題では、別のアクセス方式や検索技術の説明がひっかけとして並びます。正解の決め手は「関数(アルゴリズム)で変換した値を格納アドレスにする」という言い回しです。
| 選択肢に出る説明 | 正体 | ハッシュ法か |
|---|---|---|
| 関数でキー値から格納アドレスを求める | ハッシュ法 | ○ |
| 各レコードに入っている「次のレコードのアドレス」をたどる | ポインタによる連結(リスト構造) | × |
| キー値とアドレスの対応表を使う | 索引(インデックス) | × |
| キー値をそのままアドレスにする | 直接アドレス指定 | × |
| 同義語・類義語のリストで検索漏れを防ぐ | シソーラス | × |
| 大量データから傾向や相関を見つける | データマイニング | × |
| 利用者の意図を判断する高度な検索 | 知識ベース・AI 的な検索 | × |
「対応表を使う」と「計算で求める」の違いが最大のポイントです。ハッシュ法は表を引かずに計算するので速く、データが増えても扱いやすい(スケーラビリティが高い)と説明されます。
衝突(シノニム)は必ず起こりうる
違うキーなのに同じハッシュ値になることを衝突(コリジョン)といい、衝突したキー同士をシノニム(同義語)と呼びます。誕生日ロッカーの例なら、1月15日生まれと3月15日生まれは同じ15番になってしまいます。
格納場所の数よりキーの種類のほうがずっと多いのがふつうなので、衝突は避けられません。だから「衝突が発生しない方法である」という選択肢は必ず誤りです。衝突したときの処理方法には、大きく2種類あります。
| 方式 | 衝突したときの動き | 覚え方 |
|---|---|---|
| オープンアドレス法 | 表の中の別の空き場所を決まったルールで探して入れる | 埋まっていたら隣(など)へずれる |
| チェイン法(連鎖法) | 同じハッシュ値のデータをリストでつないで同じ場所にぶら下げる | 同じ番地に数珠つなぎ |
試験の計算問題で出るのはほぼオープンアドレス法のトレース(順に追いかけること)です。
ハッシュ値の計算:問題の式をそのまま実行するだけ
ハッシュ値の計算問題は、問題文に書かれた変換ルールを1ステップずつ忠実に実行するだけです。知識より「手順を飛ばさない」ことが問われます。
よく出る道具は mod(割り算の余り)です。たとえば mod(15, 13) は「15 を 13 で割った余り」なので 2 です。余りは必ず 0〜(割る数−1) の範囲に収まるため、表の大きさで割れば必ず表の中の番号になります。
ほかに「キーを11進数とみなして10進数に直す」(基数変換法)のような変わったルールも出ますが、やることは同じです。どの桁を使うか・切り捨てるかを問題文のとおりにやれば解けます。
衝突の判定:ASCII コードは「並び順の差」で解く
ASCII コードとは、文字を数値で表す代表的な文字コードです。小文字 a〜z には連続した番号が順に振られていて、a は 10 進で 97 です。
「1の位をハッシュ値にする」なら、1の位が同じになる組が衝突です。番号が連続しているので、アルファベット順で10文字離れた(差が10の倍数)文字同士が衝突します。a=97 を覚えていなくても、この性質だけで解けます。
| 1の位が同じグループ | 例 |
|---|---|
| a・k・u | 97・107・117 |
| b・l・v | 98・108・118 |
| c・m・w | 99・109・119 |
| d・n・x | 100・110・120 |
オープンアドレス法のトレース:表を書いて1件ずつ埋める
トレース問題はメモ用紙に表(アドレスの欄)を書いて、データを1件ずつ順番に入れていくのが確実です。頭の中だけで追うと、途中で埋まった場所を見落とします。
注意点は2つです。1つは「最終アドレスの次は先頭に戻る」というルールがあるかどうか。もう1つは、ずらし方が「+1」だけとは限らず、「+1 がだめなら +4」のように問題ごとに独自のルールがあることです。
flowchart TD
A["キーからハッシュ値を計算"] --> B{"その場所は空いている?"}
B -- "はい" --> C["そこに格納"]
B -- "いいえ(衝突)" --> D["ルールどおり次の候補へ(最後の次は先頭)"]
D --> B
試験での問われ方
- 定義問題:「関数で格納アドレスを求める」が正解。対応表=索引、次のアドレスをたどる=ポインタ、そのままアドレス=直接アドレス指定、と見分ける。
- 特徴問題:「2分木を使う」「衝突しない」「表の大きさに比例する」はすべて誤り。
- 計算問題:桁の和の mod、基数変換などを問題文どおりに計算する。商と余りの取り違えに注意。
- 衝突判定:ASCII の1の位なら、アルファベットの距離が10の倍数かを見る。
- トレース:表を書いて順に埋める。格納の順番を入れ替えないこと。
桁の和を13で割った余りで位置を求める(54321)
ア 1
イ 2
ウ 7
エ 11
解き方と答えを見る
- ハッシュ関数は mod(a1+a2+a3+a4+a5, 13)。まず各桁を足す
- 5+4+3+2+1 = 15
- 15 を 13 で割る:15 ÷ 13 = 1 余り 2
- 余りの 2 がハッシュ値なので、位置 2 に格納する(商の 1 や和の 15 ではない)
答え:イ(位置 2)
基数変換法でアドレスを求める(キー 55550)
ア 0260
イ 2525
ウ 2775
エ 4405
解き方と答えを見る
- 55550 を11進数とみなし、各桁に11のべき乗を掛ける。11^4=14641、11^3=1331、11^2=121、11^1=11、11^0=1
- 5×14641 = 73205
- 5×1331 = 6655
- 5×121 = 605
- 5×11 = 55
- 0×1 = 0
- 合計:73205+6655+605+55+0 = 80520(10進数)
- 下4桁を取り出すと 0520
- 0520 × 0.5 = 260(小数点以下は切り捨てだが、ここでは端数なし)
- 4桁で表すと 0260。アドレス範囲 0000〜4999 に収まっている
答え:ア(0260)
ASCII コードの1の位で衝突する組を探す
ア aとi
イ bとr
ウ cとl
エ dとx
出典:令和6年度 基本情報技術者試験 科目A 公開問題 問2
解き方と答えを見る
- 小文字は a=97 から連番。1の位が同じなら衝突する
- 連番なので、アルファベット順の距離が10の倍数なら1の位が一致する
- ア:a→i は 8 文字差(97 と 105 → 1の位 7 と 5)→衝突しない
- イ:b→r は 16 文字差(98 と 114 → 8 と 4)→衝突しない
- ウ:c→l は 9 文字差(99 と 108 → 9 と 8)→衝突しない
- エ:d→x は 20 文字差(100 と 120 → 0 と 0)→衝突する
答え:エ(d と x)
「余り+1」で格納し、埋まっていたら次へ(アドレス1〜6)
ア 8
イ 13
ウ 14
エ 18
解き方と答えを見る
- ルール:アドレス = (キー mod 5) + 1。埋まっていたら次のアドレスへ。6 の次は 1 に戻る
- 3:3 mod 5 = 3 → 3+1 = 4。空き → アドレス4 に 3
- 4:4 mod 5 = 4 → 4+1 = 5。空き → アドレス5 に 4
- 8:8 mod 5 = 3 → 4。4 は埋まり → 5 も埋まり → 6 が空き → アドレス6 に 8
- 13:13 mod 5 = 3 → 4。4・5・6 が埋まり → 6 の次は先頭の 1 が空き → アドレス1 に 13
- 14:14 mod 5 = 4 → 5。5・6・1 が埋まり → 2 が空き → アドレス2 に 14
- 18:18 mod 5 = 3 → 4。4・5・6・1・2 が埋まり → 3 が空き → アドレス3 に 18
- アドレス1 に入っているのは 13
答え:イ(13)
「+1 がだめなら +4」の独自ルールでたどる(A[0]〜A[9])
ア A[3]
イ A[5]
ウ A[6]
エ A[9]
解き方と答えを見る
- ルール:まず A[k mod 10]、埋まっていたら A[(k+1) mod 10]、それも埋まっていたら A[(k+4) mod 10]
- 16:16 mod 10 = 6 → A[6] が空き → A[6] に 16
- 43:43 mod 10 = 3 → A[3] が空き → A[3] に 43
- 73:73 mod 10 = 3 → A[3] は埋まり → (73+1) mod 10 = 4 → A[4] に 73
- 24:24 mod 10 = 4 → A[4] は埋まり → (24+1) mod 10 = 5 → A[5] に 24
- 85:85 mod 10 = 5 → A[5] は埋まり → (85+1) mod 10 = 6 → A[6] も埋まり → (85+4) mod 10 = 89 mod 10 = 9 → A[9] に 85
答え:エ(A[9])
要点(試験直前に読む)
- ハッシュ法=キーをハッシュ関数で計算した値を格納アドレスにする方法。探索時間は表の大きさにほぼ関係しない
- 衝突(シノニム)は必ず起こりうる。対処はオープンアドレス法(別の空きへ)とチェイン法(リストでつなぐ)
- 計算問題は問題文の式どおりに実行。mod は「余り」、基数変換は桁ごとにべき乗を掛けて足す
- ASCII の1の位で衝突判定するなら、アルファベット順で差が10の倍数の組が衝突(d と x など)
- トレース問題は表を書いて1件ずつ埋める。「最後の次は先頭」や「+1 の次は +4」などの独自ルールを読み落とさない
ひっかけ
- 「衝突が発生しない」「2分木を使う」「表の大きさに比例する」は、どれもハッシュ法の特徴として誤り
- 「対応表を使う」は索引、「次のレコードのアドレスを使う」はポインタ、「キーをそのままアドレスに」は直接アドレス指定。ハッシュ法は「関数で求める」
- シソーラス・データマイニング・知識ベースの説明が並んだら、「変換した値を格納アドレスにする」ものを選ぶ
- mod の計算で商や和そのものを答えにしない。54321 なら和 15 でも商 1 でもなく余り 2
- トレースで格納順を入れ替えたり、埋まった場所を見落としたりすると別の選択肢になる。必ず表に書き込みながら追う
用語(14)
キーをハッシュ関数で計算した値を格納場所として使い、表をなめずに直接アクセスする探索・格納の方法。
⚠ 索引(対応表を引く)や直接アドレス指定(キーをそのままアドレスにする)と混同しやすい。「関数で計算する」がハッシュ法の目印。
キーを入力すると、格納場所の番号(ハッシュ値)を返す計算式。
ハッシュ関数の計算結果で、格納場所のアドレスとして使う値。
⚠ 計算途中の値(桁の和や割り算の商)をハッシュ値と取り違えやすい。最後に出た余りなどが答え。
ハッシュ値をアドレスとしてデータを格納する配列状の表。
異なるキーなのに同じハッシュ値になり、同じ格納場所を指してしまうこと。
⚠ 「ハッシュ法は衝突が発生しない」は誤り。キーの種類が場所の数より多いので必ず起こりうる。
ハッシュ値が同じになって衝突したキー同士のこと。
⚠ 検索技術のシソーラス(同義語・類義語リスト)とは別物。
衝突したとき、決められたルールで表の中の別の空き場所を探して格納する方式。
⚠ チェイン法は同じ場所にリストでつなぐ方式。表の中で場所をずらすのがオープンアドレス法。
同じハッシュ値になったデータをリスト構造でつなぎ、同じ格納場所にまとめておく衝突処理方式。
⚠ オープンアドレス法は別の空き場所へずらす。チェイン法はずらさずにつなぐ。
mod(x, y) は x を y で割った余りを返す演算で、結果は 0〜y−1 の範囲に収まる。
⚠ 割り算の商と取り違えやすい。mod は余り。
キーを別の基数(例:11進数)の数とみなして10進数に直し、その一部を加工してアドレスにするハッシュ関数の作り方。
英数字や記号を数値で表す代表的な文字コードで、小文字 a〜z は 97〜122 の連番。
キーから計算したアドレスにレコードを直接置き、直接読み書きするファイル編成で、ハッシュ法の考え方を使う。
⚠ 順にたどる順編成ファイルや、索引を使う索引順編成ファイルとは違う。
キー値と格納アドレスの対応表を用意し、それを引いてデータにアクセスする方式。
⚠ ハッシュ法は表を引かずに計算でアドレスを出す。「対応表」と書いてあれば索引。
キー値そのものを格納アドレスとして使うアクセス方式。
⚠ ハッシュ法はキーを関数で変換してからアドレスにする。「そのまま」なら直接アドレス指定。
このレッスンの過去問
- ハッシュ法の特徴(キーの関数値で格納位置決定)平成30年度 春期 基本情報技術者試験 午前 問7
- ハッシュ法による検索の仕組み(格納アドレス変換)平成31年度 春期 基本情報技術者試験 午前 問18
- ハッシュ関数によるハッシュ値計算令和元年度 秋期 基本情報技術者試験 午前 問10
- ハッシュ関数の衝突判定(ASCIIコード利用)令和6年度 基本情報技術者試験 科目A 公開問題 問2
- オープンアドレス法によるハッシュ衝突時の格納位置のトレース平成28年度 秋期 基本情報技術者試験 午前 問20