木構造と二分探索木 — 枝分かれで半分ずつ絞り込む
データを一列に並べるのではなく、枝分かれさせて持つ。上から「大きい?小さい?」と質問を重ねるだけで、探す範囲が一段ごとに半分になる——それが二分探索木です。木が育つ様子と、油断するとただの鎖に化ける落とし穴を、動かしながら理解します。
1. 木構造の言葉 — 根・葉・高さ
木は、一番上の根(ルート)から枝が下へ分かれていくデータ構造です。各節点(ノード)は子を持ち、子のない末端が葉(リーフ)。根から一番遠い葉までの段数を高さと呼びます。この高さが、あとで見る探索の速さをそのまま決めます。
下で葉を選ぶと、根からそこまでの道すじと深さが光ります。全体を上から見下ろすイメージをつかんでください。
2. 二分探索木のルールと挿入
二分探索木(BST)のルールはたった一つ:どの節点でも「左の子 < 自分 < 右の子」。この約束のおかげで、新しい値を入れるときは根から「小さいなら左、大きいなら右」と降りていき、空いた場所にぶら下がるだけで正しい位置が決まります。
下でスライダーの値を選んで「追加」を押してください。値が根から比較しながら降りて、葉として着地します。
3. 探索 — 根から目標へ一直線
探すときも挿入と同じ動き。目標と節点を比べ、小さければ左、大きければ右へ進むだけ。1段進むごとに、見なくてよい枝(もう一方の部分木)をまるごと捨てられる——これが「半分ずつ絞り込む」の正体です。バランスが良ければ比較回数は約 log₂n 回。
下で探す値を切り替えると、根から目標までの道が光ります。存在しない値なら、行き止まりで「なし」と分かります。
4. 偏りの罠と平衡 — ソート済みを入れると鎖になる
BST の弱点:入れる順番で形が激変すること。すでに小さい順に並んだ値を入れると、毎回「右へ右へ」と降りるため、木は片側にだけ伸びた鎖——ほぼ連結リストになってしまいます。高さが n に達し、探索は O(n) に退化します。
下で並び順を切り替えて、木が育つ様子を見比べてください。ソート済みは階段状の鎖に、バランス配置はこんもり低い木になります。
std::map/Java の TreeMap の中身は赤黒木。ディスク前提でノードを多分岐にしたB木・B+木は、ほぼすべてのデータベースのインデックスを支えている。木を低く保つ工夫が、現実のシステムの検索速度を決めている。
5. まとめ — 木で「絞り込む」設計図
- 木の高さ:探索・挿入のコストはたどる道の長さ=高さで決まる。低いほど速い。
- BST のルール:左 < 親 < 右。根から比較して降りるだけで挿入も探索もできる。
- 偏りの罠:整列データを入れると高さ n の鎖に退化。平衡木(AVL・赤黒木・B木)が回転で高さを O(log n) に保つ。