衝突の回避(2):置き場の調整

衝突の回避(2):置き場の調整

 衝突が起こったときのための別の作戦を立てましょう。データを登録する際に、すでに同じハッシュ値を持っているデータが存在していると、配列のその場所は埋まっていることになります。この場合にどうすればよいでしょう?

 ひとつの方法は、「その近くに空きを探す」というものです。

 これは、新しくデータを挿入するときの作戦です。逆にデータを探す際には、ハッシュ値から得られるインデックスの場所に狙いのものがなかった場合でも、「その近辺を探す」ことを意味します。

 「近くを探す」と言うとあいまいな言い方ですが、具体的にはインデックスがひとつ小さいところを探してそこが空いていればそこに入れる。そこも埋まっていればさらにそれより小さいところを探す、というものです。

 一見するとあまりエレガントな方法には見えないかもしれませんが、それでも総当たりするよりは検索の範囲が狭まります。この方法についてはこれ以上は踏み込みませんが、登録するデータに上限がある場合には十分有効な手段です。

衝突の回避(3):リンクトリストとのコラボ!

 ハッシュ関数をどれほど調整しても衝突は回避できません。また、われわれのデータの置き場(一定のサイズの配列)では、サイズを超えたデータが現れれば、必ず衝突は起こります。このシリーズは増減するデータに対する検索がテーマですから、データ件数の上限を決めてしまいたくはありません。その上限を十分大きくとることで対応することも可能ですが、それでも固定的な配列では常に限界を持つことになります。

 それで、これまでに紹介した方法との併せ技を使います。図3-1は「第1回:サーチのアルゴリズムを学ぶ(http://www.thinkit.co.jp/article/159/1/)」で紹介したリンクトリストです。

 このデータ構造では、データの増減には対応できるものの、データの検索が線形探索になるので、時間がかかることが問題でした。

 リンクトリストで問題なのは、リストが長くなることです。長くなれば長くなるほど検索のための平均探索時間が延びます。そこで、短いリストをたくさん作ったらどうでしょう。短いリストを探索するのであれば、時間はさほど気になりません。

 今回のハッシングでは衝突が問題になりました。そこで、リンクトリストの問題点とハッシングの問題点を併せて解決しましょう。つまり、ハッシングを基本としながらも、衝突したものはリンクトリストで管理するのです。図3-2のようなイメージです。

 この図で左側に配列があります。これがハッシュ値に対応した配列です。その中身はリンクトリストへのポインタ、つまりアンカー(anchor)です。同じハッシュ値を持つものを1つのリンクトリストにつなげます。こうすることで衝突をいわば「吸収」します。

 単純なリンクトリストの場合にはアンカーが1つでした。それをハッシングと組み合わせます。アンカーを決めるためにハッシュ関数を使って配列のインデックスを求めます。これでアンカーが決まります。アンカーが決まれば、そこに連なるリンクトリストに対して追加/登録や削除、検索を実行します。

 リストの長さは単独の場合よりもはるかに短くなるでしょう。また、ここでもハッシュ関数の性能が重要なのですが、ハッシュ値ができるだけ分散するようにすることが、リストの長さを短くすることにつながります。

 第1回のinsert()とsearch()をそれぞれlist_insert()とlist_search()に置き換えれば、新しいinsert()とsearch()は図3-3のようになるでしょう。

 なかなかおしゃれだと思いませんか?このあたりの詳しいことは、プログラムとともに次回にご紹介しましょう。

 ハッシングの話はいろいろなところに出ていますが、執筆にあたって主に次のものを参考にしました。

Donald E.Knuth『The Art of Computer Programming, Vol III. 2nd ed.』McGraw-Hill(発行年:1998)

人気記事トップ10

人気記事ランキングをもっと見る

企画広告も役立つ情報バッチリ! Sponsored

ClickHouse Cloudが実現した広告運用SaaS「ATOM」のデータ基盤革新、パフォーマンスを向上しながら、運用負荷とコストを削減 11月11日 6:20 AIで開発が加速する時代、品質保証はどう変わる? Tricentisが示すAIエージェント活用の実像 11月9日 6:45 悪用までの猶予が「1分」に迫るフロンティアAI時代に開発と本番を貫く脆弱性管理が必要 10月29日 8:30 欧州CRA対応とSBOM運用。AI生成コードのOSS混入問題の対策とは ――スニペット単位で検出する「FossID」「Insignary Clarity」によるSBOM運用 9月16日 6:40 PostgreSQLからTiDBへ、稼働中SaaSで進める段階的DB移行の実践と再設計への展望 9月7日 6:30 機能安全開発におけるGoogleTestの活用を支援!「Parasoft C/C++test CT」で実現する効率化&AI連携 4月14日 6:30 【CNDW2025】Grafanaが明かす「オブザーバビリティの哲学」ー最小限の労力で実用的なインサイトを得るには 1月23日 6:30 【CNDW2025】プロダクト急増に備える基盤刷新 ーウェルスナビがECSからEKSへの移行で得た知見とは 1月15日 6:30 【CNDW2025】250環境を5人で運用、構築時間は30分に ーKINTOテクノロジーズが語るインフラ基盤組織の作り方 2025年12月18日 6:30 新たな自動化で熱視線! AIエージェントの「推論能力」を支える2つのコンポーネントとは? 2025年11月28日 6:30