応用情報技術者試験 合格教科書|2026年度(令和8年度)対応
第 3 章|科目 A 直近 10 年平均 3.5 問/科目 B は直近 19 回すべて問 3 に出題 科目 B: プログラミング(アルゴリズム)

アルゴリズムとプログラミング

データ構造とアルゴリズムを動く図で追い、計算量と擬似言語の読み方を身につける

この章で学ぶこと

科目 A は直近 10 年 19 回で 66 問、1 回平均 3.5 問。3 問確保が目標です。科目 B は直近 19 回すべて「問 3」がプログラミングで、本章がその土台になります(解き方の実戦は第 24 章)。

配列とリスト ― 格納の仕方でコストが変わる

データ構造を選ぶ基準は「どの操作を速くしたいか」の一点です。配列は添字の計算だけで任意の要素へ一発で届く代わりに、途中に要素を割り込ませると後続を全部ずらす必要があります。連結リストはポインタを張り替えるだけで割り込めますが、n 番目の要素に届くには先頭から順にたどるしかありません。この裏返しの関係が、科目 A では「配列実現とポインタ実現の長所短所を入れ替えた誤答肢」として繰り返し出題されています。

配列 ― 添字から位置を計算する

配列は同じ型の要素をメモリ上の連続領域に並べたものです。要素 1 個の大きさを L、先頭アドレスを a とすると、添字 i(0 始まり)の要素は a + L × i にあります。たどる必要がないので、要素数がいくら増えてもアクセス時間は変わりません。宣言時に大きさが決まる静的配列と、実行時に確保・拡張できる動的配列があります。

多次元配列も、実体は 1 次元の連続領域です。2 次元配列を「行を単位に前から並べる」置き方を行優先(row-major)といい、科目 B では盤面やグラフを 1 次元配列に載せる添字式(div と mod)が定番の論点になります。直近 10 年の科目 B 問 3 では、この mod/div による添字計算が 3 回、より広く「配列によるデータ表現と添字操作」が 19 回中 17 回で問われました。

計算の型: 2 次元を 1 次元配列に写す添字式

列数 C の 2 次元配列 A[i, j](i, j とも 1 始まり)を 1 次元配列 B に行優先で写すと、B[(i − 1) × C + j] が対応する。逆向きは、p = 要素番号 − 1 として 行 = p div C + 1、列 = p mod C + 1。

  1. 例題: 9 × 9 の盤面を 1 次元配列(要素番号 1〜81)に行優先で載せた。要素番号 40 は何行何列か
  2. 0 始まりに直す: p = 40 − 1 = 39
  3. 行 = 39 div 9 + 1 = 4 + 1 = 5
  4. 列 = 39 mod 9 + 1 = 3 + 1 = 4
  5. 答え: 5 行 4 列。検算は (5 − 1) × 9 + 4 = 40 で元に戻ること
ここがひっかけ 1 始まりか 0 始まりかを混ぜると、答えが 1 だけずれます。科目 B の擬似言語は配列の要素番号が 1 始まりなので、div/mod を使う前に必ず 1 を引いて 0 始まりに直し、最後に 1 を足して戻します。

リスト ― ポインタを張り替える

線形リスト(リンク付リスト)は、値と「次の節点を指すポインタ」を持つ節点をつないだ構造です。次だけを持つものが単方向リスト、前後両方を持つものが双方向リスト、末尾のポインタが先頭に戻るものが環状リストです。挿入・削除の本体はポインタの書換えだけで、要素数にも位置にも依存しない一定コストで終わります(図 3-1)。

① 元のリスト: 各節点は「値」と「次へのポインタ」を持つ 節点 A 節点 B 節点 C ② 新節点 X を確保し、X.next ← C(この時点ではまだ壊れない) 新節点 X ③ B.next ← X に付け替える。× の元リンクは自然に外れる × 書き換えたポインタは 2 本だけ。要素数 n がいくつでも手数は変わらない
図 3-1 単方向リストへの挿入。② と ③ の順序を逆にすると C 以降が迷子になるため、必ず「新節点の next を先に決めてから、直前の節点の next を書き換える」順で行います。

ただし「挿入自体は一定コスト」であって、挿入位置を見つけるまでのコストは別勘定です。単方向リストで末尾の節点を削除するには、末尾の 1 つ前までポインタをたどる必要があり、これがリスト操作の中でたどる回数が最も多くなります。双方向リストなら前の節点をすぐ得られるので、途中の節点を削除するときに書き換えるポインタは前後 2 本だけです。

操作・性質配列で実現ポインタ(連結リスト)で実現
i 番目へのアクセス添字計算 1 回、O(1)先頭から i 回たどる、O(n)
途中への挿入・削除後続を全部ずらす、O(n)ポインタ 1〜2 本の書換え、O(1)
末尾の削除添字で直接、O(1)単方向は末尾の 1 つ前までたどる(最多)
記憶領域連続領域を先に確保。未使用領域が生じる必要な分だけ確保。ポインタの分だけ余計に要る
要素数の増減上限を超えると再確保が要る上限なし(メモリの許す限り)
出題実績 線形リストの特徴と操作は直近 10 年で 3 回。令和 2 年 10 月は「ポインタ実現の挿入コストは要素数・位置によらず一定」、令和元年秋は「ポインタをたどる回数が最も多い操作は末尾の削除」、令和 4 年春は「配列実現では未使用領域が生じる」が正解でした。加えて令和 5 年秋には双方向リストの挿入後の next・prev を答えさせる読解型が出ています。

スタックとキュー ― LIFO / FIFO と逆ポーランド記法

スタックは最後に入れたものを最初に取り出す LIFO(Last In First Out)、キューは最初に入れたものを最初に取り出す FIFO(First In First Out)です。スタックへの格納がプッシュ、取出しがポップ、キューへの格納がエンキュー、取出しがデキューです。どちらも「取り出せるのは端の 1 つだけ」という制約がある代わりに、操作が O(1) で済みます。

構造取出しの規則試験で問われる用途
スタック(LIFO)最後に入れたものから関数呼出しの戻り番地・局所変数、再帰、深さ優先探索、逆ポーランド式の評価、括弧の対応検査
キュー(FIFO)最初に入れたものから幅優先探索、印刷ジョブや通信バッファの待ち行列、生産者・消費者の受渡し

同じ木を探索しても、次に見る節点をスタックで管理すれば深さ優先探索、キューで管理すれば幅優先探索になります。データ構造を差し替えるだけで探索順序が変わるという関係は、科目 B でも 4 回問われている頻出の対比です。根 A の子が B・C、B の子が D・E、C の子が F・G という木(後出の図 3-4 と同じ形)で、取り出した節点の子を入れながら 1 手ずつ進めると次のようになります。スタックは先に取り出したい方を後に積むので子を右 → 左の順にプッシュ、キューは子を左 → 右の順にエンキューします。

手順スタックで管理(深さ優先): 取り出す節点/残りの中身キューで管理(幅優先): 取り出す節点/残りの中身
1A / C・B(次に出るのは上の B)A / B・C(次に出るのは先頭の B)
2B / C・E・D(次は D)B / C・D・E
3D / C・EC / D・E・F・G
4E / CD / E・F・G
5C / G・F(次は F)E / F・G
6F / GF / G
7G / 空になったので終了G / 空になったので終了
訪問順A → B → D → E → C → F → G(先行順)A → B → C → D → E → F → G(レベル順)

どちらも終了条件は「スタック(キュー)が空になったとき」で、科目 B ではこの 1 行がそのまま穴埋めになります。あわせて、一度訪れた節点を再び入れない訪問済み管理の配列を用意するのが、グラフを探索するときの定型です。

スタックで作れる出力順列

A、B、C をこの順に 1 回ずつプッシュするとして、プッシュとポップは任意の順で交ぜてよいとき、取り出せる順列は何通りでしょうか。3 個の並べ方は 3! = 6 通りですが、スタックでは実現できない並びが 1 つあります(図 3-2)。

A → B → C の順にプッシュし、途中で任意にポップする(上が新しい) ① 3 個プッシュした状態 C B A ② ポップ → C を出力 B A ③ 次に出せるのは上の B だけ B A A は B の下 C を先に出したら、残りは B → A の順にしか出せない。だから CAB は作れない 得られる出力順列は 5 通り: ABC・ACB・BAC・BCA・CBA
図 3-2 スタックの出力順列。「先に入れたものほど下に沈む」ので、いったん飛び越して取り出した要素より下にあるものは、必ずその後に、上から順に出てきます。
出題実績 スタックの出力順列は直近 10 年で 3 回(平成 28 年春・令和 3 年春・令和 7 年春)、いずれも問 5 で正解は 5 通りでした。誤答肢は 3! = 6 通り、4 通り、7 通りです。

逆ポーランド記法(後置記法)

演算子を 2 つの被演算子の後ろに書く記法を逆ポーランド記法(後置記法)といいます。括弧が不要になり、スタックだけで機械的に評価できるのが利点です。中置式からの変換は、式を木にして後行順(左部分木 → 右部分木 → 根)でたどるのが確実です。

中置: 3 + 4 × 2      式の木(× が + より優先なので × が下に来る)

          +
        /    \
       3      ×
            /   \
           4     2

後行順(左 → 右 → 根): 3 → 4 → 2 → × → +
後置式: 3 4 2 × +

評価は、記号を左から 1 つずつ読み、数値ならプッシュ、演算子ならスタックの上位 2 つをポップして計算し、結果をプッシュするだけです(図 3-3)。

後置式 3 4 2 × + を左から 1 記号ずつ読む。数値はプッシュ、演算子は上位 2 つで計算 ① 3 をプッシュ 3 ② 4 をプッシュ 4 3 ③ 2 をプッシュ 2 4 3 ④ × : 4 × 2 = 8 8 3 ⑤ + : 3 + 8 = 11 11 最後にスタックに残った 1 個の値が式の値(11) 減算・除算は「後にプッシュした方が右の被演算子」。A B - は A - B であって B - A ではない
図 3-3 後置式のスタック評価。演算子を読むたびにスタックの高さが 1 減る(2 個ポップして 1 個プッシュ)ので、正しい式なら最後にちょうど 1 個残ります。
出題実績 逆ポーランド記法は直近 10 年で 4 回(平成 28 年秋・令和 2 年 10 月・令和 5 年秋・令和 6 年秋)、4 回とも問 3 でした。中置から後置への変換が 2 回、スタックの状態から次の演算を読む問題と、後置式に値を入れて評価する問題が各 1 回です。

木構造 ― 表現・巡回・2 分探索木の操作

木は、根から枝をたどって葉に至る階層構造です。ある節点から見て上が親、下が子で、子を高々 2 個しか持たない木を 2 分木、3 個以上を許すものを多分木といいます。子の並び順に意味がある木が順序木です。根の深さを 0 とすると深さ k の節点は最大 2k 個です。完全 2 分木は、最下段を除くすべての深さが埋まっていて、最下段は左から詰めて並んでいる木をいいます。とくにすべての深さが埋まっているとき(葉の深さがすべて等しいとき)は、節点数 n と高さ h の間に n = 2h+1 − 1 が成り立ちます(n = 7 なら h = 2)。木の高さが log2 n 程度に収まることが、探索を速くする根拠です。

配列表現と 3 つの巡回順序

完全 2 分木はポインタを使わずに配列だけで表せます。根を要素番号 1 とすると、節点 i の左の子は 2i、右の子は 2i + 1、親は i div 2 です。この配列を添字の小さい順に見ていく処理は幅優先探索(レベル順)に一致します(図 3-4)。一方、再帰でたどる順序には、根をいつ訪れるかで先行順・中間順・後行順の 3 種類があります。

完全 2 分木(節点 7 個・高さ 2) A B C D E F G 深さ 0 が根、深さ 2 が葉 配列表現(根が要素番号 1) A B C D E F G 1 2 3 4 5 6 7 左の子 = 2i、右の子 = 2i + 1、親 = i div 2 添字順に読む = 幅優先探索 先行順(根左右): A B D E C F G 中間順(左根右): D B E A F C G 後行順(左右根): D E B F G C A
図 3-4 2 分木の配列表現と巡回順序。3 つの巡回はいずれも深さ優先で、根をどこで訪れるか(先・中・後)だけが違います。幅優先は配列の添字順そのものです。
出題実績 2 分木の配列表現は直近 10 年で 2 回(平成 29 年秋・令和 3 年春)出題され、いずれも「配列を添字順に調べる操作は何に相当するか」で正解は幅優先探索でした。誤答肢は深さ優先探索・先行順・中間順・後行順です。

2 分探索木とその操作

2 分探索木は「左部分木のすべての値 < 節点の値 < 右部分木のすべての値」を保つ木です。探索は根から比較して片側へ降りるだけなので、木が平衡していれば O(log n) で済みます。中間順でたどると値が昇順に並ぶのも、この定義から出る性質です。

削除は 3 通りに場合分けします。葉ならそのまま外し、子が 1 個なら子を繰り上げ、子が 2 個なら「右部分木の最小値」(中間順で次に来る値=後継)を削除位置へ昇格させます(図 3-5 左)。左部分木の最大値を昇格させても条件は保たれますが、試験では後継を使う形で問われています。

挿入を繰り返すと木が一方向に伸びて O(n) に劣化するため、左右部分木の高さの差を 1 以下に保つのが AVL 木です。差が 2 になった時点で回転して平衡を戻します(図 3-5 右)。

2 分探索木から 30 を削除する 20 10 30 25 40 子が 2 個 右部分木の最小値 ① 削除する 30 は子を 2 個持つ ② 後継 25 を 30 の位置へ昇格させる AVL 木: 高さの差が 2 になったら回転 3 2 1 ① 1 を挿入して 3 の左右の高さの差が 2 右回転 2 1 3 ② 単回転で 2 を根に持ち上げると平衡が戻る
図 3-5 左: 2 分探索木の削除。昇格させるのは右部分木の最小値(中間順で 30 の次に来る値)です。昇格後の木は 20 を根に 10 と 25 が並び、25 の下に 40 が付く形になります(25 は葉なので元の位置はそのまま空きます)。右: AVL 木の単回転。並びが一直線なら単回転、途中で折れているなら二重回転になります。

B 木・ヒープ

B 木は 1 つの節点に複数のキーと複数の子を持たせた多分木で、木の高さを低く抑えられるためディスクアクセス回数が減り、データベースのインデックスに使われます(第 9 章)。ヒープは「親の値 ≧ 子の値」(最大ヒープ)を全節点で保つ完全 2 分木で、根が常に最大値になります。配列表現と相性がよく、優先度付きキューやヒープソートの土台です。

根を取り出したあとにヒープの条件を回復させる操作がヒープの再構成で、手順は 3 つです。

  1. 根(最大値)を取り出す
  2. 最後尾の節点を根の位置へ移す
  3. 根から下へ、子のうち大きい方と比べ、親の方が小さければ交換する。交換が起きなくなるまで繰り返す

比較は木の高さのぶんしか起きないので 1 回の再構成は O(log n)、これを要素数ぶん繰り返すヒープソートは全体で O(n log n) になります。

木の種類保つ条件主な用途・性質
2 分探索木左 < 節点 < 右探索・挿入・削除が平均 O(log n)。偏ると O(n)
AVL 木(バランス木)左右部分木の高さの差 ≦ 1回転で平衡を維持し、最悪でも O(log n)
B 木全葉が同じ深さ、節点あたり複数キー高さが低くディスク I/O が少ない。DB のインデックス
ヒープ親 ≧ 子(または親 ≦ 子)根が最大(最小)。優先度付きキュー、ヒープソート
出題実績 木構造は直近 10 年で 7 問。うち直近 3 年は操作を追わせる型に移り、令和 6 年秋に 2 分探索木の削除(正解は右部分木の最小値 13)、令和 7 年春に AVL 木の回転後の形が出ています。

探索は直近 10 年で 10 問と、この中分類で最も点になる論点です。問われるのは手順の暗記ではなく比較回数の式と前提条件なので、下の 4 つを式ごと覚えます。

探索法前提比較回数(n 件)
線形探索なし(未整列でよい)平均 (n + 1) ÷ 2、最悪 n。O(n)
ブロック分割探索ブロックの代表値が順に並ぶ平均 m ÷ 2 + n ÷ (2m)(m = ブロックの大きさ)
2 分探索キーで整列済み最大 ⌈log2(n + 1)⌉。O(log n)
ハッシュ表探索ハッシュ関数と衝突対策衝突が少なければデータ数によらずほぼ一定。O(1)

線形探索は先頭から順に比べるだけです。目的のデータが必ず表にあるなら、1 回目で見つかる確率も n 回目で見つかる確率も等しいので、平均比較回数は (n + 1) ÷ 2 になります。配列の末尾に探索キーと同じ値をあらかじめ置く番兵を使うと、「末尾に達したか」の判定が不要になり、ループ 1 回あたりの比較が 2 回から 1 回に減ります。

2 分探索は整列済みの配列の中央と比べ、大小に応じて探索範囲を半分に捨てます。1 回の比較で候補が半分になるので、n 件なら最大 ⌈log2(n + 1)⌉ 回です。n = 1,000 なら log2 1001 ≒ 9.97 なので 10 回で必ず決着します。整列済みでなければ使えない点が、誤答肢を作るときの定番の落とし穴です。

ブロック分割探索の比較回数

ブロック分割探索は、n 件を m 件ずつのブロックに分け、まずブロックの代表値を線形探索して目的のブロックを決め、次にそのブロック内を線形探索します。2 段階どちらも線形探索なので、平均は「それぞれの平均の和」になります(図 3-6)。

① 代表値を先頭から線形探索: 平均 n ÷ (2m) 回 ブロック 1 ブロック 2 ブロック 3 ブロック 4 … 全 n ÷ m ブロック 1 2 3 … m ② そのブロックの中を線形探索: 平均 m ÷ 2 回 平均比較回数 = m ÷ 2 + n ÷ (2m)
図 3-6 ブロック分割探索。ブロック間の平均とブロック内の平均を「足す」のがポイントで、どちらか片方の ÷ 2 を落とした式が誤答肢になります。

計算の型: ブロック分割探索の平均比較回数

平均比較回数 = m ÷ 2 + n ÷ (2m)(n: 全件数、m: 1 ブロックの件数)

  1. 例題: n = 10,000 件を m = 100 件ずつに分けたときの平均比較回数は
  2. ブロック内の平均: m ÷ 2 = 100 ÷ 2 = 50 回
  3. ブロック数は n ÷ m = 100 個。その線形探索の平均は 100 ÷ 2 = 50 回(= n ÷ (2m))
  4. 答え: 50 + 50 = 100 回。線形探索の平均 5,000 回に比べて 50 分の 1
  5. ちなみに m = √n のとき合計が最小になり、その値は √n(この例では 100)
出題実績 ブロック分割探索の平均比較回数は直近 10 年で 2 回(平成 30 年春・令和 7 年秋)、同一問題です。正解は m ÷ 2 + n ÷ (2m) で、誤答肢はどちらかの ÷ 2 を落とした式でした。

ハッシュ表探索と衝突

ハッシュ表探索は、キー x をハッシュ関数 h(x) に通して得た値を格納位置にします。位置を「計算で決める」ので、比較しながら絞り込む必要がなく、データ数が増えても探索時間はほとんど変わりません。試験では剰余法 h(x) = x mod n が使われ、異なるキーが同じ位置に割り当てられる衝突(シノニムの発生)の条件が繰り返し問われます(図 3-7)。

剰余法 h(x) = x mod 13。キー 20 と 33 はどちらもハッシュ値 7 になる 20 33 0 13 26 39 余り 7 余り 7 20 = 13 × 1 + 7 なので 20 mod 13 = 7 33 = 13 × 2 + 7 なので 33 mod 13 = 7 33 − 20 = 13(13 の倍数)だから 2 つのキーは同じ場所で衝突する
図 3-7 剰余法における衝突。除数 13 の目盛で区切ったとき、同じ区間内の同じ位置に落ちるキー同士が衝突します。つまり衝突条件は「2 つのキーの差が除数の倍数であること」です。
覚え方 h(x) = x mod n で a と b が衝突する ⇔ a − b が n の倍数。「和ではなく差」「それぞれが倍数ではなく、差が倍数」の 2 点だけ押さえれば、この論点は落としません。逆に「複数のキーがすべて衝突する除数を求めよ」と問われたら、キーどうしの差の公約数を探します。

衝突が起きたときの対策(シノニム対策)は 2 系統です。チェイン法(オープンハッシュ法)は同じ位置に来たキーを連結リストでつなぎます。オープンアドレス法(クローズドハッシュ法)は別の空き位置を再計算して入れる方式で、線形探査法などがあります。どちらもデータが詰まってくる(占有率が高くなる)ほど探索が遅くなるので、実務では表を余裕をもって確保します。

出題実績 ハッシュ関数の衝突は直近 10 年で 4 回(平成 30 年秋・令和元年秋・令和 4 年秋・令和 6 年秋)。3 回は「a − b が n の倍数」を選ばせる同一問題、平成 30 年秋は逆に「571・1168・1566 がすべて衝突する除数」を差の公約数から求めさせる問題でした。

整列アルゴリズム ― 途中状態で見分ける

整列は科目 A で 10 年 7 問。うちバブルソートが 4 問で、単一テーマとしてはこの中分類で最多です。近年は「説明文からアルゴリズム名を選ぶ」型に加えて、流れ図や整列途中の状態から名前を当てる読解型が増えました。手順を丸暗記するより、1 パスで何が確定するかと何と何を比べるかの 2 点で見分けるのが確実です(図 3-8)。

初期配列 5 2 4 1 3 に 1 パスだけ適用した結果を並べる 初期 5 2 4 1 3 バブル 2 4 1 3 5 隣接どうしを比べて交換 → 末尾に最大 5 が確定 選択 1 2 4 5 3 全体から最小値を探して先頭と交換 → 先頭に 1 が確定 挿入 2 5 4 1 3 2 を整列済み部分に差し込む → 先頭 2 個が整列済み
図 3-8 3 つの整列法の 1 パス目。バブルは「隣接だけを見て末尾を確定」、選択は「全体を見て先頭を確定」、挿入は「前方の整列済み部分に差し込む」。この 3 点セットで同定できます。

残る 4 つは次のとおりです。シェルソートは、離れた要素どうしの挿入ソートを間隔を縮めながら繰り返し、大きなずれを先に解消します。クイックソートは基準値(ピボット)より小さい群と大きい群に分けて、それぞれを再帰的に整列する分割統治法です。マージソートは列を半分ずつに分割し、整列済みの 2 列を併合して戻します。ヒープソートはヒープを構成して根(最大値)を取り出し、残りをヒープに再構成する処理を繰り返します。

整列法1 パスで確定するもの・特徴平均最悪安定
バブル隣接 2 個を比較・交換。末尾から確定O(n2)O(n2)安定
選択未整列部分の最小値を選び先頭と交換O(n2)O(n2)不安定
挿入整列済み部分の正しい位置に差し込むO(n2)O(n2)安定
シェル間隔を縮めながら挿入ソートを繰り返す実装依存(O(n1.3) 程度)O(n2)不安定
クイックピボットで 2 分割して再帰(分割統治)O(n log n)O(n2)不安定
マージ分割して整列し併合(分割統治)O(n log n)O(n log n)安定
ヒープヒープの根を取り出して再構成O(n log n)O(n log n)不安定

安定な整列とは、キーが等しい要素どうしの元の並び順が整列後も保たれるものをいいます。バブル・挿入・マージは安定、選択・シェル・クイック・ヒープは不安定です。「支店コードで並べ替えたあと売上額で並べ替える」ように多段のキーで並べ替えるときに安定性が効きます。

覚え方 O(n log n) 組(クイック・マージ・ヒープ)は「半分に割る」か「木の高さ」が中にあります。逆に O(n2) 組(バブル・選択・挿入)は二重ループそのものです。クイックだけは最悪 O(n2)(毎回ピボットが端に寄る場合)という例外を必ずセットで覚えます。
出題実績 バブルソートは直近 10 年で 4 回(令和 3 年秋・令和 4 年秋・令和 5 年秋・令和 6 年春)。うち 2 回は「隣接する要素を比較・交換する」という説明文を選ぶ知識型、残り 2 回は流れ図や整列途中の状態からアルゴリズム名を同定させる読解型でした。誤答肢は毎回、選択・挿入・クイックの説明です。

再帰・分割統治・動的計画法とグラフ

再帰とは、手続の中で自分自身を呼び出すことです。正しい再帰の定義には必ず ① それ以上呼び出さずに値を返す停止条件と ② 引数が停止条件へ近づく呼出しの 2 つが要ります。階乗の定義なら「n = 0 のとき 1、それ以外は n × fact(n − 1)」で、この形をそのまま選ばせる問題が 10 年で 2 回出ています。

○整数型: fact(整数型: n)
  if (n が 0 と等しい)      /* 停止条件 */
    return 1
  else
    return n × fact(n - 1)  /* 引数が 1 ずつ 0 へ近づく */
  endif

再帰呼出しはスタック(LIFO)で実現されます。呼び出すたびに戻り番地・引数・局所変数の組(スタックフレーム)が積まれ、停止条件に達すると積んだ逆順に戻りながら計算が確定します(図 3-9)。科目 B の講評でも「呼出し元へ戻った後の引数を再現できない」誤答が名指しされており、戻りの追跡こそが得点差になります。

fact(n): n が 0 なら 1、そうでなければ n × fact(n − 1) 呼び出すたびに戻り番地と引数が積まれ、停止条件に達すると逆順に戻る(LIFO) ① fact(3) を呼ぶ fact(3) ② fact(2) を積む fact(3) fact(2) ③ fact(1) を積む fact(3) fact(2) fact(1) ④ fact(0) が停止条件 fact(3) fact(2) fact(1) fact(0)→1 ⑤ 戻りながら確定 fact(0) = 1 fact(1) = 1×1 = 1 fact(2) = 2×1 = 2 fact(3) = 3×2 = 6 スタックの深さ = 再帰の深さ。停止条件を書き忘れると積み続けてあふれる
図 3-9 fact(3) のコールスタック。積む向き(引数が小さくなる)と戻る向き(値が確定する)が逆であることが、再帰を読むときの唯一のコツです。

再帰で書ける典型としてハノイの塔があります。n 枚の円盤を移す最小手数は 2n − 1 回で、「n − 1 枚を退避 → 最大の 1 枚を移す → n − 1 枚を戻す」という 2 回の再帰から導けます。フィボナッチ数列を素朴な二重再帰で書くと同じ部分問題を何度も計算して指数時間になるため、後述の動的計画法で表に記録します。

分割統治法と動的計画法

分割統治法は、問題を小さな部分問題に分割し、それぞれを独立に解いてから結果を結合する設計法です。クイックソート・マージソート・2 分探索がこの型です。一方動的計画法は、部分問題が重なり合うときにいったん解いた部分問題の答えを表に記録して再利用します。「独立に解く」のが分割統治、「解を使い回す」のが動的計画法という対比で覚えます。

手順の型: 動的計画法の 5 ステップ

  1. 分割: 元の問題を「小さい添字の同種の問題」に言い換える
  2. 表の定義: 表の各要素が何を表すかを 1 文で決める(例: L[i, j] = 先頭 i 文字と先頭 j 文字の最長共通部分列の長さ)
  3. 更新式: L[i, j] を、既に求めた L[i − 1, j − 1] や L[i − 1, j] などから決める漸化式を書く
  4. 埋める順序: 更新式が参照する要素が先に埋まる順(多くは左上から右下へ)に走査する
  5. 読み出し: 答えが入っている位置(多くは右下)を指定する
出題実績 分割統治法は直近 10 年で 2 回(令和元年秋・令和 3 年春)。「分割統治法を採用した整列」の正解はクイックソート、説明文の正解は「小さな問題に分割して独立に解き結合する」でした。科目 B では動的計画法が 2 回(平成 29 年秋のナップザック問題、令和 7 年秋の最長共通部分列)出ています。

グラフのアルゴリズムと計算量

グラフは節点(ノード)と辺(エッジ)の集合です。表現は 2 通りで、隣接行列は節点数 n の n × n 表に辺の有無を持つため辺が多いグラフ(密グラフ)向き、隣接リストは各節点が「つながっている節点の並び」を持つため辺が少ないグラフ(疎グラフ)向きです。探索は木と同じで、スタックを使えば深さ優先探索、キューを使えば幅優先探索になります。重み付きグラフの最短経路は、確定済みの節点から近い順に確定していくダイクストラ法が代表で、負の重みがある場合はベルマンフォード法を使います。文字列照合の高速化には KMP 法(クヌース・モリス・プラット法)や BM 法(ボイヤ・ムーア法)があります。

記法・用語意味代表例
O(1)データ量によらず一定配列の添字アクセス、ハッシュ表探索
O(log n)データが倍でも手数は 1 増えるだけ2 分探索、平衡木の探索
O(n)データ量に比例線形探索、リストの走査
O(n log n)分割統治や木の高さ × 全要素クイック・マージ・ヒープソート
O(n2)二重ループバブル・選択・挿入ソート、隣接行列の全走査

O 記法は「入力を大きくしたときの増え方」だけを表し、定数倍や下位の項は無視します。同じ問題でも最良・平均・最悪で計算量が変わることがあり(クイックソートは平均 O(n log n)・最悪 O(n2))、試験ではどのケースを聞かれているかを必ず確認します。近似アルゴリズム(厳密解の代わりに十分よい解を短時間で得る)、モンテカルロ法などの確率アルゴリズム、遺伝的アルゴリズム、ハフマン法・ランレングス法などのデータ圧縮アルゴリズム、Z バッファ法・スキャンライン法・レイトレーシング法などの 3 次元図形処理アルゴリズムも、シラバスには用語として並びます。

このほかシラバスには、バッチ処理で使うファイル処理のアルゴリズム(キーの切れ目で小計を出すコントロールブレーク処理、桁揃えやゼロ抑制で出力形式を整える編集処理)、自然言語処理のアルゴリズム(形態素解析・構文解析・意味解析・文脈解析・係り受け解析・n-gram・文章間類似度)、OS の記憶域管理アルゴリズム(空きメモリ管理のためのデータ構造と、メモリの割当て・解放。best-fit などの詳細は第 6 章)が用語例として並びます。いずれも科目 A では 10 年間ほぼ出ていないので、名前と 1 行の説明を結び付けられれば十分です。

流れ図と擬似言語 ― トレースの作法

アルゴリズムの表現方法には流れ図(フローチャート)、擬似言語、決定表(デシジョンテーブル)があります。科目 A では流れ図の読解が 10 年で 5 問、科目 B は 19 回すべてが擬似言語です。どちらも「絵を眺める」のではなく変数の値を紙に書き出して 1 周たどるのが正解への最短経路です。

流れ図の記号意味読むときの注意
端子処理の開始・終了入口と出口が 1 つずつあるか確認する
処理代入・計算などの 1 ステップ代入の向き(左辺が変わる)を取り違えない
定義済み処理別に定義された手続の呼出し中身は別の流れ図。戻ってくる位置を押さえる
判断条件による分岐Yes / No のどちらの枝かを線ごとに確認する
ループ端繰返しの始端と終端始端に条件があれば前判定、終端にあれば後判定
データ・線入出力データ、処理の流れ線の向き(矢印)が処理順序を決める

構造化プログラミングでは、どんな処理も順次(連接)・選択・繰返しの 3 つの制御構造だけで書けます(構造化定理)。ここに手続呼出しが加わると、制御の流れはいったん呼出し先へ移り、戻ってきて続きを実行します。呼出し側が渡す値がパラメータ(実引数)、受け取る側が仮引数です。なお、実行中のプログラム 1 つ分を OS が管理する単位がプロセスで、1 つのプロセッサを細かく切り替えて複数の処理が同時に進んでいるように見せる方式を擬似並列制御といいます(詳細は第 6 章)。

繰返しには判定の位置で 2 種類あり、条件を先に見る前判定(while 型)は 1 回も実行されないことがあり、後で見る後判定(do-while 型)は必ず 1 回は実行されます(図 3-10)。令和 6 年春には、2 つの流れ図が同じ結果になるようにループの終了条件を選ばせる等価変換が出題されました。判定の位置と条件の境界で実行回数が変わる点が論点です。

前判定繰返し(while): 0 回実行もあり得る 開始 条件を満たす? 処理 P 終了 真 繰返し 偽 後判定繰返し(do-while): 必ず 1 回は実行 開始 処理 P 条件を満たす? 終了 偽 真 繰返し
図 3-10 前判定と後判定。両者が等価になるのは「最初から条件が真である場合」だけです。等価変換の問題では、条件が最初から偽のときの実行回数(0 回か 1 回か)で判別します。なお本書では判断(条件分岐)を角丸の枠で描いていますが、実際の流れ図ではひし形です。

擬似言語の記法

科目 B の擬似言語は IPA が公表している共通の記法です。答案も擬似言語の断片で書くため、記法そのものの正確さが得点になります。最低限、次の要素は読み書きできるようにします。

○整数型: maxOf(整数型の配列: data)   /* ○ は手続・関数の宣言、: の後ろが戻り値型 */
  整数型: i, max                     /* 変数宣言 */
  max ← data[1]                      /* ← が代入。配列の要素番号は 1 から */
  for (i を 2 から dataの要素数 まで 1 ずつ増やす)
    if (data[i] > max)
      max ← data[i]
    elseif (data[i] = max)           /* 条件の追加は elseif */
      /* 何もしない */
    endif
  endfor
  while (max < 0)                    /* 前判定の繰返し */
    max ← 0
  endwhile
  return max
記法意味つまずきどころ
←代入(右辺の値を左辺へ)空欄に代入を書くときは ← ごと書く。等号 = で書くと減点
配列[i] / 配列[i, j]要素の参照。要素番号は 1 始まり2 次元は [i, j] と [i][j] の両方の書き方が出る。設問の他の行に合わせる
変数.メンバ構造体・クラスのメンバ参照宣言部のコメントにメンバの意味が書いてある
div / mod整数除算の商 / 剰余1 次元配列に 2 次元構造を載せるときの定番
for (i を A から B まで 1 ずつ増やす)繰返し。B を含むwhile の「未満」と混同しない。両端を含むか必ず確認
/* … */注釈穴埋めの答えの語は大半がここに書いてある

手順の型: 机上トレースの作法

  1. 設問だけ先に読み、空欄の個数と、それがどの図・どの行にあるかを把握する
  2. 「実データ ↔ 配列」の対応表を余白に書く(例: viaNode[k] = k の直前のノード)
  3. 変数を横に並べた表を書き、1 行実行するごとに値を 1 行足す(上書きしない)
  4. 境界だけは具体値で検算する(要素数 0・1 のとき、i が最初と最後のとき)
  5. 空欄は前後 2〜3 行から「この行が何を確定させるか」を決めてから埋める

たとえば data = {3, 9, 4} に対して上の maxOf をトレースすると、次の表になります。値を上書きせずに 1 行ずつ足していくのが、戻りや分岐を追い切るコツです。

実行行imax判定
max ← data[1]―3―
i = 2 の回29data[2] = 9 > 3 なので更新
i = 3 の回39data[3] = 4 > 9 は偽なので据置き
while (max < 0)―9max = 9 なので条件は偽。前判定なので 0 回実行
return max―9for は i = 3 で終了(B を含む)

条件の組合せと動作の対応を網羅的に整理するときは決定表を使います。上半分に条件、下半分に動作を書き、列ごとに「Y/N の組合せ」と「実行する動作」を対応づけます。条件が n 個なら列は最大 2n 通りになるため、抜けと重複の検査に向いています。

プログラミングとプログラム言語

この節は「知っていれば 1 問取れる」用語が並ぶ領域です。深追いせず、対比の形で覚えます。まずプログラミング作法とコーディング標準は、字下げ(インデンテーション)・ネストの深さの上限・命名規則・使用禁止命令などをチームで揃える取決めで、目的は機能適合性・性能効率性・使用性・保守性の向上です。守らないと、動くけれど読めない・直せないプログラムが残ります。

プログラムの 4 性質

直近 10 年で 3 回出題されました。うち 2 回(平成 29 年春・令和 3 年秋)は同じ 4 つの記述から正しいものを選ばせ、正解肢だけが入れ替わる形式、令和 4 年春は再入可能の特徴だけを問う形式です。いずれも 4 つの定義を相互に入れ替えた誤答肢が作られるので、下の表を丸ごと覚えます。

性質定義実現の条件
再帰的(リカーシブ)実行中に自分自身を呼び出せる呼出しごとの局所データをスタックに積む
再使用可能(リユーザブル)一度実行した後、再ロードせずにもう一度実行できる実行のたびに変数を初期化する
再入可能(リエントラント)複数のタスクから同時に呼ばれても、それぞれ正しい結果を返す手続部と、タスクごとのデータ部を分離する
再配置可能(リロケータブル)主記憶上のどのアドレスに置いても実行できるアドレスを相対参照で書く
覚え方 再入可能=「同時」、再使用可能=「続けて」。時間の重なりがあるかどうかが唯一の違いです。再入可能なプログラムは再使用可能でもありますが、逆は成り立ちません。

プログラム構造とオブジェクト指向

大きなプログラムは、全体の流れを制御するメインルーチンと、そこから呼び出されるサブルーチンに分けて組み立てます。このモジュール分割では、モジュール間の結びつきを弱く(結合度を低く)、内部のまとまりを強く(強度を高く)して独立性を高めるのが原則です(詳細は第 13 章)。オーバーロードは同じ名前の手続を引数の型や個数で区別して複数定義すること、オーバーライドは継承したメソッドをサブクラス側で定義し直すことです。名前が似ているので、「多重定義がオーバーロード、上書きがオーバーライド」と対で覚えます。共通処理を実行時に結合して共有する仕組みが DLL(Dynamic Link Library)です。

オブジェクト指向の柱は 3 つです。カプセル化はデータと操作を 1 つにまとめ内部を隠すこと、継承は既存クラスの性質を引き継いで新しいクラスを作ること、多態(ポリモーフィズム)は同じメッセージに対してオブジェクトごとに異なる振る舞いをすることです。クラスから生成された実体がインスタンスです。データ型には整数型・実数型・論理型・文字型のほか、複数の型をまとめた構造型、値の表現方法を隠して操作だけを公開する抽象データ型があります。

手続への値の渡し方は 2 通りです。値呼出し(call by value)は実引数の値を複写して渡すため、手続の中で仮引数を書き換えても呼出し元には影響しません。参照呼出し(call by reference)はアドレスを渡すため、書換えが呼出し元にも反映されます。実行時の記憶域は、静的変数(プログラム実行中ずっと存在)、自動変数(ブロックに入ると確保・出ると解放)、ヒープ(動的に確保し、不要になった領域はガベージコレクションが回収)に分かれ、変数が有効な範囲をスコープといいます。翻訳後のプログラム本体(目的プログラムテキスト)は実行中に書き換えないので複数のタスクで共有でき、これが再入可能を成り立たせる前提になります。

言語の種類と文法の表記法

プログラム言語は、プロセッサが直接解釈する機械語から、その命令に記号名を与えたアセンブラ言語、人間が読み書きしやすい高水準言語へと発展してきました。高水準言語は次の 5 つに分類されます。

分類特徴代表例
手続型言語処理手順を順に記述するFortran、COBOL、Pascal、BASIC、C、R(統計解析向き)
オブジェクト指向言語データと操作をクラスにまとめるJava、C++、Julia、Go、Scala(関数型の性質も併せ持つ)
スクリプト言語コンパイルせず逐次解釈で手軽に実行ECMAScript(JavaScript)、Perl、PHP、Python、Ruby
関数型言語関数の適用で計算を表し、副作用を抑えるHaskell、Lisp 系
論理型言語事実と規則を宣言し、推論で答えを導くProlog

ソースコードをまとめて機械語に翻訳してから実行するのがコンパイラ方式、1 文ずつ解釈しながら実行するのがインタプリタ方式です。実行中に頻繁に通る部分だけを機械語に変換して速度を稼ぐ JIT(Just In Time)コンパイル方式もあります。JIS X 3016(ISO/IEC 23271)で標準化された共通言語基盤(CLI)は、複数の言語から共通の中間形式・実行環境を使えるようにする枠組みです。

出題実績 言語の特徴は直近 10 年で 5 問。うち 2 回(令和 2 年 10 月・令和 4 年春)が「字下げの深さでブロックの範囲を指定する言語」=Python を選ばせる問題でした。誤答肢は波括弧や end でブロックの範囲を示す言語です。ほかに TypeScript・R・Scala が各 1 回出ています。

変数・式・文・手続といったプログラムの構成単位をどう組み立てるかという構文規則は、記号で厳密に書き表す構文記法で定義します。その代表が BNF(Backus Naur Form:バッカス記法)というメタ言語で、繰返しや省略の記法を加えたものが EBNF(Extended Backus Naur Form:拡張バッカス記法)、BNF で定義できる文法の範囲が文脈自由文法です。試験では「この規則から生成できる文字列はどれか」という読解型が出ます。

<数字> ::= 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9
<数>   ::= <数字> | <数><数字>

読み方: 「::=」は「〜と定義する」、「|」は「または」。
<数> は再帰的に定義されているので 1 桁以上の数字列すべてを表す。
したがって 123 は生成できるが、1.5 や A1 は生成できない。
出題実績 BNF は直近 10 年で 2 回(平成 29 年秋・平成 30 年秋)。規則から生成される文字列を選ぶ形式で、平成 29 年秋の正解は 123 でした。誤答肢は 1 か所だけ規則に合わない文字列です。

マークアップ言語・データ記述言語

言語位置づけ関連用語
HTMLWeb ページの構造を記述開始タグ・終了タグ、DTD(Document Type Definition:文書型定義)、SGML(Standard Generalized Markup Language)
XMLタグを独自に定義できるデータ交換用DOM(Document Object Model)、SAX(Simple API for XML)、XML Schema、SOAP(XML でメッセージを交換するプロトコル)、SVG(Scalable Vector Graphics)、符号化宣言
XHTMLHTML を XML の規則で再定義XHTML Basic、XHTML Modularization
CSS / XSL構造と表示形式を分離するスタイルシートCSS(Cascading Style Sheets:段階スタイルシート)、XSL(Extensible Stylesheet Language:拡張可能なスタイルシート言語)
JSON「名前と値の組」「値の順序付きリスト」でオブジェクトを表すJavaScript 由来。Web API の標準的な交換形式
YAML字下げで階層を表す設定記述向けの形式設定ファイル、CI 定義
UMLオブジェクト指向設計の図的表記法。クラスは属性と操作を持ち、関連の端に付ける役割名がロール名クラス図、オブジェクト図、コンポーネント図、パッケージ図、配置図、コンポジット構造図、アクティビティ図、ステートマシン図、シーケンス図、コミュニケーション図、相互作用概要図、タイミング図、ユースケース図(詳細は第 13 章)
SDL / ADL / DDLUML 以外の記述言語SDL(Specification and Description Language)、ADL(Architecture Description Language:アーキテクチャ記述言語)、DDL(Data Definition Language:データ定義言語。第 9 章)

Web の役割分担は、HTML が構造、CSS が見た目、JavaScript が振る舞いです。ブラウザ側で動くのがクライアントサイド、Web サーバ(代表的な実装が Apache HTTP Server)側で動くのがサーバサイドプログラミング(JSP=Jakarta Server Pages など)で、画面遷移せずに非同期通信で部分更新する仕組みが Ajax(Asynchronous JavaScript and XML)、1 枚の HTML で画面を切り替える構成が SPA(Single Page Application)です。ブラウザ側で操作性の高い画面を実現する仕組みの総称がリッチクライアントで、SPA の構築に使う部品群がフロントエンドフレームワークです。ブラウザ上で機械語に近い形式を高速実行する WebAssembly もシラバスの用語例に入っています。文字列のパターンを記述する正規表現は、入力チェックやログ検索で使う定番の道具です。

出題実績 JSON は直近 10 年で 2 回(平成 31 年春・令和 5 年秋)、いずれも「名前と値の組」「値の順序付きリスト」という説明からデータ記述仕様を選ぶ同一問題でした。誤答肢は XML・YAML・CSV です。

科目 B「問 3 プログラミング」への橋渡し

科目 B は問 1 の情報セキュリティだけが必須で、残りは問 2〜11 の 10 問から 4 問を選んで解きます。そのうちプログラミングは直近 19 回すべてで「問 3」に固定されているため、受験前に「解くか捨てるか」を決めておける数少ない分野です。19 問中 18 問が純粋なアルゴリズム題材(業務題材は平成 31 年春の券売機のみ)なので、本文から常識で推測する戦法は効きません。当たれば満点、添字を 1 つ取り違えれば全滅という分散の大きい分野です。

題材のジャンル10 年(19 回)での出題数例
盤面・パズル系の探索とバックトラック7 問(37%)魔方陣、ライフゲーム、ナイトの巡歴、迷路、スライドパズル
グラフ・木4 問一筆書き、AVL 木の回転、ダイクストラ法
数値・整数・信号処理3 問多倍長整数、エラトステネスの篩、誤差拡散法
データ分析・機械学習・業務モデル3 問パーセプトロン、k-means 法、券売機の状態遷移
動的計画法2 問ナップザック問題、最長共通部分列

探索(深さ優先・幅優先・バックトラック)を中心とする最初の 2 ジャンルで 11 問=58% を占めます。選ぶと決めたなら、まず探索の型を仕上げるのが数字に見合った投資です。設問の内訳も偏っていて、設問数は平均 3.6 問(枝番まで展開すると平均 4.5 小設問)、そのうち穴埋めが約 58%、計算(実行回数・トレース値・計算量の式・修正行番号)が約 20% で、この 2 つで 8 割に達します。字数記述は 19 回中 5 回しか出ておらず、いずれも 10〜30 字で、40 字以上は 10 年間で 1 問もありません。作文力ではなく擬似言語を正確に書き下す力とトレース精度で決まる分野です。

ここがひっかけ IPA の採点講評が繰り返し指摘する失点原因は 4 つです。① 机上で正確に再現できない、② 再帰から戻った後の引数を追えない、③ 境界値(top と last が等しい場合など)を詰めない、④ 配列の添字と実データの対応(isPrime[k] が 2k + 1 を表す、といった約束)を取り違える。いずれも本章の §流れ図と擬似言語で挙げたトレースの型で潰せます。

時間配分は 150 分で 5 問なので 1 問あたり 30 分。下見 2 分 → 説明を読んで対応表 6 分 → トレース 6 分 → 空欄補充 12 分 → 検算 4 分が目安で、着手 10 分で「実データ ↔ 配列」の対応表が書けなければ撤退して別の問題に移ります。実際の過去問題材での解き方と検算の作法は第 24 章で扱います。

ひっかけポイント

ここがひっかけ ①: スタックの出力順列を 3! = 6 通りと数える A・B・C を順にプッシュしたとき、CAB は作れません。C を先に出した時点で A は B の下敷きになっており、A を B より先に取り出す方法がないからです。正解は 5 通り。誤答肢には 6 通り・4 通り・7 通りが並びます。「取り出しを飛び越した要素は、その後かならず上から順に出てくる」と覚えます。
ここがひっかけ ②: 逆ポーランド記法で優先順位と被演算子の順序を落とす 変換では演算子の優先順位を無視して左から並べた式(A + B × C を AB+C× とするなど)が誤答肢になります。評価では、後にプッシュされた方が右の被演算子である点が要注意で、減算・除算では順序を逆にすると値が変わります(A B - は A − B)。加算・乗算だけの例題で練習していると気づけません。
ここがひっかけ ③: ハッシュの衝突条件で「差」を「和」に、「差が倍数」を「各々が倍数」にすり替える h(x) = x mod n の衝突条件は a − b が n の倍数です。「a + b が n の倍数」「a と b がそれぞれ n の倍数」は誤りで、後者は 20 と 33 のようにどちらも n の倍数でないのに衝突する例があることで即座に否定できます。
ここがひっかけ ④: 再入可能と再使用可能、再帰的と再配置可能を入れ替える この 4 性質は同じ 4 記述を使い回して正解肢だけを変える形式で出ます。決め手は時間の重なりで、複数タスクから同時に呼ばれても正しいのが再入可能、いったん終わってからもう一度実行できるのが再使用可能です。アドレス非依存は再配置可能、自分自身の呼出しは再帰的です。
ここがひっかけ ⑤: 整列の同定で「確定する側」と「比較する相手」を見誤る バブル・選択・挿入はどれも O(n2) で似て見えますが、バブルは隣接だけを見て末尾を確定、選択は未整列部分全体から最小値を選んで先頭を確定、挿入は前方の整列済み部分に差し込みます。流れ図や途中状態から名前を当てる問題では、この 2 軸で必ず切り分けられます。

理解度チェック(科目 A 形式)

Q1. 整列アルゴリズムのうち、隣り合う 2 つの要素を比較し、大小の順が逆であれば交換する操作を配列の端から端まで繰り返すものはどれか。
  1. クイックソート
  2. 挿入ソート
  3. バブルソート
  4. 選択ソート

正解: ウ バブルソートは隣接する 2 要素だけを比べて交換し、1 パスごとに末尾へ最大値を確定させます。ア は基準値で 2 分割して再帰する分割統治法、イ は前方の整列済み部分に正しい位置を探して差し込む方法、エ は未整列部分の最小値を選んで先頭と交換する方法です。

Q2. 中置表記の式 (P + Q) ÷ R を逆ポーランド記法(後置表記)で表したものはどれか。
  1. PQR+÷
  2. PQ+R÷
  3. ÷+PQR
  4. PQ÷R+

正解: イ 式の木を作り、後行順(左 → 右 → 根)でたどると P、Q、+、R、÷ となります。ア は + の被演算子が P と Q になっておらず括弧の効果が消えています。ウ は演算子を先に書く前置(ポーランド)記法です。エ は ÷ と + の適用順序が入れ替わっており、P ÷ Q + R を表します。

Q3. ハッシュ関数 h(x) = x mod n を使ってキー x を格納するとき、異なる 2 つのキー a、b が同じ位置に割り当てられる条件はどれか。
  1. a − b が n の倍数である
  2. a + b が n の倍数である
  3. a と b がともに n の倍数である
  4. a × b が n の倍数である

正解: ア a mod n = b mod n は、a と b を n で割った余りが等しいこと、すなわち差 a − b が n で割り切れることと同値です。イ・エ は余りの一致とは無関係です。ウ は「n = 13、a = 20、b = 33」のように、どちらも n の倍数でないのに衝突する例があるため誤りです。

Q4. A、B、C をこの順に 1 回ずつスタックにプッシュする。プッシュとポップは任意の順序で行えるとき、ポップによって得られる 3 文字の並びは何通りか。
  1. 3
  2. 4
  3. 5
  4. 6

正解: ウ ABC・ACB・BAC・BCA・CBA の 5 通りです。エ の 6 通りは 3! をそのまま答えた誤りで、CAB は C を出した時点で A が B の下にあるため作れません。ア・イ は実現できる並びを数え落としています。

Q5. 再入可能(リエントラント)なプログラムの説明として、適切なものはどれか。
  1. 主記憶上のどのアドレスに配置しても、そのまま実行できる。
  2. 実行の途中で自分自身を呼び出すことができる。
  3. 一度実行を終えた後、再ロードしなくてももう一度実行できる。
  4. 複数のタスクから同時に呼び出されても、それぞれに正しい結果を返す。

正解: エ 再入可能は、手続部とタスクごとのデータ部を分離することで、実行が時間的に重なっても互いに干渉しない性質です。ア は再配置可能、イ は再帰的、ウ は再使用可能の説明で、この 4 つを入れ替えた選択肢が定番の誤答です。

Q6. ポインタで実現した単方向の線形リストの特徴として、適切なものはどれか。
  1. 任意の要素へ、添字の計算だけで一定時間にアクセスできる。
  2. 要素の挿入に伴うポインタの書換え回数は、要素数や挿入位置によらず一定である。
  3. あらかじめ連続領域を確保するため、使われない領域が生じる。
  4. 末尾の要素の削除は、ポインタを 1 回たどるだけで完了する。

正解: イ 挿入は「新節点の next を決め、直前の節点の next を書き換える」2 本の操作で終わり、要素数にも位置にも依存しません。ア と ウ は配列で実現した場合の特徴です。エ は誤りで、単方向リストの末尾削除は末尾の 1 つ前までたどる必要があり、たどる回数が最も多くなる操作です。

Q7. 「名前と値の組」および「値の順序付きリスト」という 2 種類の構造でデータを表現し、Web API のデータ交換に広く使われている仕様はどれか。
  1. CSV
  2. DTD
  3. JSON
  4. XML

正解: ウ JSON はオブジェクト(名前と値の組の集まり)と配列(値の順序付きリスト)の 2 構造でデータを表します。ア は行と項目の区切りだけの平坦な形式、イ は XML や SGML の文書構造を定義する文書型定義、エ は独自タグで階層を表すマークアップ言語で、「名前と値の組」という説明には当たりません。

Q8. n 件のデータを m 件ずつのブロックに分け、まず各ブロックの代表値を先頭から線形探索して該当ブロックを決め、次にそのブロック内を線形探索する。目的のデータが必ず存在するとき、平均比較回数を表す式はどれか。
  1. m ÷ 2 + n ÷ (2m)
  2. m + n ÷ m
  3. m ÷ 2 + n ÷ m
  4. n ÷ (2m)

正解: ア ブロック数は n ÷ m 個なので代表値の線形探索の平均は n ÷ (2m) 回、ブロック内の線形探索の平均は m ÷ 2 回で、2 段階の和になります。イ は両方の ÷ 2 を落とした最悪値、ウ はブロック間の ÷ 2 を落とした式、エ は第 2 段階を数え忘れた式です。

Q9. 非負整数 n の階乗 n! を返す関数 fact(n) の再帰的な定義として、正しいものはどれか。
  1. n = 0 のとき 0、それ以外のとき n × fact(n − 1)
  2. n = 0 のとき 1、それ以外のとき n × fact(n − 1)
  3. n = 0 のとき 1、それ以外のとき n × fact(n)
  4. n = 1 のとき 0、それ以外のとき n × fact(n − 1)

正解: イ 0! = 1 という停止条件と、引数が 1 ずつ 0 に近づく呼出しの両方がそろっています。ア は停止条件の戻り値が 0 なので結果が常に 0 になります。ウ は引数が減らず停止しません。エ は停止条件の値が誤っているうえ、n = 0 で呼ぶと止まりません。

Q10. 分割統治法を用いている整列アルゴリズムはどれか。
  1. 挿入ソート
  2. 選択ソート
  3. バブルソート
  4. クイックソート

正解: エ クイックソートは基準値より小さい群と大きい群に分割し、それぞれを独立に再帰で整列してから結合します(マージソートも同じ型です)。ア・イ・ウ はいずれも配列を 1 本のまま走査する二重ループで、分割も再帰も行いません。

Q11. 完全 2 分木を、根を要素番号 1 とし「節点 i の左の子が 2i、右の子が 2i + 1」となるように配列へ格納した。この配列を要素番号の小さい順に調べる処理は、木のどの走査に相当するか。
  1. 幅優先探索
  2. 先行順の深さ優先探索
  3. 中間順の深さ優先探索
  4. 後行順の深さ優先探索

正解: ア この配列表現では要素番号が「根 → 深さ 1 の節点 → 深さ 2 の節点 …」と浅い順に並ぶので、添字順の走査はレベル順、すなわち幅優先探索です。イ・ウ・エ はいずれも 1 本の枝を葉まで降りてから戻る深さ優先の走査で、根をいつ訪れるかが違うだけです。

Q12. BNF で <英字> ::= A | B | C、<名前> ::= <英字> | <名前><英字> と定義するとき、<名前> として生成できる文字列はどれか。
  1. AB1
  2. 1AB
  3. CAB
  4. A-B

正解: ウ <名前> は再帰的に定義されており、A・B・C を 1 文字以上並べた列すべてを表します。CAB は C、A、B の順に 3 文字を連ねたもので生成できます。ア と イ は数字の 1、エ はハイフンを含み、<英字> の定義に無い記号なので生成できません。

Q13. 2 分探索木から、子を 2 つ持つ節点を削除する。削除した位置に移す値として適切なものはどれか。
  1. 削除する節点の左の子の値
  2. 削除する節点の右の子の値
  3. 木全体の最小値
  4. 削除する節点の右部分木の最小値

正解: エ 右部分木の最小値は、中間順で削除対象の次に来る値(後継)なので、そこへ移しても「左部分木 < 節点 < 右部分木」が保たれます。ア・イ は子がさらに子を持つ場合に条件が崩れます。ウ は木全体の最小値なので、削除位置に移すと左部分木に残る値の方が大きくなり、「左部分木 < 節点」の関係が崩れます。

Q14. 「処理 P を実行してから条件 C を判定し、C が真である間は処理 P を繰り返す」という後判定の繰返しがある。これと同じ動作を、前判定の繰返し(条件を判定してから処理を実行する形)だけを使って表したものはどれか。
  1. 処理 P を 1 回実行した後、「C が真である間、処理 P を繰り返す」前判定の繰返しを置く。
  2. 「C が真である間、処理 P を繰り返す」前判定の繰返しだけを置く。
  3. 「C が偽である間、処理 P を繰り返す」前判定の繰返しだけを置く。
  4. 処理 P を 1 回実行した後、「C が偽である間、処理 P を繰り返す」前判定の繰返しを置く。

正解: ア 後判定は「必ず 1 回は実行する」ので、その 1 回を繰返しの外に出し、残りを前判定の繰返しで書けば等価になります。イ は最初から C が偽のとき実行回数が 1 回ではなく 0 回になり一致しません。ウ・エ は判定条件を反転させており、繰り返す向きが逆になります。

まとめ

この章の得点源は「式」と「対比」に集約されます。次の表の数値と切り分け方を口に出して言えるようになれば、科目 A の目標である 3 問はほぼ確保できます。

論点覚える形典型の誤答
配列とリスト配列=添字で O(1) アクセス/リスト=挿入削除がポインタ 1〜2 本長所短所の入れ替え。末尾削除が一定時間だと思う
スタックの出力順列A・B・C なら 5 通り(CAB は不可)3! = 6 通り
逆ポーランド記法式の木の後行順。評価は数値プッシュ・演算子で 2 個ポップ優先順位無視の並び、減算の被演算子順の逆転
2 分木の配列表現左の子 2i、右の子 2i + 1、親 i div 2。添字順=幅優先深さ優先・先行順と取り違える
2 分探索木の削除子が 2 個なら右部分木の最小値を昇格直接の子をそのまま繰り上げる
線形探索平均 (n + 1) ÷ 2、最悪 n常に n ÷ 2 とする
ブロック分割探索m ÷ 2 + n ÷ (2m)。最小値は m = √n のとき √nどちらかの ÷ 2 を落とす
2 分探索最大 ⌈log2(n + 1)⌉ 回。整列済みが前提未整列データに使えると考える
ハッシュの衝突h(x) = x mod n で a − b が n の倍数和が倍数、各々が倍数
整列の同定バブル=隣接/末尾確定、選択=全体/先頭確定、挿入=差込み比較対象と確定位置の取り違え
計算量O(n log n)=クイック・マージ・ヒープ(クイックの最悪は O(n2))クイックを常に O(n log n) とする
安定な整列バブル・挿入・マージが安定選択・クイック・ヒープを安定とする
再帰の定義停止条件+引数が停止条件へ近づく呼出し停止条件の戻り値や引数を崩した定義
分割統治法分割 → 独立に解く → 結合(クイック・マージ・2 分探索)動的計画法(解の再利用)と混同する
プログラムの 4 性質再入可能=同時、再使用可能=続けて、再配置可能=アドレス非依存4 つの定義の入れ替え
擬似言語← が代入、配列は 1 始まり、for は終端を含む0 始まりで div/mod を計算して 1 ずれる

次の第 4 章では、これらのアルゴリズムを実際に動かすハードウェア側、すなわちコンピュータの構成要素(プロセッサ・記憶階層・入出力)を扱います。計算量が「手数」の話だったのに対し、次章は「1 手あたりの時間」を決める仕組みの話です。