二分探索木・ヒープの可視化ツール

値を1つずつ挿入してできる二分探索木やヒープを図にします。二分探索木では、なぞり順(先行順・中間順・後行順)、値を探すときに比べる節の経路、節を削除したあとの形を表示します。ヒープでは、配列の何番目にどの値が入るかと、根を取り出したあとの並びを確かめられます。

値の列

数か、6文字までの文字列を40個まで。すべて数なら数の大小、そうでなければ文字の順で比べます。

木の形

    先行順(行きがけ順)
    –
    中間順(通りがけ順)
    –
    後行順(帰りがけ順)
    –
    幅優先(上の段から順に)
    –
    高さ(段の数)
    –
    節の数
    –
    探索で比べた節
    –

    高さは根だけの木を1として数えます(根を0とする数え方もあります)。ヒープの図の右上の小さな数は、根を0番とした配列の番号で、i番の子は 2i+1 番と 2i+2 番、親は (i−1)÷2 の切り捨て番です。

    二分探索木とは

    二分探索木は、どの節についても、左の部分木の値はすべてその節より小さく、右の部分木の値はすべて大きい、という条件を満たす二分木です。値を探すときは根から始めて、探す値が小さければ左へ、大きければ右へ進むので、比べる回数は木の高さ以下で済みます。値を挿入するときも同じようにたどり、行き止まりの位置に新しい節を付けます。例「50 30 70 20 40 60 80」では高さ3の木ができ、60は50、70、60の3回の比較で見つかります。

    なぞり順(先行順・中間順・後行順)

    木のすべての節を訪れる順番には、節を先に訪れてから左右の部分木をたどる先行順(行きがけ順)、左の部分木・節・右の部分木の順の中間順(通りがけ順)、左右の部分木をたどってから節を訪れる後行順(帰りがけ順)があります。二分探索木を中間順でたどると、値が小さい順に並びます。後行順は部分木を先に処理するので、木の削除や式の木の計算(逆ポーランド記法)に使われ、先行順は木を複製するときなどに使われます。上の段から順に訪れるのが幅優先のなぞり順です。

    削除と偏り

    二分探索木から節を削除するとき、子がなければそのまま取り除き、子が1つならその子を代わりにつなぎます。子が2つあるときは、右の部分木の最小の値(または左の部分木の最大の値)をその位置に移してから、移した元の節を削除します。また、整列済みの値を順に挿入すると、木は一方にだけ伸びて連結リストのような形になり、探索に最大n回の比較がかかります。これを防ぐために、挿入や削除のたびに形を整えるAVL木や赤黒木などの平衡二分探索木が使われます。

    ヒープと配列での表し方

    ヒープは、親の値が子の値以上(最大ヒープ)または以下(最小ヒープ)になる二分木で、上の段から左詰めに節を並べた完全二分木の形をしています。このため、根を0番として上の段から順に配列に入れると、i番の節の子は 2i+1 番と 2i+2 番になり、ポインタなしで表せます。値を挿入するときは末尾に置いて親と比べながら上へ移し、根を取り出すときは末尾の値を根に移して子と比べながら下へ移します。どちらも木の高さに比例する O(log n) の手間で済むので、優先度付きキューやヒープソートに使われます。

    アルゴリズムの問題を解く

    二分ヒープを、根を a[0] とする配列 a[0], a[1], a[2], … に、上の段から順に左から詰めて格納する。a[4] の子と親はどれか。

    1. A子は a[9] と a[10]、親は a[1]
    2. B子は a[8] と a[9]、親は a[2]
    3. C子は a[9] と a[10]、親は a[2]
    答えと解説を見る

    正解:A. 子は a[9] と a[10]、親は a[1]

    根を a[0] とする場合、a[i] の子は a[2i+1] と a[2i+2]、親は a[(i−1)÷2 の切り捨て] です。i = 4 なら子は a[9] と a[10]、親は a[(4−1)÷2] = a[1] です。根を a[1] とする場合は子が a[2i] と a[2i+1]、親が a[i÷2] になるので、どちらの決め方かを確かめることが大切です。このように、ヒープは完全二分木なのでポインタを使わずに配列で表せ、添字の計算だけで親子をたどれます。

    親の値が子の値以上になる最大ヒープを、根を a[0] とする配列で表している。ヒープ 50, 30, 40, 10, 20, 35 に45を追加する。末尾に置いてから、親より大きい間は親と交換する操作を行った後の配列はどれか。

    1. A50, 30, 40, 10, 20, 35, 45
    2. B45, 30, 50, 10, 20, 35, 40
    3. C50, 30, 45, 10, 20, 35, 40
    答えと解説を見る

    正解:C. 50, 30, 45, 10, 20, 35, 40

    45は a[6] に置かれ、親は a[(6−1)÷2] = a[2] = 40 です。45 > 40 なので交換して a[2] に移ります。次の親 a[0] = 50 は45より大きいので、ここで止まり、50, 30, 45, 10, 20, 35, 40 になります。交換は木の高さの分しか起こらないので追加は O(log n) で、最大値の取り出しも同じく O(log n) です。この性質から、二分ヒープは優先度付きキューの実装によく使われます。

    二分探索木を中間順(通りがけ順。左の部分木、その節、右の部分木の順に訪れる)でたどったとき、訪れた節の値はどのように並ぶか。値はすべて異なるものとする。

    1. A昇順(小さい順)に並ぶ
    2. B木に挿入した順に並ぶ
    3. C根から近い順(浅い順)に並ぶ
    答えと解説を見る

    正解:A. 昇順(小さい順)に並ぶ

    二分探索木では、どの節についても、左の部分木の値はすべてその節より小さく、右の部分木の値はすべて大きくなっています。そのため、左の部分木、節、右の部分木の順にたどると、小さい値から順に訪れることになり、結果は昇順になります。根から近い順に並ぶのは、段ごとに左から訪れる幅優先(レベル順)のたどり方です。挿入した順は木の形には残りますが、たどり方の順序とは一致しません。

    空の二分探索木に、50, 30, 70, 20, 40, 60, 80 の順に値を挿入した。この木を後行順(帰りがけ順。左の部分木、右の部分木、その節の順に訪れる)でたどったときの順はどれか。

    1. A50, 30, 20, 40, 70, 60, 80
    2. B20, 40, 30, 60, 80, 70, 50
    3. C20, 30, 40, 50, 60, 70, 80
    答えと解説を見る

    正解:B. 20, 40, 30, 60, 80, 70, 50

    根は50で、左の子は30(その子が20と40)、右の子は70(その子が60と80)になります。後行順では、左の部分木の 20, 40, 30、右の部分木の 60, 80, 70 を訪れてから、最後に根の50を訪れます。50, 30, 20, 40, 70, 60, 80 は節を先に訪れる先行順(行きがけ順)、20, 30, 40, … は中間順(通りがけ順)の結果です。後行順は、子を先に処理する必要がある木の削除や、式の木から後置記法を作るときに使われます。

    空の二分探索木に、1, 2, 3, …, 1000 の順に値を挿入した(つり合いをとる操作はしない)。この木で1000を探すとき、根から比べ始めて、見つかるまでに比べる節の数はいくつか。

    1. A10
    2. B500
    3. C1,000
    答えと解説を見る

    正解:C. 1,000

    昇順に挿入すると、新しい値は毎回それまでの最大値の右の子になるので、木は右にだけ伸びた1本の列(高さ999)になります。1000はいちばん下にあるので、1, 2, …, 1000 の1,000個の節と比べることになり、連結リストを先頭からたどるのと同じ O(n) です。つり合いのとれた木なら段の数は約 log₂ 1000 ≈ 10 なので、AVL木や赤黒木のように挿入や削除のたびに形を整える平衡二分探索木を使えば、最悪でも O(log n) を保てます。

    よくある質問

    二分探索木とヒープの違いは何ですか?

    二分探索木は左右の部分木の大小関係が決まっていて、任意の値を探すのに向いています。ヒープは親と子の大小関係だけが決まっていて、最大値(または最小値)をすぐ取り出すのに向いています。ヒープで任意の値を探すには、全体を調べる必要があります。

    中間順でたどると、なぜ小さい順に並ぶのですか?

    中間順では、ある節より先に左の部分木(すべてその節より小さい値)を、後に右の部分木(すべて大きい値)を訪れます。これがすべての節で成り立つので、全体として小さい順になります。

    高さはどう数えますか?

    このツールでは、根だけの木の高さを1とし、段の数を数えます。根からいちばん深い葉までの辺の数で数える方法では、根だけの木の高さは0になります。試験の問題では、どちらの数え方かが問題文で決められています。

    試験ではどのように問われますか?

    基本情報技術者試験などでは、値を順に挿入した二分探索木の形やなぞり順、ヒープを配列で表したときの添字の関係、値を追加したあとの配列の並びがよく問われます。例を選んで、図と配列の並びを自分の答えと比べてみてください。

    関連する用語

    二分探索木 二分ヒープ 二分探索

    関連する計算ツール

    半導体・電子回路・情報の計算ツール →