メインコンテンツへスキップ
基本情報技術者基本情報科目B擬似言語アルゴリズム

基本情報 科目B スタックとキューのトレース練習|LIFOとFIFOを操作表で1つずつ追う

科目Bの頻出データ構造「スタック(後入れ先出し・LIFO)」と「キュー(先入れ先出し・FIFO)」を、プッシュ/ポップ・エンキュー/デキューの操作を表に書いて1つずつ追うトレースで攻略。同じ入力でも取り出す順番が逆になる理由、頂点・先頭・末尾ポインタの動き、つまずきを具体例で実演します。

公開:

基本情報 科目B スタックとキューのトレース練習

基本情報技術者試験の科目Bでは、探索・ソート・再帰といったアルゴリズムと並んで、データ構造そのものの操作もよく問われます。なかでも定番が スタック と キュー です。どちらも「データを順番にためて、順番に取り出す」入れ物ですが、取り出す順番のルールが正反対なので、ここを取り違えると設問の空欄がまるごと外れます。本記事は、スタックとキューの操作を変数の値を表に書きながら 1 つずつ追う トレース で攻略する練習帳です。合計・最大値・線形探索のトレース練習・二分探索のトレース練習・ソート(整列)のトレース練習・再帰のトレース練習 の続編にあたります。

本記事は 過去問AI が学習用に作成したオリジナルの例題です。掲載している擬似言語は IPA の過去問・公式サンプルの転載ではなく、説明用に書き起こしたものです。擬似言語の正式な記述形式は必ず IPA 公式ページ で確認してください。記法そのものの読み方は 基本情報 科目Bの擬似言語 記法早見表 にまとめています。

スタックとキューは「出し方」が正反対

  • スタック(stack):後入れ先出し(LIFO:Last In, First Out)。あとから入れたものが先に出る。本を机に積み上げて、上から取るイメージ
  • キュー(queue):先入れ先出し(FIFO:First In, First Out)。先に入れたものが先に出る。レジに並んだ行列で、先頭から順にさばかれるイメージ

操作の名前も決まっています。

  • スタック:上に積むのが プッシュ(push)、一番上を取り出すのが ポップ(pop)
  • キュー:後ろに追加するのが エンキュー(enqueue)、先頭から取り出すのが デキュー(dequeue)

この記事の例題は、次の約束ごとで進めます(科目Bの標準的なルールです)。

  • 代入は ←(右の値を左の変数に入れる)
  • 配列の添字は 1 始まり(最初の要素が 1 番目)
  • 関数定義の先頭の ○ は「ここから関数の中身」を表します

記法そのものが不安なら、先に 記法早見表 で ← や配列の添字の扱いを確認してから戻ってくるとスムーズです。

スタックの例題コード

配列 スタック と、一番上の位置を指す変数 頂点(最初は 0 =空)でスタックを表します。

○プッシュ(整数型: 値)
    頂点 ← 頂点 + 1
    スタック[頂点] ← 値

○整数型: ポップ()
    値 ← スタック[頂点]
    頂点 ← 頂点 - 1
    return 値

プッシュは「頂点を 1 つ上げてから、その位置に値を置く」。ポップは「頂点の位置の値を読んでから、頂点を 1 つ下げて返す」。頂点が常に「一番上の要素の位置」を指しているのがポイントです。

スタックをトレースする

プッシュ(3) → プッシュ(7) → プッシュ(1) → ポップ() → プッシュ(9) → ポップ() → ポップ() の順に操作します。中身は左を底、右を上(頂点側)として並べます。

操作頂点(操作後)スタックの中身(底→上)戻り値
プッシュ(3)13—
プッシュ(7)23, 7—
プッシュ(1)33, 7, 1—
ポップ()23, 71
プッシュ(9)33, 7, 9—
ポップ()23, 79
ポップ()137

取り出された順番は 1 → 9 → 7。最後に積んだものから先に出ていく、これが LIFO(後入れ先出し) です。3 つ目のポップで残るのは、最初に積んだ 3 だけになります。

キューの例題コード

配列 キュー と、取り出す先頭位置 先頭(最初は 1)・最後に入れた位置 末尾(最初は 0 =空)でキューを表します。

○エンキュー(整数型: 値)
    末尾 ← 末尾 + 1
    キュー[末尾] ← 値

○整数型: デキュー()
    値 ← キュー[先頭]
    先頭 ← 先頭 + 1
    return 値

エンキューは「末尾を 1 つ進めて、その位置に値を置く」。デキューは「先頭の位置の値を読んでから、先頭を 1 つ進めて返す」。先頭と末尾という 2 つのポインタが、どちらも増える方向に動くのが特徴です。

キューをトレースする

スタックと比べやすいよう、まったく同じ入力で操作します。エンキュー(3) → エンキュー(7) → エンキュー(1) → デキュー() → エンキュー(9) → デキュー() → デキュー()。残っている要素は「先頭から末尾まで」を並べます。

操作先頭末尾残っている要素(先頭→末尾)戻り値
エンキュー(3)113—
エンキュー(7)123, 7—
エンキュー(1)133, 7, 1—
デキュー()237, 13
エンキュー(9)247, 1, 9—
デキュー()341, 97
デキュー()4491

取り出された順番は 3 → 7 → 1。先に入れたものから先に出ていく、これが FIFO(先入れ先出し) です。

同じ入力なのに取り出す順が逆になる

ここが本記事の山場です。スタックもキューも、入れた値は 3 → 7 → 1 → 9 とまったく同じでした。それでも取り出した順番は、

  • スタック:1 → 9 → 7(後入れ先出し)
  • キュー:3 → 7 → 1(先入れ先出し)

と正反対になります。設問は「この操作列のあと、最初に取り出される値はどれか」「3 回取り出すと何が残るか」といった形で、この順序の違いを突いてきます。入れた順だけ見て答えず、必ずスタックかキューかを確認するのが鉄則です。

つまずきやすい3つのポイント

  1. 出し入れする場所を取り違える。スタックは出すのも入れるのも 上(頂点)の 1 か所。キューは 末尾に入れて先頭から出すと、入口と出口が別です。「キューなのに後ろから取り出す」と勘違いすると順序が丸ごと逆になります。
  2. 読む順と、ポインタを動かす順。ポップもデキューも「先に値を読んでから、ポインタを動かす」順序です。先に 頂点 ← 頂点 - 1 をしてしまうと、1 つずれた要素を読んでしまいます。トレースでは「値 ← …」の行を必ず先に処理してください。
  3. 配列に古い値は残る。配列で実装すると、ポップしても スタック[3] の中身(さっきの例なら 1)は物理的には残っています。論理的な中身は「頂点が指す範囲」で決まるので、頂点より上の値は無視します。キューも同じで、デキュー済みの キュー[1] は残っていても、先頭より前は存在しない扱いです。

もう一つの定番:循環バッファ(リングバッファ)

キューを配列で素直に作ると、エンキュー/デキューを繰り返すうちに 末尾 がどんどん右へ進み、配列の右端を使い切ってしまいます。そこで実務や応用問題では、配列の端まで来たら先頭(添字 1)へ折り返して空いた場所を再利用する 循環バッファ(リングバッファ) がよく登場します。先頭・末尾を「配列サイズで割った余り」で進めるのがコツですが、まずは本記事のように まっすぐ伸びる素朴なキュー で先頭・末尾の動きを体に入れてから、折り返しに進むのがおすすめです。

トレースで詰まらないためのコツ

スタックは 頂点 1 本、キューは 先頭・末尾の 2 本のポインタを、操作のたびに表へ書き出すのが最大のコツです。中身を毎回ぜんぶ書き直すより、「ポインタがいくつになったか」と「その範囲に何が並ぶか」をセットで追うと、要素数が増えても迷子になりません。そして操作の前に必ず「これはスタック?キュー?」と一言確認してから取り出す向きを決めてください。

次のステップ

スタックとキューまで追えれば、あとは要素が参照でつながる 連結リスト(単方向リスト)のトレース練習 に進むと、科目Bで問われるデータ構造の基本がそろいます。アルゴリズムのトレースがまだなら、基礎の 合計・最大値・線形探索のトレース練習、半分ずつ絞り込む 二分探索のトレース練習、二重ループの ソート(整列)のトレース練習、コールスタックを追う 再帰のトレース練習 を先にどうぞ。読む速度を上げる訓練法は 基本情報科目B|擬似言語アルゴリズム読解の3ステップ訓練法 で扱っています。つまずきが記法なのかトレースなのか切り分けたいときは 科目Bがわからない人へ、科目B 全体の進め方は 基本情報技術者 科目B完全対策 が地図になります。

手を動かす練習台としては、過去問AI の 基本情報 アルゴリズムとプログラミング分野の過去問 が使えます(こちらは科目A 相当の選択式で、科目B そのものの形式ではない点だけ意識してください)。各問題ページの AI コパイロットに「このスタックの操作を、頂点の値と中身を表にして 1 つずつトレースして」と頼めば、本記事と同じ追い方を対話でその場で再現できます。

よくある質問

Q. スタックとキューはどう違いますか? 取り出す順番のルールが正反対です。スタックは後入れ先出し(LIFO)で、あとから入れたものが先に出ます。キューは先入れ先出し(FIFO)で、先に入れたものが先に出ます。同じ順番でデータを入れても、取り出す順番は逆になります。設問では入れた順だけで判断せず、まずスタックかキューかを確認してください。

Q. プッシュ・ポップ・エンキュー・デキューとは何ですか? スタックの操作が、上に積むプッシュと一番上を取り出すポップです。キューの操作が、後ろに追加するエンキューと先頭から取り出すデキューです。スタックは上の 1 か所だけで出し入れし、キューは末尾に入れて先頭から出す、と入口と出口の場所が違う点が区別のかなめです。

Q. ポップやデキューでトレースが合わなくなります。何が原因ですか? 多くは処理する順番の取り違えです。ポップもデキューも、先に値を読んでから、そのあとでポインタ(頂点や先頭)を動かします。先にポインタを動かしてしまうと、1 つずれた要素を読んでしまい戻り値が変わります。トレースのときは値を読む行を必ず先に処理し、ポインタの更新は後に書いてください。

Q. 配列でスタックを作ると、ポップした値は消えますか? 物理的には配列に残ります。ポップは頂点を 1 つ下げるだけなので、古い値はその場所に残っていますが、頂点より上は「無い」ものとして扱います。論理的な中身は常に頂点が指す範囲で決まる、と考えるとトレースが安定します。キューも同様で、デキュー済みの先頭より前の要素は残っていても存在しない扱いです。

まとめ

  • スタックは 後入れ先出し(LIFO)、キューは 先入れ先出し(FIFO)。取り出す順番のルールが正反対
  • スタックは 頂点 1 本のポインタで上だけを出し入れ。キューは 先頭・末尾 の 2 本で末尾に入れて先頭から出す
  • 同じ入力 3→7→1→9 でも、スタックは 1→9→7、キューは 3→7→1 と取り出し順が逆になる
  • ポップ・デキューは 先に値を読んでからポインタを動かす。配列実装では古い値が残るので ポインタが指す範囲で中身を判断する
  • トレースは ポインタの値とその範囲の並びをセットで表に書き、操作の前に「スタック?キュー?」を確認する

線形探索・二分探索・ソート・再帰に、データ構造のスタック・キューを加えれば、科目Bのアルゴリズム設問で読めない問題はほぼ無くなります。

基本情報技術者 の過去問で実戦演習する

記事の内容を実戦で確認しましょう。AI コパイロット付きで分からない点はその場で解決できます。

この記事に関連する過去問

関連記事

※ 本記事は 過去問AI が独自にまとめた学習ガイドです。試験要項の最新情報は必ず IPA 公式ページで確認してください。