Week 4 (2025/5/2)¶
今週の目的
ファイルのデータをスタックやキューに格納する。
今週のキーワード
- スタック
- プッシュ
- ポップ
- キュー
- エンキュー
- デキュー
- ダックタイピング(ポリモーフィズム)
今回は連結リストを用いてスタックとキューを実装し、プッシュとポップ、エンキューとデキューを行うプログラムを作成する。スタックは、リスト(配列)や連結リストと同じ順序付きのデータを格納するデータ構造で、データの入口と出口が同じものである。つまり、 データの挿入および取り出しが先頭か末尾のどちらか一方だけで行われる。 スタックへのデータの追加をプッシュ、スタックからのデータの取り出しをポップという。最後に追加したデータから取り出されるため、 LIFO(Last-In First-Out) とも呼ばれる。
一方、キューは、リストや連結リストと同じ順序付きのデータを格納するデータ構造で、データの入口と出口が異なるものである。つまり、 データが先頭に挿入されるのであれば、末尾からデータが取り出され、データが末尾に挿入されるのであれば、先頭からデータが取り出される。 キューへのデータの追加をエンキュー、キューからのデータの取り出しをデキューという。最初に追加したデータから取り出されるため、FIFO(First-In First-Out)とも呼ばれる。
本演習では連結リストを用いて、スタック(Stackインスタンス)にプッシュし、スタックからポップするプログラムと、キュー(Queueインスタンス)にエンキューし、キューからデキューするプログラムを作成する。
今回作成するStack
クラスとQueue
クラスの仕様は、以下の通りである
Stackクラス
class Stack()
スタックのクラス
インスタンス変数
- top: 連結リストの先頭の節(
Node
インスタンス)
push(data)
スタックにデータをプッシュするメソッド
パラメータ
- data: スタックに挿入するデータ(
Stop
インスタンス)
pop()
スタックからデータをポップするメソッド
返り値
- スタックの先頭に格納されていたデータ(
Stop
インスタンス)。スタックが空であればNone
を返す。
display()
スタックの中身を表示するメソッド
Queueクラス
class Queue()
キューのクラス
インスタンス変数
- top: 連結リストの先頭の節(
Node
インスタンス) - rear: 連結リストの末尾の節(
Node
インスタンス)
enqueue(data)
キューにデータをエンキューするメソッド
パラメータ
- data: キューに挿入するデータ
dequeue()
キューからデータをデキューするメソッド
返り値
- キューの先頭に格納されていたデータ(
Stop
インスタンス)。キューが空であればNone
を返す。
display()
キューの中身を表示するメソッド
なお、前回作成したNode
クラスの定義をimportするために、def_node.py をダウンロードし、同一ディレクトリに保存して用いよ。
課題1:スタックにデータをプッシュする¶
以下のプログラムの穴あき部分を埋めて、スタックにデータをプッシュするメソッド(push(self, data)
)を完成させ、実行例の通りに動くことを確認せよ。 push
メソッドは、data
がStop
インスタンスであることを確認してから、スタック内の連結リストの先頭(top
)に節を挿入する。また、Stop
インスタンス以外がpush
された時は「Stop
インスタンス以外はPUSHできません。」と表示すること。
ヒント
第3週で取り組んだ「連結リストの先頭へのデータの挿入方法」を思い出そう。なお、あるオブジェクトがStop
インスタンスかどうか確認するには、以下のisinstance(object, class)
関数を用いるとよい。
isinstance関数
isinstance(object, class)
オブジェクトがあるクラスのインスタンスかどうか確認する関数
パラメータ
- object: 対象のオブジェクト
- class: 対象のクラス
返り値
- 対象のオブジェクトが対象のクラスのインスタンスであれば
True
、そうでなければFalse
を返す(ブール値)
使用例
APIの詳細は公式のページを参照すること。
======スタックの先頭======
======スタックの底======
Stopインスタンス以外はPUSHできません。
======スタックの先頭======
龍谷大学前(ID:ED01_2263)のバス停の緯度経度は(34.9631519,135.76834405)です。
京都産大前(ID:ED01_2244)のバス停の緯度経度は(35.07182049,135.75638731)です。
京大正門前(ID:ED01_1841)のバス停の緯度経度は(35.02548675,135.7786403)です。
同志社前(ID:ED01_1922)のバス停の緯度経度は(35.02913136,135.76314762)です。
立命館大学前(ID:ED01_1914)のバス停の緯度経度は(35.03497163,135.72602961)です。
======スタックの底======
課題2:スタックからデータをポップする¶
課題1のプログラムを修正し、スタックに積まれたデータをポップするメソッド(pop(self)
)を追加せよ。pop
メソッドはスタック内の連結リストの先頭(top
)の節を切り取り、その節に格納されているStop
インスタンスを返す(return
)こと。さらに、スタックが空の時は「スタックが空でPOPできません。」と表示してNone
を返す(return
)こと。
課題1の通りにStop
インスタンスをスタックに追加した後、pop
メソッドを用いて、スタックが空になるまでスタックから一つずつStop
インスタンスを取り出しそのStop
インスタンスを表示して、実行例の通りに動くことを確認せよ。
ヒント
第3週で取り組んだ「連結リストのデータの切り取り」を思い出そう。
龍谷大学前(ID:ED01_2263)のバス停の緯度経度は(34.9631519,135.76834405)です。
京都産大前(ID:ED01_2244)のバス停の緯度経度は(35.07182049,135.75638731)です。
京大正門前(ID:ED01_1841)のバス停の緯度経度は(35.02548675,135.7786403)です。
同志社前(ID:ED01_1922)のバス停の緯度経度は(35.02913136,135.76314762)です。
立命館大学前(ID:ED01_1914)のバス停の緯度経度は(35.03497163,135.72602961)です。
スタックが空でPOPできません。
課題3:キューを作る¶
課題1と課題2で実装したスタックのプログラムを参考に、キューにデータをエンキューするメソッドと、キューからデータをデキューするメソッドをもつ以下のQueue
クラスを実装せよ。
enqueue
メソッドは、スタックのpush
メソッドのようにdata
がStop
インスタンスであることを確認してから、キュー内の連結リストの末尾(rear
)に節を挿入すること。また、Stop
インスタンス以外がenqueue
された時は「Stopインスタンス以外はENQUEUEできません。」と表示すること。一方、dequeue
メソッドは、スタックのpop
メソッドと同様にキュー内の連結リストの先頭(top
)から節を切り取り、その節に格納されているStop
インスタンスを返す(return
)こと。さらに、キューが空の時は「キューが空でDEQUEUEできません。」と表示してNone
を返す(return
)すること。
このenqueue
メソッドを用いて、数字の「1」および「立命館大学前」「同志社前」「京大正門前」「京都産大前」「龍谷大学前」の各Stop
インスタンスを順にエンキューせよ。次にdisplay
メソッドを用いてキューの中身を表示し、実行例の通り、キューの末尾にデータが追加されていることを確認せよ。さらに、dequeue
メソッドを用いて、キューが空になるまでキューから一つずつStop
インスタンスを取り出してそのStop
インスタンスを表示し、実行例の通りに動くことを確認せよ。
ヒント
連結リストの末尾への挿入は、連結リストの末尾を指すリストヘッド(rear
)を用いよう。挿入後に忘れずにその末尾のリストヘッドの位置を更新すること。連結リストの先頭の切り取りは課題2を参考にするとよい。
Stopインスタンス以外はENQUEUEできません。
======キューの先頭======
立命館大学前(ID:ED01_1914)のバス停の緯度経度は(35.03497163,135.72602961)です。
同志社前(ID:ED01_1922)のバス停の緯度経度は(35.02913136,135.76314762)です。
京大正門前(ID:ED01_1841)のバス停の緯度経度は(35.02548675,135.7786403)です。
京都産大前(ID:ED01_2244)のバス停の緯度経度は(35.07182049,135.75638731)です。
龍谷大学前(ID:ED01_2263)のバス停の緯度経度は(34.9631519,135.76834405)です。
======キューの末尾======
立命館大学前(ID:ED01_1914)のバス停の緯度経度は(35.03497163,135.72602961)です。
同志社前(ID:ED01_1922)のバス停の緯度経度は(35.02913136,135.76314762)です。
京大正門前(ID:ED01_1841)のバス停の緯度経度は(35.02548675,135.7786403)です。
京都産大前(ID:ED01_2244)のバス停の緯度経度は(35.07182049,135.75638731)です。
龍谷大学前(ID:ED01_2263)のバス停の緯度経度は(34.9631519,135.76834405)です。
キューが空でDEQUEUEできません。
発展課題4:リストでスタックとキューを作る¶
リストクラスのappend
メソッドとpop
メソッドを用いて、push
メソッドとpop
メソッド、display
メソッドを備えたListStack
クラスと、enqueue
メソッドとdequeue
メソッド、display
メソッドを備えたListQueue
クラスを実装せよ。display
メソッドは内部のリストを表示するものとし、ListStack
クラスのdisplay
メソッドは「======スタックの先頭======」と「======スタックの底======」、ListQueue
クラスのdisplay
メソッドは「======キューの先頭======」と「======キューの末尾======」を表示すること。なお、スタックはデータを出入り口を先頭、キューはデータの入り口を末尾、出口を先頭とする。
今回作成するListStack
クラスとListQueue
クラスの仕様は、以下の通りである
ListStackクラス
class ListStack()
スタックのクラス
インスタンス変数
- list: データ格納用のリスト
push(data)
スタックにデータをプッシュするメソッド
パラメータ
- data: スタックに挿入するデータ(
Stop
インスタンス)
pop()
スタックからデータをポップするメソッド
返り値
- スタックの先頭に格納されていたデータ(
Stop
インスタンス)。スタックが空であればNone
を返す。
display()
スタックの中身を表示するメソッド
ListQueueクラス
class ListQueue()
キューのクラス
インスタンス変数
- list: データ格納用のリスト
enqueue(data)
キューにデータをエンキューするメソッド
パラメータ
- data: キューに挿入するデータ
dequeue()
キューからデータをデキューするメソッド
返り値
- キューの先頭に格納されていたデータ(
Stop
インスタンス)。キューが空であればNone
を返す。
display()
キューの中身を表示するメソッド
さらに、kyotocitybus_stop.dat
からバス停データを読み込み、読み込んだ順に全てのデータをスタックにプッシュし、その後ポップしたデータを全て表示せよ。同様に、kyotocitybus_stop.dat
からバス停データを読み込み、読み込んだ順に全てのデータをキューにエンキューし、その後デキューしたデータを全て表示せよ。また、実行例の通りに動くことを確認し、出力結果がスタックとキューで逆順になっていることに注意せよ。
京都駅八条口(ID:ED01_4102)のバス停の緯度経度は(34.98401063,135.75866056)です。
京都駅前(ID:ED01_4089)のバス停の緯度経度は(34.98719397,135.75802795)です。
京都会館美術館前(ID:ED01_2307)のバス停の緯度経度は(35.01363868,135.78107416)です。
(途中省略)
大宮総門口町(ID:ED01_1639)のバス停の緯度経度は(35.05831804,135.74403767)です。
神光院前(ID:ED01_1638)のバス停の緯度経度は(35.06134071,135.74395031)です。
西賀茂車庫前(ID:ED01_1637)のバス停の緯度経度は(35.06385669,135.74499864)です。
スタックが空でPOPできません。
西賀茂車庫前(ID:ED01_1637)のバス停の緯度経度は(35.06385669,135.74499864)です。
神光院前(ID:ED01_1638)のバス停の緯度経度は(35.06134071,135.74395031)です。
大宮総門口町(ID:ED01_1639)のバス停の緯度経度は(35.05831804,135.74403767)です。
(途中省略)
京都会館美術館前(ID:ED01_2307)のバス停の緯度経度は(35.01363868,135.78107416)です。
京都駅前(ID:ED01_4089)のバス停の緯度経度は(34.98719397,135.75802795)です。
京都駅八条口(ID:ED01_4102)のバス停の緯度経度は(34.98401063,135.75866056)です。
キューが空でDEQUEUEできません。
発展課題5:ポリモーフィズムを使う¶
課題1のスタック(Stack
クラス)と発展課題4のListStack
クラス、課題3のキュー(Queue
クラス)と発展課題4のListQueue
クラスを用いて、kyotocitybus_stop.dat
から読み込んだ全てのバス停データを、読み込んだ順に各スタックおよび各キューに格納せよ。その後、display
メソッドを用いて、格納したデータを表示し比較せよ。なお、ポリモーフィズムを用いて実装すること。
ヒント
ポリモーフィズムとは、同じメソッド名を用いることで、呼び出し方法を変えずにオブジェクトを変えるだけで振る舞いを変えることである。スタックの各インスタンスをリストに格納し、for
文で一つずつ異なる実装のスタックインスタンスを取り出して、ループ内でそれぞれのpush
メソッドを用いてスタックにデータを格納するとよい。キューも同様である。
======スタックの底======
西賀茂車庫前(ID:ED01_1637)のバス停の緯度経度は(35.06385669,135.74499864)です。
神光院前(ID:ED01_1638)のバス停の緯度経度は(35.06134071,135.74395031)です。
大宮総門口町(ID:ED01_1639)のバス停の緯度経度は(35.05831804,135.74403767)です。
(途中省略)
京都会館美術館前(ID:ED01_2307)のバス停の緯度経度は(35.01363868,135.78107416)です。
京都駅前(ID:ED01_4089)のバス停の緯度経度は(34.98719397,135.75802795)です。
京都駅八条口(ID:ED01_4102)のバス停の緯度経度は(34.98401063,135.75866056)です。
======スタックの先頭======
======スタックの先頭======
京都駅八条口(ID:ED01_4102)のバス停の緯度経度は(34.98401063,135.75866056)です。
京都駅前(ID:ED01_4089)のバス停の緯度経度は(34.98719397,135.75802795)です。
京都会館美術館前(ID:ED01_2307)のバス停の緯度経度は(35.01363868,135.78107416)です。
(途中省略)
大宮総門口町(ID:ED01_1639)のバス停の緯度経度は(35.05831804,135.74403767)です。
神光院前(ID:ED01_1638)のバス停の緯度経度は(35.06134071,135.74395031)です。
西賀茂車庫前(ID:ED01_1637)のバス停の緯度経度は(35.06385669,135.74499864)です。
======スタックの底======
======キューの先頭======
西賀茂車庫前(ID:ED01_1637)のバス停の緯度経度は(35.06385669,135.74499864)です。
神光院前(ID:ED01_1638)のバス停の緯度経度は(35.06134071,135.74395031)です。
大宮総門口町(ID:ED01_1639)のバス停の緯度経度は(35.05831804,135.74403767)です。
(途中省略)
京都会館美術館前(ID:ED01_2307)のバス停の緯度経度は(35.01363868,135.78107416)です。
京都駅前(ID:ED01_4089)のバス停の緯度経度は(34.98719397,135.75802795)です。
京都駅八条口(ID:ED01_4102)のバス停の緯度経度は(34.98401063,135.75866056)です。
======キューの末尾======
======キューの先頭======
西賀茂車庫前(ID:ED01_1637)のバス停の緯度経度は(35.06385669,135.74499864)です。
神光院前(ID:ED01_1638)のバス停の緯度経度は(35.06134071,135.74395031)です。
大宮総門口町(ID:ED01_1639)のバス停の緯度経度は(35.05831804,135.74403767)です。
(途中省略)
京都会館美術館前(ID:ED01_2307)のバス停の緯度経度は(35.01363868,135.78107416)です。
京都駅前(ID:ED01_4089)のバス停の緯度経度は(34.98719397,135.75802795)です。
京都駅八条口(ID:ED01_4102)のバス停の緯度経度は(34.98401063,135.75866056)です。
======キューの末尾======