仮の宿 学習室

基本情報技術者 FUNDAMENTAL IT ENGINEER

データ構造とアルゴリズム(科目B)

講義 3 本・確認問題 30 問 | 本試験では「科目B」(20問)の一部 | 最終更新 2026-09-24

この章で学ぶこと
目次
  1. リスト・スタック・キューを擬似言語で扱う
  2. 探索と整列を擬似言語で読む
  3. 木と再帰
  4. 確認問題(30問)
  5. 演習ツール

1. リスト・スタック・キューを擬似言語で扱う

科目Bで最も出題が多い「つながりをたどるデータ構造」を、擬似言語のコードとして読めるようにします。

単方向リストは「値」と「次にどこへ行くか」を1組にしたノードをつないだ構造です。科目Bの問題では、ノードを二つの配列で表す書き方がよく使われます。値[i] に i 番目のノードが持つ値を入れ、次[i] に「i の次のノードの添字」を入れます。次[i] が 0 のときはそこがリストの終わりです。配列の添字の順番とリストの順番は一致しないのが普通で、先頭 という変数が「どの添字から読み始めるか」を持ちます。走査は 整数型: p ← 先頭 としてから while (p ≠ 0) の中で p ← 次[p] を繰り返す、という形が定型です。この p ← 次[p] を書けるかどうかが第一関門です。

挿入と削除は「つなぎ替えの順番」がすべてです。添字 p のノードの直後に新しいノード q を入れるなら、先に 次[q] ← 次[p] として新ノードの行き先を確保し、そのあとで 次[p] ← q とします。逆の順で書くと 次[p] が上書きされてしまい、p の後ろにつながっていたノードへ二度とたどり着けなくなります。削除は逆で、p の直後のノード q を外すには 次[p] ← 次[q] とします。配列の要素を実際に消す必要はなく、たどれなくなればリストからは外れたことになります。配列と違って途中への挿入・削除が要素の移動なしにできる反面、n 番目の要素を取り出すには先頭から順にたどるしかない、というのがリストの性質です。

スタックは後入れ先出し(LIFO)、キューは先入れ先出し(FIFO)です。スタックは配列 st と「今どこまで積んだか」を表す sp の組で書きます。push は sp ← sp + 1 のあと st[sp] ← x、pop は v ← st[sp] のあと sp ← sp - 1 で、push と pop で sp の増減と代入の順が逆になる点に注意してください。キューは取り出し位置 head と入れる位置 tail の二つを持ちます。単純に増やし続けると配列の末尾で行き止まりになるので、実際には末尾まで来たら先頭に戻る環状キュー(リングバッファ)にします。1始まりの配列で n 個ぶんを一周させるときの戻し方は、添字が n を超えたら n を引く、と書くのが確実です。

配列2本で単方向リストを表す(先頭 ← 2 のとき 10 → 20 → 30 → 50 と並ぶ)
添字 i値[i]次[i]リスト上の位置
13043番目
21031番目(先頭)
32012番目
45004番目(終端)
リストを先頭からたどって値を合計する(戻り値は 10+20+30+50 = 110)
整数型の配列: 値 ← {30, 10, 20, 50}整数型の配列: 次 ← {4, 3, 1, 0}整数型: 先頭 ← 2 ○整数型: 合計()  整数型: s ← 0  整数型: p ← 先頭  while (p ≠ 0)    s ← s + 値[p]    p ← 次[p]  endwhile  return s

用語

単方向リスト
各ノードが値と「次のノードを指す情報」だけを持つ線形リスト。先頭から順方向にしかたどれない。途中への挿入や削除はつなぎ替えだけで済むが、k番目の要素を得るには先頭からk回たどる必要がある。
番兵
リストや配列の終わりを表すために置く特別な値。配列でリストを表すときは、次の添字として存在しない値0を入れて終端を示すことが多い。終端判定の条件式を単純にできるのが利点である。
スタック
最後に入れたものを最初に取り出す後入れ先出し(LIFO)のデータ構造。積む操作をプッシュ、取り出す操作をポップと呼ぶ。関数呼出しの戻り先の管理や、式の評価、深さ優先の探索に使われる。
キュー
最初に入れたものを最初に取り出す先入れ先出し(FIFO)のデータ構造。入れる操作をエンキュー、取り出す操作をデキューと呼ぶ。処理待ち行列や幅優先の探索に使われる。
リングバッファ
固定長の配列の末尾と先頭を論理的につないで環状に使うキューの実装。添字が配列の末尾を超えたら先頭へ戻す。要素の移動なしに一定の領域を再利用できるため、入出力の緩衝領域などに使われる。

例題

例題:添字1のノードの直後に、添字5のノード(値60)をつなぎたい。どう書けばよいか。
次[5] ← 次[1]次[1] ← 5
答えと考え方 次[5] ← 次[1] を先に書き、そのあと 次[1] ← 5 と書く。配列は5要素ぶん用意されているものとする。上の表では 次[1] は 4 なので、次[5] ← 4、次[1] ← 5 となり、リスト全体は 10 → 20 → 30 → 60 → 50 の順になる。順序を逆にして 次[1] ← 5 を先に書くと、もとの 次[1](=4)が失われ、添字4のノードにたどり着けなくなる。
例題:空のスタックに 4, 8, 2 の順にプッシュし、ポップを2回行うと何が取り出されるか。
答えと考え方 後入れ先出しなので、最後に入れた2が先に出て、次に8が出る。取り出す順は 2, 8。同じ操作をキューで行うと先入れ先出しなので 4, 8 の順になる。

出典・根拠:IPA 基本情報技術者試験 シラバス Ver.9.2 大分類1:基礎理論 中分類2:アルゴリズムとプログラミング(データ構造)

2. 探索と整列を擬似言語で読む

線形探索・2分探索と、バブル・選択・挿入の3つの整列を、コードの動きとして追えるようにします。

線形探索は先頭から順に比べていくだけの探索です。for (i を 1 から xの要素数 まで 1 ずつ増やす) の中で if (x[i] = k) なら return i、最後まで見つからなければ return -1 とするのが定型です。見つかった時点で return するか、変数に控えて最後まで回すかで意味が変わり、前者は最初に現れた位置、後者は最後に現れた位置を返します。平均比較回数は要素数の約半分、最悪は要素数と同じで、計算量は O(n) です。整列されていなくても使える点が長所です。

2分探索は整列済みの配列にしか使えませんが、1回の比較で候補を半分に減らせます。lo(範囲の下端)と hi(範囲の上端)を持ち、mid ← (lo + hi) ÷ 2 の商 として真ん中を見ます。x[mid] が目的の値なら終了、x[mid] が小さければ答えは右半分にあるので lo ← mid + 1、大きければ左半分なので hi ← mid - 1 とします。ここで lo ← mid や hi ← mid と書いてしまうと範囲が縮まらず、無限ループになることがあるので、必ず mid を範囲から外す +1 / -1 が要ります。lo > hi になったら見つからなかったということです。最悪比較回数は要素数 n に対して 2 のべき乗で n を超える最小の指数、つまり log2(n) の切捨てに1を足した値になります。

基本的な整列は3つ押さえます。バブルソートは隣り合う2要素を比べて逆順なら交換することを繰り返し、1回のパスで最大値が右端に確定します。選択ソートは未整列部分の最小値の位置をまず探し、その要素と未整列部分の先頭を交換します。挿入ソートは、すでに整列済みの左側へ次の要素を差し込む方式で、差し込む場所が見つかるまで要素を1つずつ右へずらします。3つとも比較回数はおよそ n(n-1)/2 回で計算量は O(n^2) ですが、挿入ソートはほぼ整列済みのデータで速く、選択ソートは交換回数が n-1 回以下で済む、といった違いがあります。整列済みの列を2本つなぐマージは、両方の先頭を比べて小さいほうを取り出し、取り出したほうの添字だけを進める、という手順です。

整列済み配列 {2, 5, 8, 11, 14, 17, 21, 26} から 21 を2分探索する
回lohimidx[mid]判定と次の動き
11841111 < 21 なので lo ← 5
25861717 < 21 なので lo ← 7
378721一致したので 7 を返す
2分探索の定型。mid を範囲から必ず外すのがポイント
○整数型: 2分探索(整数型の配列: x, 整数型: k)  /* x は昇順に整列済み */  整数型: lo ← 1  整数型: hi ← xの要素数  整数型: mid  while (lo ≦ hi)    mid ← (lo + hi) ÷ 2 の商    if (x[mid] = k)      return mid    elseif (x[mid] < k)      lo ← mid + 1    else      hi ← mid - 1    endif  endwhile  return -1

用語

線形探索
配列の先頭から順に目的の値と比較していく探索法。整列されていなくても使える。要素数nに対して最悪n回、平均で約n/2回の比較が必要で、計算量はO(n)である。
2分探索
整列済みの配列に対し、範囲の中央の要素と比較して探索範囲を半分ずつ狭めていく探索法。計算量はO(log n)。整列されていることが前提で、要素の挿入や削除が多いデータには向かない。
バブルソート
隣り合う2つの要素を比較し、順序が逆なら交換する操作を繰り返す整列法。1回の走査ごとに未整列部分の最大値が末尾に確定する。比較回数は約n(n-1)/2回で計算量はO(n^2)である。
選択ソート
未整列部分から最小(または最大)の要素を選び、未整列部分の先頭と交換することを繰り返す整列法。比較回数は約n(n-1)/2回だが、交換回数はn-1回以下に抑えられる。
挿入ソート
整列済みの部分に対して次の要素を正しい位置へ差し込む整列法。差し込み位置より後ろの要素を1つずつずらす。ほぼ整列済みのデータでは比較・移動が少なく、最良の場合O(n)で済む。
マージ
整列済みの二つの列の先頭どうしを比較し、小さいほうを取り出して新しい列に並べる併合処理。取り出した側の添字だけを進める。二つの列の要素数の和に比例する時間で済み、マージソートの中核となる。

例題

例題:{5, 3, 8, 1, 9, 2} をバブルソートしたとき、外側のループを1回終えた時点の並びは。
答えと考え方 隣どうしを左から比べて逆順なら交換する。5と3を交換して {3,5,8,1,9,2}、5と8はそのまま、8と1を交換して {3,5,1,8,9,2}、8と9はそのまま、9と2を交換して {3,5,1,8,2,9}。最大値9が右端に確定している。
例題:要素数1,000の整列済み配列を2分探索するとき、比較は最大で何回か。
答えと考え方 1回の比較で候補が半分以下になるので、2の9乗=512では足りず、2の10乗=1,024で1,000を上回る。したがって最大10回。要素数が2倍になっても1回しか増えないのが2分探索の強みである。

出典・根拠:IPA 基本情報技術者試験 シラバス Ver.9.2 大分類1:基礎理論 中分類2:アルゴリズムとプログラミング(アルゴリズム)

3. 木と再帰

2分木の3つの走査順と、再帰関数がどの順に呼ばれてどこまで深くなるかを読み解きます。

2分木は、各節が高々2つの子(左と右)を持つ木構造です。科目Bでは配列2本で表すことが多く、L[p] に節 p の左の子の添字、R[p] に右の子の添字を入れ、子がないときは 0 とします。走査(トラバーサル)は3種類あり、自分自身を出力するタイミングだけが違います。前順(行きがけ順)は「自分・左・右」、中順(通りがけ順)は「左・自分・右」、後順(帰りがけ順)は「左・右・自分」です。2分探索木を中順で走査すると値が昇順に並ぶこと、後順は部分木の結果を集めてから自分を処理するので式の計算や領域の解放に向くこと、を合わせて覚えておくと選択肢を絞りやすくなります。

再帰関数は「終了条件」と「自分より小さい問題への呼び出し」の二つでできています。終了条件がないか、引数が小さくならないと、呼び出しが戻ってこず無限再帰になります。空欄補充では 階乗(n - 1) を 階乗(n) と書いた選択肢、最大(x, mid + 1, hi) を 最大(x, mid, hi) と書いた選択肢がよく並びますが、これらは範囲が縮まらないため誤りです。呼び出しの途中の状態(戻り先や局所変数)はスタックに積まれるので、再帰の深さがそのままスタックの深さになります。階乗のように一直線に呼ぶ再帰は深さ n、2分木の走査は木の高さぶんの深さになります。

再帰の呼び出し回数は、木の形を思い浮かべて数えます。フィボナッチを fib(n) = fib(n-1) + fib(n-2) と素直に再帰で書くと、同じ値が何度も計算されるため呼び出し回数が急激に増えます。呼び出し総数を C(n) とすると C(1) = C(2) = 1、C(n) = 1 + C(n-1) + C(n-2) となり、C(6) は15回にもなります。これを避けるには、前の2つの値だけを変数で持ち回る反復版に書き換えるか、計算済みの値を配列に覚えておきます。一方、分割統治は問題を半分ずつに割ってから合わせる方式で、割るたびに大きさが半分になるので深さは log2(n) 程度にとどまり、マージソートや2分探索の考え方の土台になります。

配列2本で表した2分木(節1が根)と3つの走査結果
添字 pv[p]L[p]R[p]
1A23
2B45
3C00
4D00
5E00
前順(1) は A B D E C、中順(1) は D B E A C の順に出力する
文字列型の配列: v ← {"A", "B", "C", "D", "E"}整数型の配列: L ← {2, 4, 0, 0, 0}整数型の配列: R ← {3, 5, 0, 0, 0} ○前順(整数型: p)  if (p ≠ 0)    出力(v[p])    前順(L[p])    前順(R[p])  endif ○中順(整数型: p)  if (p ≠ 0)    中順(L[p])    出力(v[p])    中順(R[p])  endif

用語

前順(行きがけ順)
2分木の走査順の一つで、節自身を処理してから左部分木、右部分木の順にたどる。木構造をそのままの形で書き出したいときや、木の複製を作るときに使われる。preorderともいう。
中順(通りがけ順)
左部分木、節自身、右部分木の順にたどる走査。2分探索木を中順で走査すると、格納された値が昇順に取り出せる。inorderともいう。
後順(帰りがけ順)
左部分木、右部分木をたどってから最後に節自身を処理する走査。部分木の結果を使って自分の値を決める処理、たとえば木の高さの計算や式の値の計算に適する。postorderともいう。
再帰
関数や手続が自分自身を呼び出す書き方。必ず終了条件を持ち、呼び出しのたびに問題が小さくなる必要がある。呼び出しごとの戻り先や局所変数はスタックに積まれるため、深さに比例した記憶域を消費する。
分割統治法
問題を同じ形の小さい部分問題に分割し、それぞれを解いてから結果を統合する設計手法。2分探索、マージソート、クイックソートが代表例で、分割のたびに大きさが半分になるものは深さがlog nに収まる。

例題

例題:上の木を後順(帰りがけ順)で走査すると、どの順に出力されるか。
答えと考え方 左部分木、右部分木、自分の順なので、節2の下から D、E、続いて節2の B、次に右部分木の C、最後に根の A。すなわち D E B C A となる。前順の A B D E C、中順の D B E A C と比べると、自分を出す位置だけが違うことが分かる。
例題:fib(n) = fib(n-1) + fib(n-2)(fib(1) = fib(2) = 1)を素直に再帰で書いたとき、fib(5) を求めるのに fib は何回呼び出されるか。
○整数型: fib(整数型: n)  if (n ≦ 2)    return 1  else    return fib(n - 1) + fib(n - 2)  endif
答えと考え方 呼び出し総数を C(n) とすると C(1) = C(2) = 1、C(n) = 1 + C(n-1) + C(n-2)。C(3) = 3、C(4) = 5、C(5) = 9 回となる。n が1増えるごとに回数がおよそ1.6倍になるため、n が大きいと実用にならない。

出典・根拠:IPA 基本情報技術者試験 試験要綱 Ver.5.6 出題範囲(科目B試験)アルゴリズムとプログラミング

確認問題(30問)

四肢択一。「正解と解説」を開くと、正解の理由と他の選択肢が違う理由を確認できます。

問1|リスト走査

次のプログラムは、配列2本で表した単方向リストの要素数を数えて返す。プログラム中の【a】に入れる式はどれか。ここで、次[p] が 0 のときノード p がリストの終わりであることを表す。

単方向リストの要素数を数える
整数型の配列: 値 ← {30, 10, 20}整数型の配列: 次 ← {0, 3, 1}整数型: 先頭 ← 2 ○整数型: 個数()  整数型: cnt ← 0  整数型: p ← 先頭  while (p ≠ 0)    cnt ← cnt + 1    p ← 【a】  endwhile  return cnt
  1. 次[p]
  2. p + 1
  3. 値[p]
  4. 次[cnt]
正解と解説
正解:A. 次[p]

リストをたどるには、いま見ているノードの添字 p を「p の次のノードの添字」である 次[p] に置き換える。この例では 2 → 3 → 1 → 0 とたどり、cnt は 3 になる。p + 1 は配列の並び順に進むだけでリストの順序と無関係であり、p が 0 にならず終わらない。値[p] はノードの値であって添字ではない。次[cnt] は cnt を添字に使っており、1回目で 次[1] = 0 となって cnt が 1 のまま終わる。

根拠:IPA 基本情報技術者試験 シラバス Ver.9.2 大分類1:基礎理論 中分類2:アルゴリズムとプログラミング(データ構造)

問2|リスト最大

次の関数 f は何をするものか。ここで、値[p] はノード p の値、次[p] は p の次のノードの添字で、次[p] が 0 のときリストの終わりを表す。リストは空でないものとする。

単方向リストに対する関数 f
○整数型: f(整数型の配列: 値, 整数型の配列: 次, 整数型: 先頭)  整数型: p ← 先頭  整数型: m ← 値[先頭]  while (次[p] ≠ 0)    p ← 次[p]    if (値[p] > m)      m ← 値[p]    endif  endwhile  return m
  1. リストの末尾のノードの値を返す
  2. リストに格納されている値の最大値を返す
  3. リストに格納されている値の合計を返す
  4. リストの要素数を返す
正解と解説
正解:B. リストに格納されている値の最大値を返す

m には先頭の値を入れ、たどりながら 値[p] が m より大きいときだけ m を更新している。したがって返るのは全ノードの値の最大値である。末尾の値を返すなら if 文が不要で return 値[p] になる。合計なら m ← m + 値[p] の形になる。要素数なら値ではなく回数を数える必要がある。

根拠:IPA 基本情報技術者試験 シラバス Ver.9.2 大分類1:基礎理論 中分類2:アルゴリズムとプログラミング(データ構造)

問3|リスト挿入

次のプログラムは、値が w の未使用ノード q を、添字 p のノードの直後につないでリストに加える。プログラム中の【a】に入れるものはどれか。ここで、次[p] が 0 のときリストの終わりを表す。

単方向リストへのノードの挿入
整数型の配列: 値 ← {10, 20, 30, 0}整数型の配列: 次 ← {2, 0, 0, 0}整数型: 先頭 ← 1 ○挿入(整数型: p, 整数型: q, 整数型: w)  /* 値が w のノード q を、ノード p の直後につなぐ */  値[q] ← w  【a】  次[p] ← q ○主処理()  挿入(1, 3, 15)  /* このあとリストは 10 → 15 → 20 の順になる */
  1. 次[q] ← 0
  2. 次[p] ← 次[q]
  3. 次[q] ← 次[p]
  4. 次[q] ← p
正解と解説
正解:C. 次[q] ← 次[p]

先に新ノード q の行き先を 次[q] ← 次[p] で確保してから、次[p] ← q でつなぐ。順序を守らないと元の 次[p] が失われる。次[q] ← 0 では q が終端になり、p の後ろにあったノードがすべてたどれなくなる。次[p] ← 次[q] は直後の 次[p] ← q で上書きされるうえ、やはり元の 次[p] が失われる。次[q] ← p は q から p へ戻る輪ができてしまう。

根拠:IPA 基本情報技術者試験 シラバス Ver.9.2 大分類1:基礎理論 中分類2:アルゴリズムとプログラミング(データ構造)

問4|リスト削除

次の関数 削除(1) を実行した後の配列 次 の内容はどれか。ここで、次[p] が 0 のときリストの終わりを表す。

単方向リストからのノードの削除
整数型の配列: 次 ← {3, 0, 4, 2} ○整数型の配列: 削除(整数型: p)  /* 添字 p のノードの直後のノードをリストから外す */  整数型: q  q ← 次[p]  if (q ≠ 0)    次[p] ← 次[q]    次[q] ← 0  endif  return 次
  1. {3, 0, 0, 2}
  2. {4, 0, 0, 2}
  3. {4, 0, 4, 2}
  4. {2, 0, 0, 4}
正解と解説
正解:B. {4, 0, 0, 2}

q ← 次[1] で q は 3 になる。次[1] ← 次[3] = 4 となり、続いて 次[3] ← 0 で外したノードの行き先が消える。よって {4, 0, 0, 2} である。{3, 0, 0, 2} は 次[1] を更新していない。{4, 0, 4, 2} は 次[3] を 0 にしていない。{2, 0, 0, 4} は 次[1] に 次[4] の値を入れており、1つ多く飛ばしている。

根拠:IPA 基本情報技術者試験 シラバス Ver.9.2 大分類1:基礎理論 中分類2:アルゴリズムとプログラミング(データ構造)

問5|リスト探索

次のプログラムで、主処理 の戻り値はどれか。ここで、次[p] が 0 のときリストの終わりを表す。

リストの先頭から数えて何番目にあるかを返す
○整数型: 探す(整数型の配列: 値, 整数型の配列: 次, 整数型: 先頭, 整数型: k)  整数型: p ← 先頭  整数型: c ← 0  while (p ≠ 0)    c ← c + 1    if (値[p] = k)      return c    endif    p ← 次[p]  endwhile  return -1 ○整数型: 主処理()  整数型の配列: 値 ← {40, 10, 30, 20}  整数型の配列: 次 ← {4, 3, 1, 0}  return 探す(値, 次, 2, 40)
  1. 1
  2. 3
  3. 4
  4. -1
正解と解説
正解:B. 3

先頭が 2 なのでリストの並びは 値[2]=10、値[3]=30、値[1]=40、値[4]=20 である。c は 1, 2, 3 と増え、3番目で 値[1] = 40 が k と一致して 3 を返す。1 は 40 が入っているノードの配列上の添字でリスト内の順番ではない。4 はリストの要素数で最後まで数えた場合の値、-1 は見つからなかった場合の値である。

根拠:IPA 基本情報技術者試験 シラバス Ver.9.2 大分類1:基礎理論 中分類2:アルゴリズムとプログラミング(データ構造)

問6|スタック

次のスタックに対し、push(3)、push(7)、pop()、push(5)、push(9)、pop()、pop() をこの順で呼び出す。3回の pop() の戻り値を、呼び出した順に並べたものはどれか。

配列と sp によるスタックの実装
整数型の配列: st ← {0, 0, 0, 0, 0}整数型: sp ← 0 ○push(整数型: x)  sp ← sp + 1  st[sp] ← x ○整数型: pop()  整数型: v ← st[sp]  sp ← sp - 1  return v
  1. 3, 7, 5
  2. 7, 5, 9
  3. 9, 5, 3
  4. 7, 9, 5
正解と解説
正解:D. 7, 9, 5

スタックは後入れ先出しなので、1回目の pop は直前に積んだ 7 を返す。その後 5、9 を積み、2回目の pop は 9、3回目の pop は 5 を返す。よって 7, 9, 5。3, 7, 5 は先入れ先出し(キュー)の動きと混同したもの。7, 5, 9 と 9, 5, 3 は取り出す順が実際の sp の増減と合わない。

根拠:IPA 基本情報技術者試験 シラバス Ver.9.2 大分類1:基礎理論 中分類2:アルゴリズムとプログラミング(データ構造)

問7|配列逆順

次の関数は、配列 x の要素をスタックに積んでから取り出すことで、逆順に並べた配列を返す。プログラム中の【a】に入れる式はどれか。

スタックを使って配列を逆順にする
○整数型の配列: 逆順(整数型の配列: x)  整数型の配列: st  整数型の配列: b  整数型: sp ← 0  整数型: i  for (i を 1 から xの要素数 まで 1 ずつ増やす)    sp ← sp + 1    st[sp] ← x[i]  endfor  for (i を 1 から xの要素数 まで 1 ずつ増やす)    b[i] ← 【a】    sp ← sp - 1  endfor  return b
  1. st[i]
  2. st[sp]
  3. st[sp - 1]
  4. st[xの要素数]
正解と解説
正解:B. st[sp]

1つ目の for で st には x がそのままの順で積まれ、sp は要素数を指している。2つ目の for では毎回スタックの一番上 st[sp] を取り出して sp を1つ減らすので、後から積んだものから順に取り出せて逆順になる。st[i] では積んだ順のまま取り出すので元の並びに戻る。st[sp - 1] は1つ下を読むため最後に添字 0 を参照してしまう。st[xの要素数] は常に同じ要素を返す。

根拠:IPA 基本情報技術者試験 シラバス Ver.9.2 大分類1:基礎理論 中分類2:アルゴリズムとプログラミング(データ構造)

問8|キュー

次のキューに対し、enqueue(5)、enqueue(1)、dequeue()、enqueue(8)、dequeue()、enqueue(3)、dequeue()、dequeue() をこの順で呼び出す。4回の dequeue() の戻り値を、呼び出した順に並べたものはどれか。

配列と head, tail によるキューの実装
整数型の配列: que ← {0, 0, 0, 0, 0, 0}整数型: head ← 1整数型: tail ← 1 ○enqueue(整数型: x)  que[tail] ← x  tail ← tail + 1 ○整数型: dequeue()  整数型: v ← que[head]  head ← head + 1  return v
  1. 5, 1, 8, 3
  2. 1, 5, 3, 8
  3. 5, 8, 1, 3
  4. 3, 8, 1, 5
正解と解説
正解:A. 5, 1, 8, 3

キューは先入れ先出しなので、入れた順にそのまま出てくる。入れた順は 5, 1, 8, 3 なので、取り出す順も 5, 1, 8, 3 である。3, 8, 1, 5 は後入れ先出し(スタック)と混同したもの。1, 5, 3, 8 と 5, 8, 1, 3 は head が指す位置の進み方と合わない。

根拠:IPA 基本情報技術者試験 シラバス Ver.9.2 大分類1:基礎理論 中分類2:アルゴリズムとプログラミング(データ構造)

問9|環状キュー

次のプログラムは、要素数 5 の配列を環状に使うキュー(リングバッファ)である。cnt は現在キューに入っている個数を表す。プログラム中の【a】に入れる式はどれか。

環状キュー(リングバッファ)
整数型: n ← 5整数型の配列: que ← {0, 0, 0, 0, 0}整数型: head ← 1整数型: cnt ← 0 ○enqueue(整数型: x)  整数型: t  if (cnt < n)    t ← 【a】    if (t > n)      t ← t - n    endif    que[t] ← x    cnt ← cnt + 1  endif ○整数型: dequeue()  整数型: v ← que[head]  head ← head + 1  if (head > n)    head ← 1  endif  cnt ← cnt - 1  return v
  1. cnt + 1
  2. head + cnt - 1
  3. head + cnt
  4. head + cnt + 1
正解と解説
正解:C. head + cnt

先頭が head、入っている個数が cnt なので、次に書き込むべき位置は head から cnt 個進んだ head + cnt であり、n を超えたら n を引いて先頭に戻す。cnt + 1 は head が動いたあとに書き込み位置がずれ、まだ取り出していない要素を上書きしてしまう。head + cnt + 1 は1つ飛ばしになり、head が指す位置に何も入らない。head + cnt - 1 は最初の呼び出しで添字 0 となり配列の範囲外になる。

根拠:IPA 基本情報技術者試験 シラバス Ver.9.2 大分類1:基礎理論 中分類2:アルゴリズムとプログラミング(データ構造)

問10|スタック計算

次のプログラムで、主処理 の戻り値はどれか。

正の値は積み、負の値でスタックの一番上を取り出して c に反映する
○整数型: 計算(整数型の配列: x)  整数型の配列: st  整数型: sp ← 0  整数型: c ← 0  整数型: i  for (i を 1 から xの要素数 まで 1 ずつ増やす)    if (x[i] > 0)      sp ← sp + 1      st[sp] ← x[i]    else      if (sp > 0)        c ← c × 2 + st[sp]        sp ← sp - 1      endif    endif  endfor  return c ○整数型: 主処理()  整数型の配列: y ← {3, 5, -1, 2, -1, -1, -1}  return 計算(y)
  1. 10
  2. 24
  3. 27
  4. 54
正解と解説
正解:C. 27

3, 5 を積んだ状態で最初の -1 が来て 5 を取り出し c = 0×2+5 = 5。次に 2 を積み、-1 で 2 を取り出して c = 5×2+2 = 12、さらに -1 で 3 を取り出して c = 12×2+3 = 27。最後の -1 のとき sp は 0 なので何もしない。よって 27。10 は取り出した値を単純に足した場合、24 は先入れ先出しで取り出した場合、54 は最後の -1 でも空のスタックから 0 を取り出して 2 倍したとした場合の値である。

根拠:IPA 基本情報技術者試験 シラバス Ver.9.2 大分類1:基礎理論 中分類2:アルゴリズムとプログラミング(データ構造)

問11|線形探索

次の関数は、配列 x の中で値 k が最後に現れる位置(添字)を返す。k が一つも無いときは -1 を返す。プログラム中の【a】に入れるものはどれか。

線形探索(最後に現れる位置を返す)
○整数型: 最後の位置(整数型の配列: x, 整数型: k)  /* k が最後に現れる位置を返す。無ければ -1 を返す */  整数型: i  整数型: r ← -1  for (i を 1 から xの要素数 まで 1 ずつ増やす)    if (x[i] = k)      【a】    endif  endfor  return r
  1. return i
  2. r ← i
  3. r ← x[i]
  4. r ← r + 1
正解と解説
正解:B. r ← i

見つけても return せずに r ← i と控え続けることで、最後に一致した位置が r に残る。例えば x が {4, 7, 4, 9, 4}、k が 4 のとき r は 5 になる。return i はその場で戻るので最初に現れた位置(1)になってしまう。r ← x[i] は位置ではなく値そのもの(4)を返す。r ← r + 1 は出現回数に近い値になり、位置を表さない。

根拠:IPA 基本情報技術者試験 シラバス Ver.9.2 大分類1:基礎理論 中分類2:アルゴリズムとプログラミング(アルゴリズム)

問12|2分探索

次の2分探索を、x が {2, 5, 8, 11, 14, 17, 21, 26}、k が 21 の状態で実行する。変数 mid に代入される値を代入された順に並べたものはどれか。

2分探索
○整数型: 2分探索(整数型の配列: x, 整数型: k)  /* x は昇順に整列済み */  整数型: lo ← 1  整数型: hi ← xの要素数  整数型: mid  while (lo ≦ hi)    mid ← (lo + hi) ÷ 2 の商    if (x[mid] = k)      return mid    elseif (x[mid] < k)      lo ← mid + 1    else      hi ← mid - 1    endif  endwhile  return -1
  1. 4, 6, 8
  2. 4, 5, 7
  3. 4, 6, 7
  4. 4, 7, 8
正解と解説
正解:C. 4, 6, 7

1回目は lo=1, hi=8 で mid=4、x[4]=11 < 21 なので lo=5。2回目は lo=5, hi=8 で mid=6、x[6]=17 < 21 なので lo=7。3回目は lo=7, hi=8 で mid=7 となり x[7]=21 で一致する。よって 4, 6, 7。4, 6, 8 は最後の mid を切上げで求めた誤り、4, 5, 7 と 4, 7, 8 は範囲の狭め方を誤ったもので、(lo + hi) ÷ 2 の商 に従えば2回目の mid は 6 になる。

根拠:IPA 基本情報技術者試験 シラバス Ver.9.2 大分類1:基礎理論 中分類2:アルゴリズムとプログラミング(アルゴリズム)

問13|探索範囲

次の2分探索は、整列済みの配列 x から k を探し、見つかればその添字を、見つからなければ 0 を返す。プログラム中の【a】に入れるものはどれか。

2分探索(見つからないときは 0 を返す)
○整数型: 2分探索(整数型の配列: x, 整数型: k)  /* x は昇順に整列済み */  整数型: lo ← 1  整数型: hi ← xの要素数  整数型: mid  while (lo ≦ hi)    mid ← (lo + hi) ÷ 2 の商    if (x[mid] = k)      return mid    elseif (x[mid] > k)      hi ← mid - 1    else      【a】    endif  endwhile  return 0
  1. lo ← mid
  2. lo ← hi
  3. lo ← mid + 1
  4. hi ← mid - 1
正解と解説
正解:C. lo ← mid + 1

x[mid] < k のときは答えが mid より右にあるので、mid 自身を範囲から外して lo ← mid + 1 とする。lo ← mid では lo と mid が同じ値になったときに範囲が縮まらず、無限ループになる。lo ← hi は範囲を一気に右端へ飛ばすため間の要素を見落とす。hi ← mid - 1 は範囲を左へ縮めており、大小の判定と逆で目的の値に到達できない。

根拠:IPA 基本情報技術者試験 シラバス Ver.9.2 大分類1:基礎理論 中分類2:アルゴリズムとプログラミング(アルゴリズム)

問14|比較回数

要素数が 1,000 の昇順に整列済みの配列に対して2分探索を行うとき、配列の要素と探索対象の値を比較する回数は最大で何回か。

  1. 10
  2. 9
  3. 11
  4. 500
正解と解説
正解:A. 10

2分探索は1回の比較で候補の個数が半分以下になる。1回の比較で最大2個、2回で最大4個…と、m回の比較で見分けられる要素数は最大 2 の m 乗である。2 の 9 乗は 512 で 1,000 に足りず、2 の 10 乗は 1,024 で 1,000 を上回るので最大 10 回。9 では 512 個までしか特定できない。11 は余分に1回数えている。500 は線形探索の平均比較回数に近い値である。

根拠:IPA 基本情報技術者試験 シラバス Ver.9.2 大分類1:基礎理論 中分類2:アルゴリズムとプログラミング(アルゴリズム)

問15|バブル1巡

次のバブルソートを x が {5, 3, 8, 1, 9, 2} の状態で実行する。外側のループ(変数 i)の1回目が終わった時点での配列 x の内容はどれか。

バブルソート(昇順)
○整数型の配列: 整列(整数型の配列: x)  整数型: i, j, t  for (i を 1 から xの要素数 - 1 まで 1 ずつ増やす)    for (j を 1 から xの要素数 - i まで 1 ずつ増やす)      if (x[j] > x[j + 1])        t ← x[j]        x[j] ← x[j + 1]        x[j + 1] ← t      endif    endfor  endfor  return x
  1. {3, 5, 1, 8, 2, 9}
  2. {3, 5, 8, 1, 2, 9}
  3. {1, 3, 5, 8, 2, 9}
  4. {3, 5, 1, 2, 8, 9}
正解と解説
正解:A. {3, 5, 1, 8, 2, 9}

i が 1 のとき j は 1 から 5 まで動く。5と3を交換して {3,5,8,1,9,2}、8と1を交換して {3,5,1,8,9,2}、9と2を交換して {3,5,1,8,2,9} となる。{3,5,8,1,2,9} は 8 と 1 の交換を見落とした並びである。{1,3,5,8,2,9} は1巡で最小値が先頭に確定すると誤ったもので、確定するのは最大値 9 が右端に来ることだけである。{3,5,1,2,8,9} は 2 が 8 を飛び越えており、隣どうしの交換では起こらない。

根拠:IPA 基本情報技術者試験 シラバス Ver.9.2 大分類1:基礎理論 中分類2:アルゴリズムとプログラミング(アルゴリズム)

問16|降順整列

次のプログラムは、配列 x を降順(大きい順)に並べ替えて返す。プログラム中の【a】に入れる式はどれか。

バブルソートによる降順整列
○整数型の配列: 整列(整数型の配列: x)  /* x を降順に並べ替える */  整数型: i, j, t  for (i を 1 から xの要素数 - 1 まで 1 ずつ増やす)    for (j を 1 から xの要素数 - i まで 1 ずつ増やす)      if (【a】)        t ← x[j]        x[j] ← x[j + 1]        x[j + 1] ← t      endif    endfor  endfor  return x
  1. x[j] > x[j + 1]
  2. x[i] < x[i + 1]
  3. x[j] < x[j - 1]
  4. x[j] < x[j + 1]
正解と解説
正解:D. x[j] < x[j + 1]

降順にするには、隣り合う2つのうち左が右より小さいときに交換すればよいので x[j] < x[j + 1] が正しい。x[j] > x[j + 1] は昇順の条件である。x[i] < x[i + 1] は内側のループで動く j ではなく i を見ているため、隣どうしの比較になっていない。x[j] < x[j - 1] は j が 1 のとき x[0] を参照し、1始まりの配列では範囲外になる。

根拠:IPA 基本情報技術者試験 シラバス Ver.9.2 大分類1:基礎理論 中分類2:アルゴリズムとプログラミング(アルゴリズム)

問17|選択ソート

次の選択ソートを x が {4, 1, 3, 5, 2} の状態で実行する。外側のループの変数 i が 2 の回を終えた時点での配列 x の内容はどれか。

選択ソート(昇順)
○整数型の配列: 整列(整数型の配列: x)  整数型: i, j, m, t  for (i を 1 から xの要素数 - 1 まで 1 ずつ増やす)    m ← i    for (j を i + 1 から xの要素数 まで 1 ずつ増やす)      if (x[j] < x[m])        m ← j      endif    endfor    t ← x[i]    x[i] ← x[m]    x[m] ← t  endfor  return x
  1. {1, 2, 3, 4, 5}
  2. {1, 4, 3, 5, 2}
  3. {1, 2, 3, 5, 4}
  4. {1, 2, 4, 5, 3}
正解と解説
正解:C. {1, 2, 3, 5, 4}

i が 1 のときは全体の最小値 1(添字2)を見つけて x[1] と交換し {1,4,3,5,2}。i が 2 のときは添字2以降の最小値 2(添字5)を見つけて x[2] と交換し {1,2,3,5,4} となる。{1,4,3,5,2} は i が 1 の回までの結果、{1,2,3,4,5} は最後まで実行した結果であり、いずれも問われた時点とは異なる。{1,2,4,5,3} は交換ではなく要素をずらしたときの並びである。

根拠:IPA 基本情報技術者試験 シラバス Ver.9.2 大分類1:基礎理論 中分類2:アルゴリズムとプログラミング(アルゴリズム)

問18|最小位置

関数 最小位置(x, s) は、配列 x の添字 s 以降で最も小さい要素の添字を返す。この関数を使う選択ソートが正しく昇順に整列するために、プログラム中の【a】に入れる式はどれか。

最小値の位置を求める関数と、それを使う選択ソート
○整数型: 最小位置(整数型の配列: x, 整数型: s)  /* x[s] 以降で最も小さい要素の添字を返す */  整数型: m ← s  整数型: j  for (j を s + 1 から xの要素数 まで 1 ずつ増やす)    if (【a】)      m ← j    endif  endfor  return m ○整数型の配列: 選択ソート(整数型の配列: x)  整数型: i, m, t  for (i を 1 から xの要素数 - 1 まで 1 ずつ増やす)    m ← 最小位置(x, i)    t ← x[i]    x[i] ← x[m]    x[m] ← t  endfor  return x
  1. x[j] < x[m]
  2. x[j] < x[s]
  3. x[m] < x[j]
  4. x[j] < x[j - 1]
正解と解説
正解:A. x[j] < x[m]

m は「これまでで最も小さかった要素の添字」なので、新しい要素 x[j] をその最小値 x[m] と比べ、小さければ m を更新する。x[j] < x[s] は常に先頭の要素と比べるため、最後に見つかった「先頭より小さい要素」の位置になり最小とは限らない。x[m] < x[j] は大小が逆で最大値の位置を返す。x[j] < x[j - 1] は隣どうしの比較で、範囲全体の最小値を求めていない。

根拠:IPA 基本情報技術者試験 シラバス Ver.9.2 大分類1:基礎理論 中分類2:アルゴリズムとプログラミング(アルゴリズム)

問19|挿入ソート

次の挿入ソートを x が {6, 2, 9, 4, 7} の状態で実行する。外側のループの変数 i が 4 の回を終えた時点での配列 x の内容はどれか。

挿入ソート(昇順)
○整数型の配列: 挿入ソート(整数型の配列: x)  整数型: i, j, v  for (i を 2 から xの要素数 まで 1 ずつ増やす)    v ← x[i]    j ← i - 1    while (j ≧ 1 and x[j] > v)      x[j + 1] ← x[j]      j ← j - 1    endwhile    x[j + 1] ← v  endfor  return x
  1. {2, 6, 9, 4, 7}
  2. {2, 4, 6, 7, 9}
  3. {2, 6, 4, 9, 7}
  4. {2, 4, 6, 9, 7}
正解と解説
正解:D. {2, 4, 6, 9, 7}

i が 2 で 2 を前に差し込み {2,6,9,4,7}、i が 3 では 9 がすでに正しい位置なので変化なし、i が 4 では v が 4 となり 9 と 6 を1つずつ右へずらして 4 を差し込み {2,4,6,9,7} になる。{2,6,9,4,7} は i が 3 までの結果、{2,4,6,7,9} は最後まで実行した結果である。{2,6,4,9,7} は 4 を 6 の後ろに入れており、整列済み部分への差し込み位置を誤っている。

根拠:IPA 基本情報技術者試験 シラバス Ver.9.2 大分類1:基礎理論 中分類2:アルゴリズムとプログラミング(アルゴリズム)

問20|マージ

次の関数は、昇順に整列済みの二つの配列 p と q を併合して、昇順に整列した一つの配列を返す。プログラム中の【a】に入れる式はどれか。

整列済みの2つの配列の併合(マージ)
○整数型の配列: 併合(整数型の配列: p, 整数型の配列: q)  /* p, q はともに昇順に整列済み */  整数型の配列: r  整数型: i ← 1  整数型: j ← 1  整数型: k  for (k を 1 から pの要素数 + qの要素数 まで 1 ずつ増やす)    if (j > qの要素数)      r[k] ← p[i]      i ← i + 1    elseif (i > pの要素数)      r[k] ← q[j]      j ← j + 1    elseif (p[i] ≦ q[j])      r[k] ← p[i]      【a】    else      r[k] ← q[j]      j ← j + 1    endif  endfor  return r
  1. i ← i - 1
  2. i ← j + 1
  3. j ← j + 1
  4. i ← i + 1
正解と解説
正解:D. i ← i + 1

p[i] を取り出したのだから、進めるべきは p 側の添字 i である。i ← i + 1 が正しい。j ← j + 1 では p 側が進まないので p[i] が何度も取り出され、q 側だけを読み飛ばす。i ← j + 1 は二つの添字を取り違えており、p の要素を飛ばしたり範囲外を参照したりする。i ← i - 1 は添字が 0 以下になり、1始まりの配列では範囲外になる。

根拠:IPA 基本情報技術者試験 シラバス Ver.9.2 大分類1:基礎理論 中分類2:アルゴリズムとプログラミング(アルゴリズム)

問21|前順走査

次のプログラムで 前順(1) を呼び出したとき、出力される順序はどれか。ここで、L[p] は節 p の左の子、R[p] は右の子の添字で、0 は子が無いことを表す。手続 出力 は引数の値を一つ出力する。

2分木の前順(行きがけ順)走査
文字列型の配列: v ← {"A", "B", "C", "D", "E", "F", "G"}整数型の配列: L ← {2, 4, 6, 0, 0, 0, 0}整数型の配列: R ← {3, 5, 7, 0, 0, 0, 0} ○前順(整数型: p)  if (p ≠ 0)    出力(v[p])    前順(L[p])    前順(R[p])  endif
  1. A B D E C F G
  2. D B E A F C G
  3. D E B F G C A
  4. A B C D E F G
正解と解説
正解:A. A B D E C F G

前順は「自分・左部分木・右部分木」の順である。根 A を出し、左の B、その左の D、右の E、続いて右部分木の C、その左の F、右の G となる。D B E A F C G は中順(通りがけ順)、D E B F G C A は後順(帰りがけ順)の結果である。A B C D E F G は配列の添字順に並べただけで、走査の順序ではない。

根拠:IPA 基本情報技術者試験 試験要綱 Ver.5.6 出題範囲(科目B試験)アルゴリズムとプログラミング

問22|中順走査

次のプログラムで 中順(1) を呼び出したとき、出力される順序はどれか。ここで、L[p] は節 p の左の子、R[p] は右の子の添字で、0 は子が無いことを表す。手続 出力 は引数の値を一つ出力する。

2分木の中順(通りがけ順)走査
文字列型の配列: v ← {"P", "Q", "R", "S", "T"}整数型の配列: L ← {2, 4, 0, 0, 0}整数型の配列: R ← {3, 5, 0, 0, 0} ○中順(整数型: p)  if (p ≠ 0)    中順(L[p])    出力(v[p])    中順(R[p])  endif
  1. P Q S T R
  2. S Q T P R
  3. S T Q R P
  4. S Q T R P
正解と解説
正解:B. S Q T P R

中順は「左部分木・自分・右部分木」の順である。節1(P)の左部分木である節2(Q)へ進み、さらにその左の S を出し、Q を出し、右の T を出す。戻って P を出し、最後に右部分木の R を出す。よって S Q T P R。P Q S T R は前順、S T Q R P は後順の結果である。S Q T R P は自分を出す位置を根だけ後回しにした誤りである。

根拠:IPA 基本情報技術者試験 試験要綱 Ver.5.6 出題範囲(科目B試験)アルゴリズムとプログラミング

問23|後順走査

次のプログラムで 後順(1) を呼び出すと D, E, B, C, A の順に出力される。プログラム中の【a】に入れるものはどれか。手続 出力 は引数の値を一つ出力する。

2分木の後順(帰りがけ順)走査
文字列型の配列: v ← {"A", "B", "C", "D", "E"}整数型の配列: L ← {2, 4, 0, 0, 0}整数型の配列: R ← {3, 5, 0, 0, 0} ○後順(整数型: p)  /* 節 p を根とする部分木を後順(帰りがけ順)で出力する */  if (p ≠ 0)    後順(L[p])    【a】    出力(v[p])  endif
  1. 後順(p)
  2. 後順(L[p])
  3. 後順(R[p])
  4. 出力(v[R[p]])
正解と解説
正解:C. 後順(R[p])

後順は「左部分木・右部分木・自分」の順なので、左の走査の次には右部分木の走査 後順(R[p]) が入る。後順(p) は自分自身を同じ引数で呼び直すため終了せず、無限に再帰する。後順(L[p]) は左部分木を二度たどり、右部分木を一度もたどらない。出力(v[R[p]]) は右部分木の根の値しか出さず、しかも子が無いとき v[0] を参照してしまう。

根拠:IPA 基本情報技術者試験 試験要綱 Ver.5.6 出題範囲(科目B試験)アルゴリズムとプログラミング

問24|階乗

次のプログラムは階乗を再帰で求める。主処理 の戻り値が 120 になるように、プログラム中の【a】に入れる式はどれか。

階乗を求める再帰関数
○整数型: 階乗(整数型: n)  if (n ≦ 1)    return 1  else    return 【a】  endif ○整数型: 主処理()  整数型: k ← 5  return 階乗(k)
  1. n × 階乗(n)
  2. 階乗(n - 1)
  3. (n - 1) × 階乗(n - 1)
  4. n × 階乗(n - 1)
正解と解説
正解:D. n × 階乗(n - 1)

階乗の定義は n! = n × (n-1)! なので n × 階乗(n - 1) が正しく、5×4×3×2×1 = 120 になる。n × 階乗(n) は引数が小さくならないため終了条件に到達せず無限に再帰する。階乗(n - 1) は掛け算をしていないので必ず 1 を返す。(n - 1) × 階乗(n - 1) は 4×3×2×1×1 = 24 となり 120 にならない。

根拠:IPA 基本情報技術者試験 シラバス Ver.9.2 大分類1:基礎理論 中分類2:アルゴリズムとプログラミング(アルゴリズム)

問25|呼出回数

次のプログラムで 主処理 を1回実行したとき、関数 fib が呼び出される回数は合計で何回か。主処理 からの1回目の呼び出しも数えるものとする。

フィボナッチ数を求める再帰関数
○整数型: fib(整数型: n)  /* fib(1) = 1, fib(2) = 1 とする */  if (n ≦ 2)    return 1  else    return fib(n - 1) + fib(n - 2)  endif ○整数型: 主処理()  return fib(6)
  1. 8
  2. 9
  3. 15
  4. 25
正解と解説
正解:C. 15

呼び出し総数を C(n) とすると C(1) = C(2) = 1、C(n) = 1 + C(n-1) + C(n-2) である。C(3) = 3、C(4) = 5、C(5) = 9、C(6) = 1 + 9 + 5 = 15 回。8 は fib(6) の値そのもの、9 は fib(5) を求めるときの呼び出し回数であり、いずれも問われた値ではない。25 は呼び出しの木を数え違えた値である。

根拠:IPA 基本情報技術者試験 シラバス Ver.9.2 大分類1:基礎理論 中分類2:アルゴリズムとプログラミング(アルゴリズム)

問26|反復fib

次の関数は、フィボナッチ数(fib(1) = 1, fib(2) = 1)を繰返しで求める。fib(7) が 13 を返すように、プログラム中の【a】に入れる式はどれか。

フィボナッチ数を繰返しで求める
○整数型: fib(整数型: n)  /* fib(1) = 1, fib(2) = 1 とする */  整数型: p ← 1  整数型: q ← 1  整数型: t  整数型: i  if (n ≦ 2)    return 1  endif  for (i を 3 から n まで 1 ずつ増やす)    t ← p + q    【a】    q ← t  endfor  return q
  1. p ← q
  2. p ← t
  3. q ← p
  4. p ← p + q
正解と解説
正解:A. p ← q

p に1つ前、q に直前の値を持たせる。新しい値 t を作ったら、次の回に備えて p には現在の q を、q には t を移す必要があるので p ← q が正しい。p ← t や p ← p + q では p と q が同じ値になり、値が毎回2倍される。q ← p は直後の q ← t で上書きされるうえ p が更新されないため、q は 1 ずつしか増えない。

根拠:IPA 基本情報技術者試験 シラバス Ver.9.2 大分類1:基礎理論 中分類2:アルゴリズムとプログラミング(アルゴリズム)

問27|再帰の順序

次のプログラムで 主処理 を実行したとき、出力される順序はどれか。手続 出力 は引数の値を一つ出力する。

自分自身を2回呼ぶ再帰手続
○f(整数型: n)  if (n > 0)    f(n - 1)    出力(n)    f(n - 1)  endif ○主処理()  /* 出力された値を左から順に並べたものを答える */  f(3)
  1. 1 2 3 2 1
  2. 1 2 1 3 1 2 1
  3. 3 2 1 1 2 3
  4. 1 1 2 1 1 2 3
正解と解説
正解:B. 1 2 1 3 1 2 1

f(1) は 1 だけを出す。f(2) は f(1)・2・f(1) の順なので 1 2 1。f(3) は f(2)・3・f(2) なので 1 2 1 3 1 2 1 の7個になる。1 2 3 2 1 は5個しかなく、f(3) が f(2) を2回呼ぶ構造と合わない。3 2 1 1 2 3 は出力を再帰呼出しの前後に置いた場合、1 1 2 1 1 2 3 は出力を2つの再帰呼出しの後ろにまとめた場合の並びである。

根拠:IPA 基本情報技術者試験 シラバス Ver.9.2 大分類1:基礎理論 中分類2:アルゴリズムとプログラミング(アルゴリズム)

問28|分割統治

次の関数 最大(x, lo, hi) は、配列 x の添字 lo から hi までの範囲の最大値を分割統治法で求める。プログラム中の【a】に入れる式はどれか。

分割統治法で配列の最大値を求める
○整数型: 最大(整数型の配列: x, 整数型: lo, 整数型: hi)  整数型: mid  整数型: p  整数型: q  if (lo = hi)    return x[lo]  endif  mid ← (lo + hi) ÷ 2 の商  p ← 最大(x, lo, mid)  q ← 【a】  if (p ≧ q)    return p  endif  return q
  1. 最大(x, mid, hi)
  2. 最大(x, mid + 1, hi)
  3. 最大(x, mid, hi - 1)
  4. 最大(x, lo, hi)
正解と解説
正解:B. 最大(x, mid + 1, hi)

左半分を lo から mid まで調べたので、右半分は mid + 1 から hi までとしなければ範囲が重なる。最大(x, mid, hi) では lo と hi が隣り合うとき mid = lo となり、同じ範囲を呼び直して無限に再帰する。最大(x, lo, hi) も引数が変わらず無限再帰になる。最大(x, mid, hi - 1) は右端の要素を調べないので、最大値が末尾にあるとき正しい答えにならない。

根拠:IPA 基本情報技術者試験 シラバス Ver.9.2 大分類1:基礎理論 中分類2:アルゴリズムとプログラミング(アルゴリズム)

問29|互除法

次の関数 g(m, n) は何を求めるものか。ここで m は正の整数、n は 0 以上の整数とする。

再帰で書いた関数 g
○整数型: g(整数型: m, 整数型: n)  if (n = 0)    return m  else    return g(n, m を n で割った余り)  endif ○主処理()  出力(g(1071, 462))  /* 21 が出力される */
  1. m を n で割った商
  2. m と n の最小公倍数
  3. m と n のうち小さいほう
  4. m と n の最大公約数
正解と解説
正解:D. m と n の最大公約数

これはユークリッドの互除法である。m と n の最大公約数は n と「m を n で割った余り」の最大公約数に等しく、余りが 0 になったときの割る数が最大公約数になる。1071 と 462 では 147、21、0 と余りが進み 21 が得られる。最小公倍数なら 1071×462÷21 = 23,562 になる。商なら 2、小さいほうなら 462 であり、いずれも 21 とは一致しない。

根拠:IPA 基本情報技術者試験 シラバス Ver.9.2 大分類1:基礎理論 中分類2:アルゴリズムとプログラミング(アルゴリズム)

問30|木の高さ

次のプログラムで h(1) の戻り値はどれか。ここで、L[p] は節 p の左の子、R[p] は右の子の添字で、0 は子が無いことを表す。

2分木に対する再帰関数 h
整数型の配列: L ← {2, 4, 0, 0, 6, 0, 0}整数型の配列: R ← {3, 5, 0, 0, 7, 0, 0} ○整数型: h(整数型: p)  整数型: s  整数型: t  if (p = 0)    return 0  endif  s ← h(L[p])  t ← h(R[p])  if (s ≧ t)    return s + 1  endif  return t + 1
  1. 2
  2. 3
  3. 7
  4. 4
正解と解説
正解:D. 4

h は部分木の高さ(根から最も深い葉までの節の個数)を返す。節4は葉なので h(4)=1、節6と節7も葉で h=1 だから h(5)=2、h(2)=max(1,2)+1=3、h(3)=1 なので h(1)=max(3,1)+1=4 である。2 は節5までの高さ、3 は節2を根とする部分木の高さにすぎない。7 は節の総数であって高さではない。

根拠:IPA 基本情報技術者試験 試験要綱 Ver.5.6 出題範囲(科目B試験)アルゴリズムとプログラミング

演習:この章の問題を解く

ランダム出題の演習ツールです(JavaScript が有効な場合に動きます)。上の「確認問題」はそのままでもすべて読めます。

※ 解説は学習用の情報提供です。最新の出題範囲・制度は必ずIPAの公式発表をご確認ください。
※ 出題はIPA公開のシラバスVer.9.2(2026年1月8日適用)に沿った仮の宿 学習室のオリジナル問題です。擬似言語の記述形式もIPA公開の仕様に合わせています。試験制度・実施要項はIPAの公式発表をご確認ください(2027年度春ごろに新試験制度へ移行予定)。