データ構造とアルゴリズム

technical-news

二分探索木

 二分探索木は木のような生え方をしたデータの記録方法で、単純なルールしかないので理解しやすいです。

二分探索木のルール

1.1つの節(分岐)は最大で2つの足を持つ。
2.一番上の節は「根」と呼ばれる
3.節の数より小さい数は左の足へ行く
4.節の数より多きい数は右の足へ行く

サンプル

はじめに15という数字を登録するとします。
そうすると根に15という値が入ります。

つぎに10という数字を登録しようとしたときは、根の数字(15)と、入れようとする数字を比較して、入れようとしている数字が小さければ左の節に行き値(10)を追加する

こんどは9という数字を入れる場合、根が15なので左へ進む。そして9は10よりも大きいので、今度は10の節の左側に節を新しく作って登録する。結果としてこの木は左にしか枝がない偏った木になるが、二分探索木ではこれでもOK。

この木のようにきれいに等間隔にできた木のことを「完全二分木」と言います。
・木の形が「左から順番にノードが詰まっている」。
・一番下の段以外はすべてノードが埋まっている。
・一番下の段にノードが足りない場合でも、左から順番に並んでいる。

平衡木(AVL木)

 平衡木とは二分探索木がいびつなかたちになってしまって検索の効率が悪くなるのを防ぐことができる木です。Adelson-Velsky(アデルソン=ヴェルスキー)とLandis(ランディス)という人たちが世界で最初に平衡木を考案したのでAVL木と名付けられています。

値をセットするたびに木をチェックするAVL木

 AVL木はデータを登録するたびに木をチェックして、足の長さが2以上にならないように修正を入れるロジックがある木です。以下に1から順に見ていきます。

ブラウザを再描画してください。
Imgur spankyjpn
01-spankyjpn.com-TOU-東京通信大学

まずはじめに1つめのデータを根に登録します。

ブラウザを再描画してください。
Imgur spankyjpn
01-spankyjpn.com-TOU-東京通信大学

次に10を追加します。15より小さいので左の節にします。
1つ上の節から見ると高さが1なのでOKとします。

ブラウザを再描画してください。
Imgur spankyjpn
01-spankyjpn.com-TOU-東京通信大学

次に12を追加します。10の右に節を追加します。
1つ上の10の節から見ると、高さが1なのでOKですが、
そのもう1つ上の根から見ると高さが2になっているのでNGです。ここで「回転」という動作を行います
今回は10の右の足を伸ばしたことで高さが2になりましたので、これはR型です。R型の不均衡の場合は、10を頂点にして右に回転させます(一重回転)。

10を右に一重回転して高さが1の木になりました。
もしも左に木が伸びて高さが2になった場合は(L型の不均衡の場合は)、左に一重回転させると均衡状態になります。

AVL木の二重回転

木を二重回転という回転のさせかたをして均衡を取り戻す方法があります。
たとえば以下のような例です。

ブラウザを再描画してください。
Imgur spankyjpn
01-spankyjpn.com-TOU-東京通信大学

この例ではすべての節(数字が入っている丸)の高さの差が2未満で釣り合っている状態です。

ここで新しく47を追加してみます。すると以下のようになります。

ブラウザを再描画してください。
Imgur spankyjpn
01-spankyjpn.com-TOU-東京通信大学

47の足を新しく足す順序は以下のとおりです。
まずは根から見ていきます。
47は根の50より小さいので左へ行きます(30の節に来ます)。
次に30より大きいので右へ行きます(40の節に来ます)。
次に40より大きいので右へ行きます(46の節に来ます)。
46の節には足がないので46より大きい47は46の右の節になります。

さらに、
47が新しく加わったのでチェックを行います。
46➤40➤30とさかのぼって見ていくと、30を頂点とする木までの高さの差は2未満ですので、30を頂点とする木は均衡が取れています

ところが一番上の根(50の節)から見ると、50の右の80を頂点とする木の高さは3なのに対して、30を頂点とする左の木は5段目に届いているので、この30の木の高さは5です。したがって高さの差が2になってしまいました。

ブラウザを再描画してください。
Imgur spankyjpn
01-spankyjpn.com-TOU-東京通信大学

しかしこのような場合は、図のように単純な右への一重回転では解決できません。

このような場合は下の図のように三角形の木を連想するとわかりやすくなります。

ブラウザを再描画してください。
Imgur spankyjpn
01-spankyjpn.com-TOU-東京通信大学

上の図では、30の節から見て右側の40を頂点とする三角形が高すぎるために起こっている不均衡(LR型不均衡)でしたので、40の木を二重回転という動作で均衡化します。
不均衡を検出した節は根の50であり、実際に不均衡の原因を作ったのは、40の木ですから、40を新しい根にして50を右にずらします。
40より下の節は一旦分解して保留しておきます。

ブラウザを再描画してください。
Imgur spankyjpn
01-spankyjpn.com-TOU-東京通信大学

LR型右2重回転をした結果です。
40の左にあった35は新しく30の右の節になります。
40の右にあった46と47は50の下につけます。
こうすることで二分木のルール(左節は小さい数字で、右の節が大きい数字)のルールを保ったまま、すべての節の高さが2未満に揃いました。

ブラウザを再描画してください。
Imgur spankyjpn
01-spankyjpn.com-TOU-東京通信大学

もしも原因を作った木が、不均衡を検出した節(このサンプルの場合は根)の右側にあった場合は、RL型不均衡として根を左にずらして原因となった木の節を根に持っていきます。

実際にテストを受ける際のポイント

AVL木の問題がでたら、頭で考えるのではなく、即興で紙に書いてみるとわかりやすくなります。

B木

B木は二分探索木とちがって視覚的に理解しやすいです。
B木もいろいろルールはありますが、一番シンプルに解説していきます。

基本のかたち

 以下の図はB木の基本的な形です。一番上の枠は「根」と呼びます。2段目以降は何段あってもすべて「節」と呼びます。筆者が勝手に命名した節は次の節または葉への「ポインタ」と、そのポインタを検索するためのキーが入る「インデックス」があります。このインデックスがあるおかげで、目的のデータがどこにあるか検討がつくわけです。そして実際のデータ(葉)は必ず一番下の段にぶら下がります

ブラウザを再描画してください。
Imgur spankyjpn
01-spankyjpn.com-TOU-東京通信大学

上記の図では、葉も1段と数えるので、段数が3段のB木となります。

もしも1つの節の中にすべての葉が入ってしまう場合は、その節が「節の無い根」になります。

サンプル

B木の動きを追ってみましょう。

ブラウザを再描画してください。
Imgur spankyjpn
01-spankyjpn.com-TOU-東京通信大学

まずはなにもない根だけのB木があります。

ブラウザを再描画してください。
Imgur spankyjpn
01-spankyjpn.com-TOU-東京通信大学

この空のB木に情報「50」を登録します。まだ情報(葉)が1つしかないので、検索もなにもないためインデックスは不要です。

ブラウザを再描画してください。
Imgur spankyjpn
01-spankyjpn.com-TOU-東京通信大学

次に情報「20」を登録する場合を考えてみます。B木は必ず左端から昇順にデータが並んでいなければいけないのでを左端の葉にして50を右にずらします。ここではじめてインデクスを書き込んで探索をしやすくします。インデックスの値はすぐ右の葉の値です。

ブラウザを再描画してください。
Imgur spankyjpn
01-spankyjpn.com-TOU-東京通信大学

同じように情報「30」を登録します。ここで節がいっぱいになりました。

ブラウザを再描画してください。
Imgur spankyjpn
01-spankyjpn.com-TOU-東京通信大学

いっぱいになった節にさらにデータを入れようとすると(この場合は65)、節を半分に分割し、最上段に根を設定して分割した両方の節を探索しやすいように修正します。

タイトルとURLをコピーしました