Pythonでスタックを実装する3つの方法を具体例つきで解説
スタック(Stack)は、LIFO(Last In First Out:後入れ先出し)という仕組みで動作する線形データ構造です。最初にスタックへ格納された要素は、最後に取り出されるという特徴を持ちます。
身近な例で理解するスタック
スタックの仕組みは、「積み重ねた皿」をイメージすると分かりやすくなります。
皿は1枚ずつ上に重ねていきます。最初に置いた皿は山の一番下にあり、最後に置いた皿が一番上にきます。皿が必要になったとき、私たちは必ず一番上の皿、つまり最後に置かれた皿から取ります。逆に、最初に置かれた皿が一番下に残り、最後に取り出されることになります。これこそが「後入れ先出し(LIFO)」の仕組みです。
Pythonにおけるスタックの実装方法
Pythonでは、リストや標準ライブラリの組み込みモジュールなどを利用して、複数の方法でスタックを実装できます。ここでは代表的な3つの方法を紹介します。
方法1:リスト(list)を使った実装
Pythonのリストを使えば手軽にスタックを実装できます。ただし、リストによる実装はパフォーマンス面で効率が良くないため、大規模な処理には推奨されません。
主な操作
append() … スタックの末尾に要素を追加します。
pop() … スタックの末尾(一番上)の要素を取り除き、その値を返します。要素はLIFOの順序で取り出されます。
コード例
stack = []
stack.append(1)
stack.append(2)
stack.append(3)
print("初期のスタック:", stack)
print("スタックから取り出した要素")
print(stack.pop())
print(stack.pop())
print("要素を取り出した後のスタック:", stack)実行結果
初期のスタック: [1, 2, 3] スタックから取り出した要素 3 2 要素を取り出した後のスタック: [1]
なお、空のスタックに対してさらにpop()を呼び出すことはできません。その場合、例外が発生します。
stack.pop() IndexError: pop from empty list
方法2:queue.LifoQueueを使った実装
これはPythonの組み込みモジュールを使った実装方法です。queueモジュールからLifoQueueをインポートして使用します。スタックの最大サイズを指定して初期化でき、サイズに0を指定した場合は無制限のスタックとして扱われます。
主な操作
maxsize … スタックに格納できる要素数の上限。
get() … スタックの末尾(一番上)の要素を取り除いて返します。スタックが空の場合は、要素が追加されるまで待機します。
get_nowait() … スタックの末尾の要素を取り除いて返します。スタックが空の場合は例外を発生させます。
put(item) … スタックの末尾に要素を追加します。スタックが満杯の場合は、空きスロットができるまで待機します。
put_nowait(item) … スタックの末尾に要素を追加します。スタックが満杯の場合は例外を発生させます。
full() … スタックが満杯ならTrue、そうでなければFalseを返します。
empty() … スタックが空ならTrue、そうでなければFalseを返します。
qsize() … スタック内の現在の要素数を返します。
コード例
from queue import LifoQueue
s = LifoQueue(maxsize=3)
s.put(1)
s.put(2)
s.put(3)
print("スタックは満杯か:", s.full())
print("スタックから取り出した要素")
print(s.get())
print(s.get())
print("スタック内の要素数:", s.qsize())
print("スタックは空か:", s.empty())実行結果
スタックは満杯か: True スタックから取り出した要素 3 2 スタック内の要素数: 1 スタックは空か: False
方法3:collections.dequeを使った実装
もうひとつの方法が、collectionsモジュールのdeque(デック)を使う実装です。dequeは両端キューとして設計されており、スタック用途にも高速に対応できます。
主な操作
append() … スタックの末尾に要素を追加します。
pop() … スタックの末尾の要素を取り除いて返します。計算量はO(1)と非常に高速です。
コード例
from collections import deque
stack = deque()
stack.append(1)
stack.append(2)
stack.append(3)
print("初期のスタック:", stack)
print("スタックから取り出した要素")
print(stack.pop())
print(stack.pop())
print("要素を取り出した後のスタック:", stack)実行結果
初期のスタック: deque([1, 2, 3]) スタックから取り出した要素 3 2 要素を取り出した後のスタック: deque([1])
なお、空のdequeに対してpop()を呼び出すと、IndexErrorの例外が発生する点に注意してください。
-
【初心者向け】JavaScriptのfinallyステートメントをサンプルコード付きでわかりやすく解説
finallyステートメントは、エラーが発生したかどうかにかかわらず、tryブロックとcatchブロックの処理が完了した後に必ず実行されるブロックです。ファイルのクローズやデータベース接続の切断など、処理の成功・失敗に関係なく必ず実行したい後処理(クリーンアップ処理)を記述する際に非常に便利です。finallyの基本構文try { // エラーが発生する可能性のある処理 } catch (err) { // エラー発生時に実行される処理 } finally { // エラーの有無にかかわらず必ず実行される処理 }サンプルコード以下は、JavaScriptにおけるfinallyステー
-
C言語の文字列ライブラリ関数を具体例つきでわかりやすく解説
C言語の文字列ライブラリ関数とは C言語には、文字列を扱うための定義済み関数が標準ライブラリ「string.h」に多数用意されています。これらの関数を活用することで、文字列の長さ取得・コピー・連結・比較・検索といった処理を簡単かつ効率的に実装できます。 本記事で紹介する主な文字列関数は以下の通りです。 strlen() strcmp() strcpy() strncmp() strncpy() strrev() strcat() strstr() strncat() strlen()関数 ― 文字列の長さを取得する strlen() は、文字列に含まれる文字数(長さ)を返す関数です。