概要とイメージとかんたんな用途だけ。コードは無し。
スタックとキューはデータ構造の一種
スタック
スタック(Stack) は、一段ずつ積み上げて保存する構造で、取り出すときは上から取り出す。
こんな入れ物があったとする。
|
V
| |
| |
+---+
A, B, C の順で入れたとすると、以下のようになる。
| C |
| B |
| A |
+---+
ここから取り出すときは 上から取り出す。なので「何を取り出すか」なんて言わない。「何回取り出すか」だけだ。
たとえば 2 回取り出したら、こうなる。
1回目に取り出したもの: C
2回目に取り出したもの: B
| |
| |
| A |
+---+
スタックの用途
たとえば履歴管理に使われる。
皆さんが今見ているブラウザの戻る・進む動作も、スタックで実現されている。
たとえば以下の行動をしたとして、
- 1: X(Twitter) のホーム画面を開く
- 2: タイムラインに流れていた、兎田ぺこらのツイートの詳細を開く
- 3: YouTube 動画リンクされてるので、そっちを開く
- 4: 関連動画でこんこよのライブが始まっていたので、そっちを開く
その後、一回だけ戻る操作をしたとする。これはスタックで表現すると、以下のようになる。
Watching Watching
[4] [3]
| | | 3 | | |
| | ---> | 2 | ---> | 2 |
| | | 1 | | 1 |
+---+ +---+ +---+
要は、
- 新しいページを開いたら、さっき見ていたページをスタックに入れる
- 戻るボタンを押したら、スタックから一つ取り出してそれを開く
という操作をしている。
キュー
キュー(Queue) は、入口から一個ずつ詰めて保存する構造で、出すときは出口から出す。
こんな入れ物、というか筒があったとする。
------
--->
------
A, B, C の順で入れたとすると、以下のようになる。
------
---> C B A
------
ここから取り出すときは 出口から取り出す。スタックと同様、「何を取り出すか」なんて言わない。「何回取り出すか」だけだ。
たとえば 2 回取り出したら、こうなる。
1回目に取り出したもの: A
2回目に取り出したもの: B
------
---> C
------
キューの用途
現実では 待ち列 としてよく使われる。実際は急患を優先したり、順番を抜かす悪い人がいたりするが、考え方自体は非常に身近であり、改めて説明されるまでもないだろう。
IT では、特定のプログラムが処理を受け取る受信箱として使うことが多い。特に複数のプログラムやサーバーが連携しているような複雑なシステムでは、「受信箱にリクエストが来たら処理しますわ」「受信箱は 10 秒ごとにチェックしますわ」の形を取ることが多い。これだと受信箱を見るだけでいいので管理がシンプルになる(※1)。この受信箱に使われるのがキューである。
※1 ただし誰がいつ何を入れて、といった取り決めはちゃんと考えないといけなくて、その辺は複雑になる。
このとき、私たちが普段使うメールやチャットのように読み飛ばしたりはしない。来たものから順に処理する。その方が単純だし、漏れもないし、わかりやすいから使い勝手が良い。もし、これで問題がおきたとしたら、キューに入れる量か、取り出して処理する側の能力がおかしいのでそっちを何とかすればいい。キューのせいじゃない。キューの部分(受信箱の部分)は至ってシンプルだ。
FIFO と LIFO は正直無視していい
実用上は困らないし、読み飛ばしても困ることは無いと思う。
一応、解説しておくと、キューのように先に入れたもの(First In)が先に出てくる(Last Out)構造を FIFO といい、スタックのように後に入れたもの(Last In)が先に出てくるものを LIFO という。
後ろの FO の部分(First Out、先に出る)が同じというネーミング。
あー、あとは操作名の話
スタックに入れることをプッシュ(Push)、スタックから取り出すことをポップ(Pop)という。
キューに入れることエンキュー(Enqueue)、キューから取り出すことをデキュー(Dequeue)という。