15 スタックとキュー

データを「どの順番で取り出すか」を決める。

配列は、要素番号を指定して好きな場所のデータを参照できます。 しかし実際の処理では、「最後に入れたものから取り出したい」「先に来たものから順番に処理したい」 という場面がよくあります。

そのような順番のルールを持つ代表的なデータ構造が、スタックキューです。 試験では、操作の順番から最終状態や取り出される値を問う問題がよく出ます。
この資料では、スタックの「入れる」操作を push、「取り出す」操作を pop と呼びます。 キューの「入れる」操作を enqueue、「取り出す」操作を dequeue と呼びます。

1. スタック

スタックは、最後に入れたデータを最初に取り出すデータ構造です。 この性質を LIFO(Last In, First Out) といいます。

仕組みの図解

スタック:上から入れて、上から取り出す D C B A top bottom push:上に積む pop:上から取り出す push(A), push(B), push(C), push(D) この後 pop すると、最初に出るのは D 取り出し順:D, C, B, A
スタックのイメージ: 皿を積むとき、最後に置いた皿が一番上にあります。 取り出すときも一番上から取るので、最後に入れたものが最初に出ます。

スタックの基本操作

操作意味変化
push(x)x をスタックに入れるtop が1つ上がる
pop()一番上の値を取り出すtop が1つ下がる
peek()一番上の値を見る取り出さないので状態は変わらない

コード例:配列でスタックを表す

ここでは、top を「現在一番上にある要素番号」とします。 空のときは top = 0 です。

整数型の配列: stack
整数型: top ← 0

○ push(整数型: x)
    top ← top + 1
    stack[top] ← x

○整数型: pop()
    整数型: x
    x ← stack[top]
    top ← top - 1
    return x
実際のプログラムでは範囲チェックが必要: 空のスタックから pop しようとする状態をアンダーフロー、 容量いっぱいのスタックに push しようとする状態をオーバーフローといいます。

トレース例

push(10)push(20)push(30)pop()push(40) の順に操作します。

操作取り出した値スタックの状態(下から上)top
初期状態-{}0
push(10)-{10}1
push(20)-{10, 20}2
push(30)-{10, 20, 30}3
pop()30{10, 20}2
push(40)-{10, 20, 40}3

2. キュー

キューは、先に入れたデータを先に取り出すデータ構造です。 この性質を FIFO(First In, First Out) といいます。

仕組みの図解

キュー:後ろから入れて、前から取り出す dequeue 前から出る A B C D front rear enqueue 後ろに入る enqueue(A), enqueue(B), enqueue(C), enqueue(D) この後 dequeue すると、最初に出るのは A
キューのイメージ: レジ待ちの列では、先に並んだ人から順番に処理されます。 新しく来た人は列の後ろに並びます。

キューの基本操作

操作意味変化
enqueue(x)x をキューの後ろに入れるrear 側に追加する
dequeue()キューの前から値を取り出すfront 側から削除する
peek()先頭の値を見る取り出さないので状態は変わらない

コード例:配列でキューを表す

ここでは front を「次に取り出す位置」、 rear を「次に入れる位置」とします。 空のときは front = 1rear = 1 とします。

整数型の配列: queue
整数型: front ← 1
整数型: rear ← 1

○ enqueue(整数型: x)
    queue[rear] ← x
    rear ← rear + 1

○整数型: dequeue()
    整数型: x
    x ← queue[front]
    front ← front + 1
    return x
配列でキューを実装すると、取り出すたびに front が右へ進みます。 実用上は、配列の末尾まで使ったら先頭に戻る循環キューを使うことがあります。 この資料では、まず基本の取り出し順を優先して扱います。

トレース例

enqueue(10)enqueue(20)enqueue(30)dequeue()enqueue(40) の順に操作します。

操作取り出した値キューの状態(前から後ろ)frontrear
初期状態-{}11
enqueue(10)-{10}12
enqueue(20)-{10, 20}13
enqueue(30)-{10, 20, 30}14
dequeue()10{20, 30}24
enqueue(40)-{20, 30, 40}25

3. スタックとキューの比較

項目スタックキュー
取り出し順最後に入れたものが先先に入れたものが先
性質LIFOFIFO
入れる操作pushenqueue
取り出す操作popdequeue
戻る操作、関数呼び出し、逆順処理待ち行列、印刷待ち、幅優先探索
試験での注意: 「取り出す」操作が行われた瞬間に、その値はデータ構造から消えます。 問題を解くときは、操作のたびに状態を書き換えるのが安全です。

4. 理解度チェック問題

問題15-1

スタックの性質として正しいものはどれか。

解説を表示 正解:ア
スタックは LIFO です。最後に push したデータが、一番上にあるため最初に pop されます。

問題15-2

キューの性質として正しいものはどれか。

解説を表示 正解:イ
キューは FIFO です。先に enqueue されたデータが、先に dequeue されます。

問題15-3

空のスタックに push(3)push(5)push(8) を行った後、pop() で取り出される値はどれか。

解説を表示 正解:ウ
スタックでは最後に入れたものから出ます。最後に push した値は 8 なので、最初の pop で 8 が出ます。

問題15-4

空のキューに enqueue(3)enqueue(5)enqueue(8) を行った後、dequeue() で取り出される値はどれか。

解説を表示 正解:エ
キューでは先に入れたものから出ます。最初に enqueue した値は 3 なので、最初の dequeue で 3 が出ます。

問題15-5 空欄補充

次のスタックの push 処理で、空欄 [ A ] に入るものとして適切なものはどれか。

○ push(整数型: x)
    top ← top + 1
    [ A ]
解説を表示 正解:イ
top を1つ進めた後、その位置に新しい値 x を格納します。

問題15-6 空欄補充

次のキューの dequeue 処理で、値を取り出した後に行う更新として適切なものはどれか。

○整数型: dequeue()
    整数型: x
    x ← queue[front]
    [ B ]
    return x
解説を表示 正解:ア
front は次に取り出す位置です。 先頭の値を取り出した後は、次の要素を指すように front を1つ進めます。

問題15-7

空のスタックに次の操作を行う。最後の pop() で取り出される値はどれか。

push(1)
push(2)
pop()
push(3)
pop()
解説を表示 正解:ウ
push(1) で {1}、push(2) で {1,2}、pop() で 2 が出て {1}。 その後 push(3) で {1,3} になるので、最後の pop() では 3 が出ます。

問題15-8

空のキューに次の操作を行う。最後の dequeue() で取り出される値はどれか。

enqueue(1)
enqueue(2)
dequeue()
enqueue(3)
dequeue()
解説を表示 正解:エ
enqueue(1), enqueue(2) で {1,2}。最初の dequeue() で 1 が出て {2}。 enqueue(3) で {2,3} になるので、最後の dequeue() では先頭の 2 が出ます。