キュークラス(enqueue と dequeue)
前回は、インスタンスの中にリストを 1 本持たせました。今回は、そのリストに触るメソッドの側を決めます。
中身が同じなのに、出てくる答えが違う
1, 2, 3 をこの順に入れた入れ物が 2 つあります。片方から取り出すと 3、もう片方から取り出すと 1 が出ます。中に入っているリストは、どちらも [1, 2, 3] でまったく同じです。
| 種類 | 入れる場所 | 取り出す場所 |
|---|---|---|
| スタック | 末尾 | 末尾 |
| キュー | 末尾 | 先頭 |
違うのはメソッドの中身だけです。データ構造の正体は、持っているデータではなく、そのデータに許した操作のほうにあります。列に並ぶ人の流れ、印刷の順番待ち、幅優先探索の訪問順は、どれも先に入ったものが先に出る FIFO です。
メソッドは、状態をどう変えるかを名前で約束する
Python
class Lamp:
def __init__(self):
self.on = False
def toggle(self):
self.on = not self.on
def turn_off(self):
self.on = Falsetoggle は反転、turn_off は必ず消灯です。使う側は self.on を直接書き換えず、どちらのメソッドを呼ぶかだけを決めます。同じ on という 1 つの属性でも、用意するメソッドを変えれば、まったく違う部品になります。
メソッド越しにする利点は、呼ぶ側が中の形を知らずに済むことです。あとで on を明るさの数値に作り替えても、turn_off を呼んでいる側は 1 行も変わりません。差し替えられる余地は、外に見せる操作を絞ったぶんだけ残ります。
先頭から抜くと、後ろが全部ずれる
リストの先頭を取り除く道具は、言語ごとに用意されています。
Python
items = [1, 2, 3]
first = items.pop(0) # first は 1、items は [2, 3]JavaScript
const items = [1, 2, 3];
const first = items.shift(); // first は 1、items は [2, 3]どちらも、抜いたあとに残り全部を 1 つずつ前へ詰め直します。要素が n 個あれば n 回ずらします。末尾から抜くときは最後の 1 個を外すだけなので、詰め直しは起きません。同じ配列を使っていても、どちらの端を触るかで手間が変わる、というのがここでの発見です。
やってみよう
ひな形の TODO を完成させてください。enqueue と、空を確認する dequeue の本体を自分で書きます。入力を受け取る枠と説明つきの準備部分はそのまま使えます。
演習で使う書き方
本文の Lamp と同じくメソッドで状態を変えます。キューでは入れた順を保ちます。[8, 5] に pop(0) を使うと 8 が返り、[5] が残ります。入力をメソッドへ振り分ける部分と配列の初期化を用意しました。追加と、空確認を含む取り出しを自分で書きます。
要件
- enqueue と、空を確認する dequeue の本体を自分で実装する
- 関数名と引数、入力と戻り値の形を保つ。説明つきの準備部分を使い、TODO の仮の処理を置き換える