資格道場 › レッスン一覧 › アルゴリズムとプログラミング
アルゴリズムとプログラミング・11/13・13分

2分探索木とヒープ

ゴール

2分探索木の大小関係・データの挿入・要素の削除と、ヒープへの要素の挿入・ヒープソートの説明を見分けて、過去問の図や選択肢から正しいものを自力で選べるようになる。

2分探索木とヒープは、どちらも「木の形でデータを並べて、探す・取り出す手間を減らす」仕組みです。データベースの索引や、優先度の高い仕事から処理する仕組みの土台になっています。試験では図を見て判定する問題が毎年のように出ますが、ルールは1つずつしかないので、覚えれば確実に得点できます。

このレッスンで稽古する(用語チェック・過去問)

結論:ルールはそれぞれ1行で言える

  • 2分探索木:どの節で見ても 左の部分木の値すべて < その節 < 右の部分木の値すべて
  • ヒープ:どの節で見ても 親 ≦ 子(または親 ≧ 子)。左右の子の大小は決まっていない

2分探索木は「左右」に大小があり、ヒープは「上下」に大小があります。この違いさえ押さえれば、図の問題で迷いません。

2分探索木ヒープ503070小大左 < 親 < 右横方向に大小103020小大親 ≦ 子縦方向に大小・左右は自由
2分探索木は左右の向きに大小があり、ヒープは上下の向きに大小があります(ヒープの左右の子は順不同です)。

木の用語を30秒で

木は、1つの出発点から枝分かれしていくデータの形です。いちばん上を根、子を持たない末端を葉、それぞれの丸を節(ノード)と呼びます。各節の子が最大2つの木を2分木といいます。

ある節から下をまとめたかたまりを部分木と呼びます。左の子から下が「左部分木」、右の子から下が「右部分木」です。2分探索木の条件は、直下の子だけでなく部分木の全員に対して成り立つ必要があります。

2分探索木の大小関係(いちばんよく出る)

2分探索木は数当てゲームに似ています。「50より大きい?」「小さい」「なら25より?」と半分ずつ絞り込むように、根から比べて小さければ左、大きければ右へ進めば目的の値にたどり着きます。

見分けるときのコツ:直下の親子だけを見ると失敗します。たとえば根17の左部分木に18が混ざっていたら、親子の関係が正しく見えても違反です。各節について「自分の祖先の誰よりも、左右の向きとして正しい範囲に入っているか」を確かめます。

大小の順に並べるときは中間順(通りがけ順)、つまり「左部分木 → 自分 → 右部分木」の順に読みます。2分探索木を中間順で読むと、必ず小さい順になります。

        a
      /   \
     b     c
    / \   / \
   d   e f   g

中間順:d → b → e → a → f → c → g(これが小さい順)

なぞり方 順番 上の木で読むと 2分探索木での意味
先行順(行きがけ順) 自分 → 左 → 右 a b d e c f g 特になし
中間順(通りがけ順) 左 → 自分 → 右 d b e a f c g 小さい順になる
後行順(帰りがけ順) 左 → 右 → 自分 d e b f g c a 特になし
1710256182030左部分木左部分木は全員17より小さいはず18は親10とは正しいが17に違反
親の10と子の18だけを見ると正しく見えますが、18は根17の左部分木にいるので2分探索木の条件に違反しています。

挿入:入れる順番で木の形が変わる

挿入は検索と同じ道をたどります。根から「小さければ左、大きければ右」へ進み、空いている場所(葉の下)にそのまま置きます。すでにある節の並びは変えません。

同じデータでも入れる順番が違えば形が変わります。たとえば 1, 2, 3, 4… と小さい順に入れると右へ一直線に伸び、探すのに全部をたどることになります。左右の高さがそろった木なら、探す回数は約 log₂n 回で済みます。

15個の値を入れて完全2分木(すべての段が満杯の木)にする場合、置き場所の配置は1通りに決まりますが、その形になる挿入順は何通りもあります(例:根になる真ん中の値を最初に入れ、次に2段目の2つを入れる、など)。

削除:子が2つあるときだけ要注意

削除する節 やること
葉(子なし) そのまま消す
子が1つ その子(の部分木)を削除した位置に繰り上げる
子が2つ 右部分木の最小値、または左部分木の最大値を削除した位置に移す

子が2つのときに右部分木の最小値を選ぶのは、その値が「左側の全員より大きく、右側の残り全員より小さい」からです。右部分木の最小値は、右の子から左へ左へたどった突き当たりにあります。左部分木の最大値なら、左の子から右へ右へたどります。

12削除10148111315右部分木の最小値13を12の位置へ14から左へ左へたどった突き当たり10や14をそのまま上げるのは誤り
子が2つある12を削除するときは、右の子14から左へたどった突き当たりにある最小値13を、12の位置へ移します。

ヒープ:上ほど小さい(大きい)木

ヒープは「親は子より小さい(または大きい)」という上下の関係だけを守る木です。根には必ず最小値(または最大値)が来るので、いちばん小さいものをすぐ取り出したいときに使います。左右の子同士の大小は決まっていません。

2分探索木 ヒープ
大小の向き 左 < 親 < 右(横方向) 親 ≦ 子(縦方向)
根にある値 決まっていない 最小値(または最大値)
得意なこと 任意の値を探す 最小値・最大値を取り出す
形 挿入順で偏ることがある 上の段から左詰めで埋める

挿入の手順はトーナメントの勝ち上がりに似ています。新しい要素を最後部(最下段の左詰めの次の位置)に置き、親より小さい間は親と入れ替えて上へ進みます。親以上になったところ、または根に着いたところで止まります。

① 最後部に2を置く35896102② 2<8 なので交換35296108③ 2<3 なので交換 → 根で終了253961081回で止めず、親以上か根に着くまで続ける
ヒープに2を挿入すると、最後部から親との入れ替えを2回繰り返し、根に着いたところで止まります。

ヒープソート:ヒープから1つずつ取り出して並べる

ヒープソートは、未整列の部分をヒープ(順序木)にし、根にある最大値(または最小値)を取り出して整列済みの部分へ移す操作を繰り返します。取り出したあとは残りを再びヒープに整えます。

試験では、4種類の整列法の説明文の名前だけを入れ替えた選択肢が出ます。説明文のキーワードで見分けてください。

整列法 説明文のキーワード
ヒープソート 順序木、最大値・最小値を取り出して整列済みへ移す
シェルソート 一定間隔おきの部分列を整列し、間隔を詰めていく
クイックソート 基準値より大きい区分と小さい区分に振り分ける
バブルソート 隣り合う要素を比べて逆なら入れ替える

試験での問われ方

  • 図から2分探索木を選ぶ:直下の親子は正しいのに、孫の位置で祖先との大小が崩れている図が混ざります。
  • 大小関係を並べる:先行順・後行順・逆順の並びが選択肢に入っています。中間順(左→自分→右)で読みます。
  • 挿入後の図を選ぶ:途中の比較を1か所だけ逆にした図が並びます。根から1つずつ比べて道をたどります。
  • 削除:直下の子(10や14)をそのまま上げる選択肢が混ざります。正解は右部分木の最小値か左部分木の最大値です。
  • ヒープへの挿入:入れ替えが1回で止まると考えると間違えます。親以上になるか根に着くまで続けます。
  • 整列法の説明:説明文の名前が入れ替わっています。キーワードで判定します。
例題 1

2分探索木の値を小さい順に並べる

図の木構造は 2 分探索木である。a~g の値の大小関係として,適切なものはどれか。ここで,a~g の値は重複しないものとする。
完全 2 分木(7 節点): a(根) ├ b(左の子) │ ├ d(左) │ └ e(右) └ c(右の子) ├ f(左) └ g(右)

ア a<b<d<e<c<f<g
イ d<b<e<a<f<c<g
ウ d<e<f<g<b<c<a
エ g<f<c<e<d<b<a

出典:令和7年度 基本情報技術者試験 科目A 公開問題 問3

解き方と答えを見る
  1. 2分探索木を中間順(左部分木 → 自分 → 右部分木)で読むと小さい順になる、というルールを使う。
  2. 根 a の左部分木(b, d, e)を先に読む。b の部分木の中間順は d → b → e。
  3. 次に根 a を読む。ここまでで d → b → e → a。
  4. 最後に右部分木(c, f, g)を読む。c の部分木の中間順は f → c → g。
  5. つなげると d<b<e<a<f<c<g。これはイと一致する。
  6. アは先行順に近い並び、エは逆順で、どちらも2分探索木の大小関係とは合わない。

答え:イ(d<b<e<a<f<c<g)

例題 2

2分探索木になっている図を選ぶ

2 分探索木になっている 2 分木はどれか。
2 分木 4 種(ア~エ)。各木の構造は choices に記述。

ア [図] 根 16,左の子 15(その子は左 10・右 14),右の子 19。
イ [図] 根 17,左の子 14(その子は左 10・右 16),右の子 19(その左の子 18)。
ウ [図] 根 18,左の子 16(その子は左 15・右 14),右の子 19(その右の子 20)。
エ [図] 根 20,左の子 18(その子は左 10・右 14),右の子 19(その子は左 15・右 16)。

出典:平成28年度 秋期 基本情報技術者試験 午前 問6

解き方と答えを見る
  1. 各節について「左部分木の全部 < 自分 < 右部分木の全部」を確かめる。
  2. ア:15 の右の子が 14。14<15 なので右側にあるのは違反。
  3. ウ:16 の右の子が 14。14<16 なので違反。
  4. エ:根 20 の右の子が 19。19<20 なので違反。
  5. イ:根 17 の左部分木は 14, 10, 16 で、どれも 17 より小さい。右部分木は 19, 18 で、どれも 17 より大きい。14 の左が 10(<14)、右が 16(>14)。19 の左が 18(<19)。すべての節で条件を満たす。

答え:イ

例題 3

8, 12, 5, 3, 10, 7, 6 の順に挿入した木

空の 2 分探索木に,8, 12, 5, 3, 10, 7, 6 の順にデータを与えたときにできる 2 分探索木はどれか。
選択肢ア~エはいずれも2分木の図(節点は丸囲みの数字)。

ア [図] 根8。左子5(左子3,右子6),右子10(左子7,右子12)
イ [図] 根8。左子5(左子3,右子7(左子6)),右子10(右子12)
ウ [図] 根8。左子5(左子3(右子7),右子6),右子12(左子10)
エ [図] 根8。左子5(左子3,右子7(左子6)),右子12(左子10)

出典:平成23年度 特別試験 基本情報技術者試験 午前 問5

解き方と答えを見る
  1. 8 を根に置く。
  2. 12:12>8 なので右へ。空いているので 8 の右の子になる。
  3. 5:5<8 なので左へ。8 の左の子になる。
  4. 3:3<8 で左へ、3<5 で左へ。5 の左の子になる。
  5. 10:10>8 で右へ、10<12 で左へ。12 の左の子になる(8 の右の子ではない)。
  6. 7:7<8 で左へ、7>5 で右へ。5 の右の子になる。
  7. 6:6<8 で左へ、6>5 で右へ、6<7 で左へ。7 の左の子になる。
  8. できた形は「根8、左5(左3、右7(左6))、右12(左10)」で、エと一致する。

答え:エ

例題 4

子が2つある節 12 を削除する

次の 2 分探索木から要素 12 を削除したとき,その位置に別の要素を移動するだけで 2 分探索木を再構成するには,削除された要素の位置にどの要素を移動すればよいか。
2 分探索木。根 6。6 の左の子 4,右の子 8。4 の左の子 2,右の子 5。2 の左の子 1,右の子 3。8 の左の子 7,右の子 12(削除対象・太線の円)。12 の左の子 10,右の子 14。10 の左の子 9,右の子 11。14 の左の子 13,右の子 15。

ア 9
イ 10
ウ 13
エ 14

出典:平成25年度 春期 基本情報技術者試験 午前 問5

解き方と答えを見る
  1. 12 は左の子 10 と右の子 14 を持つので、右部分木の最小値か左部分木の最大値を移す。
  2. 右部分木の最小値:右の子 14 から左へたどる。14 → 13。13 に左の子はないので最小値は 13。
  3. 左部分木の最大値:左の子 10 から右へたどる。10 → 11。最大値は 11。
  4. 選択肢にあるのは 13 だけ(11 はない)。
  5. 確認:13 を 12 の位置に移すと、左側(10, 9, 11)はすべて 13 より小さく、右側(14, 15)はすべて 13 より大きい。条件が崩れない。
  6. 10 や 14 をそのまま上げると、その子の付け替えが必要になり、「移動するだけ」では再構成できない。

答え:ウ(13)

例題 5

親<子のヒープに 7 を挿入したとき、A の位置に来る要素

親の節の値が子の節の値より小さいヒープがある。このヒープへの挿入は,要素を最後部に追加し,その要素が親よりも小さい間,親と子を交換することを繰り返せばよい。次のヒープの*の位置に要素7を追加したとき,Aの位置に来る要素はどれか。
二分木。根9。9の子は左11,右14。11の子は左24,右25(二重丸で,Aと記されている)。14の子は左19,右28。24の子は左29,右34。*は25の左下(点線で25とつながる,25の子の位置)。

ア 7
イ 11
ウ 24
エ 25

出典:基本情報技術者試験 科目A免除 修了試験 20170122 実施分 問6

解き方と答えを見る
  1. 7 を最後部の*(25 の子の位置)に置く。
  2. 1回目:7<親の 25 なので入れ替え。7 が A の位置へ、25 が下へ。
  3. 2回目:7<親の 11 なので入れ替え。7 が 11 の位置へ、11 が A の位置へ下りる。
  4. 3回目:7<親の 9 なので入れ替え。7 が根へ、9 が元の 11 の位置へ下りる。
  5. 7 は根に着いたので終了。このとき A の位置には 11 がある。
  6. 入れ替えが1回で止まると考えると A=7、入れ替えないと考えると A=25 を選んでしまう。

答え:イ(11)

要点(試験直前に読む)

  • 2分探索木はどの節でも「左部分木の全部<自分<右部分木の全部」。直下の子だけでなく孫以下も確かめる。
  • 2分探索木を中間順(左→自分→右)で読むと小さい順になる。
  • 挿入は根から「小さければ左・大きければ右」とたどり、空いた場所に葉として置く。挿入順で形が変わる。
  • 子が2つある節を削除するときは、右部分木の最小値(右の子から左へたどった突き当たり)か左部分木の最大値を移す。
  • ヒープ(親<子)への挿入は、最後部に置いて親より小さい間は上と入れ替え、根に着くか親以上になれば止める。
  • ヒープソートのキーワードは「順序木」「最大値・最小値を取り出して整列済みへ移す」。

ひっかけ

  • 直下の親子は正しいのに、孫の位置で祖先との大小が崩れている図 → 各節について部分木の全員を確かめる。
  • 先行順・後行順・逆順の並びが選択肢に入っている → 2分探索木で小さい順になるのは中間順だけ。
  • 削除で直下の子(10や14)を上げる選択肢 → 移すのは右部分木の最小値(または左部分木の最大値)。
  • ヒープへの挿入で入れ替えを1回で止める → 親以上になるか根に着くまで繰り返す。
  • 整列法の説明文の名前が入れ替わっている → 順序木=ヒープ、間隔=シェル、基準値=クイック、隣り合う=バブルで判定する。

用語(17)

2分木 にぶんぎ
各節の子が最大2つ(左の子・右の子)までの木構造。
⚠ 2分探索木は、2分木に「左<親<右」の大小条件を加えたもの。形が2分木でも、大小条件がなければ2分探索木ではない。
根 ね(ルート)
木のいちばん上にある、親を持たない節。
⚠ 葉は反対に、子を持たない末端の節。
葉 は(リーフ)
子を1つも持たない末端の節。
⚠ 根と取り違えないこと。2分探索木の挿入では、新しい値は必ず葉として加わる。
節(ノード) せつ(node)
木を構成する1つ1つのデータの入れ物。
部分木 ぶぶんぎ
ある節の左右どちらかの子を根として、その下をまとめた木。
⚠ 直下の子1つだけではなく、その子孫全員を含む。2分探索木の条件は部分木の全員に対して確かめる。
2分探索木 にぶんたんさくぎ(binary search tree)
どの節でも、左部分木の値はすべて節より小さく、右部分木の値はすべて節より大きい2分木。
⚠ ヒープは上下(親と子)の大小、2分探索木は左右の大小。根に最小値が来るのはヒープ。
完全2分木 かんぜんにぶんぎ
最下段以外の段がすべて埋まり、最下段は左から詰めて並ぶ2分木(15個なら4段がちょうど満杯になる)。
⚠ 2分探索木で完全2分木になる値の配置は1通りだが、その形になる挿入順は複数ある。
中間順(通りがけ順) ちゅうかんじゅん(in-order)
左部分木 → 自分 → 右部分木 の順に節をたどる方法。2分探索木では小さい順になる。
⚠ 先行順は自分が最初、後行順は自分が最後。2分探索木の値を小さい順に並べるのは中間順だけ。
先行順(行きがけ順) せんこうじゅん(pre-order)
自分 → 左部分木 → 右部分木 の順に節をたどる方法。
⚠ 中間順と取り違えやすい。自分(親)を最初に読むのが先行順。
後行順(帰りがけ順) こうこうじゅん(post-order)
左部分木 → 右部分木 → 自分 の順に節をたどる方法。
⚠ 自分(親)を最後に読むのが後行順。最後に根が来る。
ヒープ heap
どの親も子より小さい(または大きい)という上下の関係を保ち、上の段から左詰めで埋めた2分木。
⚠ 2分探索木と違い、左右の子の大小は決まっていない。根に最小値(最大値)が来る。
ヒープへの挿入 ひーぷへのそうにゅう
最後部に要素を置き、親より小さい(親<子のヒープの場合)間は親と入れ替えて上へ進める操作。
⚠ 2分探索木への挿入は根から下へたどって葉に置く。ヒープは最後部に置いてから上へ上がる。
順序木 じゅんじょぎ
親子の間に一定の大小関係を保った木。整列法の説明文ではヒープのことを指す。
⚠ 選択肢に「順序木」とあればヒープソートの説明。
ヒープソート heap sort
未整列部分をヒープにし、根の最大値(最小値)を取り出して整列済み部分へ移すことを繰り返す整列法。
⚠ 一定間隔おきに整列するのはシェルソート、基準値で振り分けるのはクイックソート、隣同士を入れ替えるのはバブルソート。
シェルソート shell sort
一定間隔おきに取り出した要素の部分列を整列し、間隔を詰めながら最後は間隔1で整列する方法。
⚠ 「間隔」がキーワード。クイックソートの説明と入れ替えられやすい。
クイックソート quick sort
基準値を決めて、大きい値の区分と小さい値の区分に振り分け、各区分で同じ処理を繰り返す方法。
⚠ 「基準値」「区分」がキーワード。バブルソートの説明と入れ替えられやすい。
バブルソート bubble sort
隣り合う要素を比べ、大小が逆なら入れ替える操作を繰り返す方法。
⚠ 「隣り合う」がキーワード。シェルソートの説明と入れ替えられやすい。

このレッスンの過去問

このレッスンで稽古する