キューを使うとき、「list でいいのか? deque のほうが速いのか? queue.Queue とは何が違うのか?」と迷ったことがあるかもしれません。それぞれのデータ構造には特徴があり、適材適所で使い分けることで処理の効率が大きく変わります!
1. それぞれの特徴
データ構造 | 主な用途 | 特徴 |
---|---|---|
list |
一般的な配列操作 | 先頭の要素の追加・削除が遅い(O(n)) |
collections.deque |
高速な両端キュー | 両端の追加・削除が高速(O(1)) |
queue.Queue |
マルチスレッドのタスク管理 | スレッドセーフなFIFOキュー |
2. list
(通常のリスト)
✅ 長所
- Python の組み込み型で、使いやすい
- 末尾の
append()
やpop()
は O(1) で高速
❌ 短所
- 先頭の要素の
insert(0, x)
やpop(0)
は O(n)(遅い)
lst = [1, 2, 3]
lst.append(4) # 末尾に追加(高速)
print(lst.pop()) # 4(末尾から削除、O(1))
lst.insert(0, 0) # 先頭に追加(O(n))
print(lst.pop(0)) # 0(先頭から削除、O(n))
🔹 先頭の追加・削除が多い場合は
deque
を使うべき!
3. collections.deque
(両端キュー)
✅ 長所
- 両端の
append()
/appendleft()
/pop()
/popleft()
が O(1) で高速 -
list
のような可変長のデータ構造 - スレッドセーフ(ロックは手動で必要)
❌ 短所
-
list
のようなランダムアクセス(deque[i]
)は遅い(O(n))
from collections import deque
dq = deque([1, 2, 3])
dq.append(4) # 右端に追加
dq.appendleft(0) # 左端に追加
print(dq.pop()) # 4(右端から削除)
print(dq.popleft()) # 0(左端から削除)
🔹 両端の操作が頻繁に発生する場合は
deque
が最適!
4. queue.Queue
(スレッドセーフなキュー)
✅ 長所
-
put()
/get()
がスレッドセーフ(ロック管理不要) - マルチスレッドのタスクキューに適している
❌ 短所
-
deque
よりもやや遅い(スレッドロックのオーバーヘッド) - 直接インデックスアクセス不可(FIFO 方式)
import queue
q = queue.Queue()
q.put(1) # キューに追加
q.put(2)
q.put(3)
print(q.get()) # 1(FIFOで取得)
print(q.get()) # 2
🔹 マルチスレッド環境で安全にキューを使いたい場合に最適!
5.まとめ
データ構造 | 先頭追加 | 末尾追加 | 先頭削除 | 末尾削除 | スレッドセーフ | 用途 |
---|---|---|---|---|---|---|
list |
O(n) | O(1) | O(n) | O(1) | ❌ | 一般的なリスト操作 |
deque |
O(1) | O(1) | O(1) | O(1) | △(ロックが必要) | キュー・スタック |
queue |
O(1) | O(1) | O(1) | O(1) | ✅ | マルチスレッドのタスク管理 |
-
list
→ 配列のように扱いたいとき(検索や末尾操作が中心) -
deque
→ 先頭や末尾の要素の追加・削除が多いとき(スタック・キュー用途) -
queue
→ マルチスレッドで安全にキューを使いたいとき(タスク管理)
参考
- https://docs.python.org/3/tutorial/datastructures.html
- https://www.geeksforgeeks.org/deque-in-python/
- https://www.geeksforgeeks.org/queue-in-python/
弊社の求人,ご興味ある方是非応募してください。