【科目B対策】ハッシュ法(ハッシュ探索)を擬似プログラミング言語で理解する

― 探索が一瞬で終わるアルゴリズム ―

はじめに

基本情報技術者試験・科目Bでは、

探索アルゴリズムとして次の3つが扱われます。

  • 線形探索法
  • ハッシュ法
  • 2分探索法

この記事では、その中でも

「なぜ高速なのか」がポイントになるハッシュ法(ハッシュ探索)に絞って解説します。


ハッシュ法とは?

一言でいうと

ハッシュ法とは、探したいデータの「置き場所」を先に計算してしまう探索アルゴリズムです。

線形探索のように先頭から順番に調べるのではありません。


探索の考え方(超重要)

ハッシュ法では、次の流れで探索を行います。

  1. データを ハッシュ関数 に入れる
  2. ハッシュ値 を求める
  3. ハッシュ値を 配列の要素番号(アドレス) として使う
  4. その場所を直接確認する

👉 探す場所が最初から決まっている

これが最大の特徴です。


ハッシュ関数とは?

ハッシュ関数の役割

データ → 数値(ハッシュ値)に変換する仕組み

科目Bでは、次のような 非常にシンプルなハッシュ関数 がよく使われます。

ハッシュ値 = 入力値 mod 10

※ mod は「割り算の余り」を表します。


具体例で理解する(教科書準拠)

例:次のデータを格納する

データ
32
78
51

ハッシュ関数

x mod 10

ハッシュ値の計算

  • 32 mod 10 → 2
  • 78 mod 10 → 8
  • 51 mod 10 → 1

ハッシュ表(配列)のイメージ

要素番号データ
151
232
878

このように、

ハッシュ値 = データの格納場所

になります。


ハッシュ法による探索の流れ

例:32 を探す場合

  1. 探索対象「32」をハッシュ関数に入れる
  2. 32 mod 10 = 2
  3. 要素番号「2」を確認
  4. 一発で発見

👉 探索回数は1回

これが、ハッシュ法が高速な理由です。


擬似プログラミング言語でのイメージ

前提

  • 配列 T はハッシュ表
  • ハッシュ関数は KEY mod 10

擬似コード例

H ← KEY mod 10

if T[H] = KEY then
  FOUND ← true
else
  FOUND ← false
endif

読み取りポイント

  • ループが存在しない
  • 計算 → 1回比較だけ
  • 「速い」理由を構造で理解する

(科目Bの擬似言語)だと、「全コード」は (1) ハッシュ表を作る(格納) と (2) 探す(探索) の両方を含む形になります。

ハッシュ関数:x mod 10、ハッシュ表:配列 T[0..9](空は EMPTY) として、衝突は“起きる”ところまで(解決法は試験範囲外になりやすい)を基本形にします。


1) 科目B向け:衝突解決なし(最小構成の全コード)

「衝突が起きたら格納失敗」とする、いちばんシンプルな形です。

// 定数
EMPTY ← -1

// ハッシュ関数
function Hash(x)
  return x mod 10
endfunction

// ハッシュ表の初期化
procedure InitTable(T)
  for i ← 0 to 9
    T[i] ← EMPTY
  endfor
endprocedure

// 格納(衝突解決なし)
function Insert(T, x)
  h ← Hash(x)
  if T[h] = EMPTY then
    T[h] ← x
    return true
  else
    // 衝突(コリジョン)
    return false
  endif
endfunction

// 探索
function Search(T, key)
  h ← Hash(key)
  if T[h] = key then
    return true
  else
    return false
  endif
endfunction

// メイン例(教科書データ)
procedure Main()
  declare T[0..9]

  InitTable(T)

  Insert(T, 32)
  Insert(T, 78)
  Insert(T, 51)

  print Search(T, 32)   // true
  print Search(T, 49)   // false(格納していない想定)
endprocedure

このコードで、科目B的に重要なポイントはこれです。

  • h ← key mod 10 が 格納場所(要素番号) を決める
  • 探索は 1回のアクセス+1回の比較(速い理由)
  • 弱点は Insert の else にある 衝突

2) 参考:衝突を解決する全コード(線形探索=線形プロービング)

科目Bでは「衝突が起きる」は問われやすい一方、解決法の詳細は深追いされにくいです

(空きが見つかるまで 次の場所へずらして格納

EMPTY ← -1

function Hash(x)
  return x mod 10
endfunction

procedure InitTable(T)
  for i ← 0 to 9
    T[i] ← EMPTY
  endfor
endprocedure

// 格納(線形プロービング)
function Insert(T, x)
  h ← Hash(x)

  for k ← 0 to 9
    idx ← (h + k) mod 10
    if T[idx] = EMPTY then
      T[idx] ← x
      return true
    endif
  endfor

  // 表が満杯
  return false
endfunction

// 探索(線形プロービング)
function Search(T, key)
  h ← Hash(key)

  for k ← 0 to 9
    idx ← (h + k) mod 10

    if T[idx] = EMPTY then
      // 途中で空が出たら、これ以上先には存在しない
      return false
    endif

    if T[idx] = key then
      return true
    endif
  endfor

  return false
endfunction

procedure Main()
  declare T[0..9]

  InitTable(T)

  Insert(T, 32)   // 2
  Insert(T, 42)   // 2で衝突 → 3へ
  Insert(T, 78)   // 8
  Insert(T, 51)   // 1

  print Search(T, 42)   // true
  print Search(T, 49)   // false
endprocedure

どっちを「科目Bの全コード」として覚えるべき?

  • 試験の本筋(速い理由・衝突が起きる)に絞るなら → 1) 衝突解決なし
  • 授業で「衝突したらどうする?」まで見せたいなら → 2) 線形プロービング

ハッシュ法の弱点(試験に出る)

衝突(コリジョン)とは?

異なるデータなのに、同じハッシュ値になること

  • 32 mod 10 → 2
  • 42 mod 10 → 2

この場合、

  • 同じ要素番号「2」に
  • 2つのデータを格納できない

これを 衝突 と呼びます。


科目Bでの扱い方(重要)

基本情報技術者試験では、

  • 「ハッシュ法のデメリットは衝突が起こる可能性があること」
  • 衝突をどう解決するか(連鎖法・再ハッシュなど)

👉 解決方法の詳細は問われません

あくまで、

「衝突が起きる可能性がある」

という 性質の理解 がポイントです。


ハッシュ法の特徴まとめ

項目内容
探索速度非常に速い
探索回数原則1回
並び順不要
デメリット衝突が起こる可能性

科目B対策としての注意点

① ハッシュ値=要素番号

  • ハッシュ値は「比較する値」ではなく「場所」

ここを混同すると誤読します。


② for文を探さない

ハッシュ法の問題では、

  • ループがない
  • または最小限

👉 「なぜ繰り返していないのか?」

を意識すると正解しやすくなります。


まとめ

  • ハッシュ法は「探す場所を計算する」探索アルゴリズム
  • 科目Bでは 速さの理由と衝突の存在 が理解できればOK
  • 擬似プログラミング言語では計算 → 直接アクセス の流れを読む

訪問数 5 回, 今日の訪問数 5回