スタックとキューの理論的基礎
1. スタックとキューの違い
(1) Python のリストは連結リストの形式で実装されるため、Python のリストを作成する際にデータ構造やリストの長さを指定する必要がなく、それに応じて配列も作成時に宣言する必要があります。
. データ型、配列の長さも指定する必要があります
(2) メモリアドレス:
リスト: 不連続
配列: 連続
(3) データ型
リスト: 内部の要素は任意のデータ型にすることができます
配列: 同じ型
配列内のデータ型はすべて同じであるため、配列内のすべての項目は同じデータ型を持ち、演算は各要素に対して同じように動作します。したがって、配列は、多数の同種のデータ型を扱う場合に非常に役立ちます。Python は各要素のデータ型の詳細を個別に記憶する必要がないため、配列はリストよりも高速で、使用するメモリも少なくなります。
- スタックとキューは 2 つの基本的なデータ構造であり、どちらもコンテナ タイプです。2 つの違いは次のとおりです。
スタック: 後入れ先出し
キュー: 先入れ先出し
注: スタックとキューは、特定の位置にある要素をクエリして操作することはできません。しかし、彼らの配置はきちんとしている。
2. Pythonでのスタックの実装
スタックの場合、Python の組み込みリスト実装を使用できます。リストは線形配列であり、最後に要素を挿入および削除するのにかかる時間は O(1) であり、スタックの要件と非常に一致しています。もちろん、リストを使用することもできます。スタックの実装コード (Python の組み込みリストを使用) は実装が簡単で、次のとおりです。
class Stack(object):
def __init__(self):
self.stack = []
def push(self,value): #进栈
self.stack.append(value)
def pop(self): #出栈
if self.stack:
self.stack.pop()
else:
raise LookupError('stack is empty') #无效数据查询
def is_empty(self): ##判断栈是否为空
return bool(self.stack)
def top(self): #取出栈中最新的元素
return self.stack[-1]
3. キューの実装
キューのデータ構造を実装するために次のリンク リストを定義します。
左側がキューの先頭を指し、右側がキューの末尾を指すようにヘッド ノードを定義します。これにより、要素の挿入と要素の取り出しが両方とも O(1) 操作になることが保証されます。この種のリンク リストを使用してキューを実装すると非常に便利です。
class Head(object):
def __init__(self):
self.left = None
self.right = None
def Node(object):
def __init__(self,value):
self.value = value
self.next = None
class queue(object):
def __init__(self):
#初始化节点
self.head = Head()
def enqueue(self,value):
#插入一个元素
newnode = Node(value)
p = self.head
if p.right:
#如果head节点的右边不为None,
#说明队列中有其他元素
temp = p.right
temp.next = newnode
p.right = newnode
else:
#此时说明队列为空
p.right = newnode
p.left = newnode
def dequeue(self):
#取出一个元素
p = self.head
if p.left and (p.left == p.right):
#说明队中只有一个元素
temp = p.left
p.left = p.right = None
return temp.value
elif p.left and (p.left != p.right):
#说明队中不只一个元素
temp = p.left
p.left = temp.next
return temp.value
else:
#说明队列为空
raise LookupError('queue is empty!')
def is_empty(self):
if self.head.left:
return False
else:
return True
def top(self):
#查询队列中最先入队的元素
if self.head.left:
return self.head.left.value
else:
raise LookupError('queue is empty!')
4.Python の組み込みヒープ、スタック、キュー
まとめ
具体的な用途
heapq ヒープキュー
heapq は組み込みのヒープ構造であり、親ノードの値が常に子ノードよりも大きい完全なバイナリ ツリーの特別な形式です。そのプロパティに従って、Python は heap[k] <= を満たすものを使用できます。 heap[2 * k + 1] < = heap[2 * k + 2] リストを取得します。Heapq は最小ヒープです。最大ヒープを達成したい場合は、いくつかのトリックを使用できます。たとえば、heappush のときにデータ * -1 を入力し、heappop のときにポップされた要素に -1 を乗算します。
import heapq
heap = []
heapq.heappush(heap, 3)
heapq.heappush(heap, 2)
heapq.heappush(heap, 1)
print(heap) # 输出为 [1, 3, 2]
# 要想有序输出 堆的元素
heapq.heappop(heap) # 输出1
heapq.heappop(heap) # 输出2
heapq.heappop(heap) # 输出3
# 要想输出前n个最大值,前n个最小值,可以使用
heapq.nlargest(n, heap)
heapq.nsmallest(n, heap)
DEQUE 両端キュー
from collections import deque は、スタック関数またはキュー関数を実装できます。両端のキューはキューの先頭と末尾で編集できるため、Python でスタック関数を実装したい場合、最良の選択は deque です。通常の配列構造を使用します。
通常のキュー操作では、キューの最後に要素を挿入し、次に要素を先頭からポップします。
dq = queue()
dq.append(3) # deque([3])
dq.append(4) # deque([3, 4])
dq.popleft() # 弹出 3,并且dq为 deque([4])
如果设置为一个栈的话,FILO,那么就是如下的代码
dq = queue()
dq.append(3) # deque([3])
dq.append(4) # deque([3, 4])
dq.pop() # 弹出 4,并且dq为 deque([3])
列
Queue キューはスレッドセーフなパッケージです。このパッケージには、スタック LifoQueue などの多くの構造があります。並行環境で使用する場合は、この構造を使用するのが最善です。スタックが空の場合、最上位のスタックの要素がポップされると、スタックが空でなくなるまでブロックが発生します。
リフォキュー
LifoQueue はプッシュ操作と終了操作を備えたスタック構造で、メソッドはそれぞれ put() と get() であり、LifoQueue() が空の場合は get() がブロックされます。
from queue import LifoQueue
s = LifoQueue()
s.put(3)
s.put(4)
print(s.get()) # 打印4
print(s.get()) # 打印3
print(s.get()) # 一直等待直到s中存在元素,然后就打印退出
列
Queue は、エンキュー操作とデキュー操作を行うキューです。メソッドはそれぞれ put() と get() で、キューが空の場合、get() はブロックされます。さらに、キューの長さも設定できます。キューの長さが設定されていない場合、またはキューの長さを 0 以下の数値に設定した場合、キューの長さは無限になります。キューの最大長は .maxsize 属性を通じて取得できます。
from queue import Queue
q = Queue()
q.put(3)
q.put(4)
print(q.get()) # 打印3
print(q.get()) # 打印4
print(q.get()) # 一直等待直到q中存在元素,然后就打印退出
print(q.get_nowait()) # 如果队列q为空,那么不会等待,而是输出 Empty 的异常
優先キュー
PriorityQueue は優先キューです。キューの要素はソートされているため、ソートされたシーケンスに優先キューを使用すると、最大または最小の要素を効率的に取得できます。
スケジューリングの問題のシナリオでは、プライオリティ キューがよく使用されます。主に、最大値または最小値を取得する操作とキューに入れる操作が含まれます。プライオリティ キューは、内部で heapq をカプセル化します。違いは、プライオリティ キューがスレッドセーフであることと、プライオリティ キューがスレッドセーフであることです
。環境では、PriorityQueue の使用を選択する必要があります。
from queue import PriorityQueue
pq = PriorityQueue()
pq.put((2, 'name'))
pq.put((1, 'age'))
pq.put((3, 'job'))
while not pq.empty():
print(pq.get())
"""
输出内容如下
(1, "age")
(2, "name")
(3, "job")
"""
マルチプロセッシング.キュー
キューのマルチプロセス バージョン multiprocessing.Quque。マルチプロセス環境でキューを使用する場合は、 multiprocessing.Queue を選択する必要があります。
そのエンキュー操作とデキュー操作はそれぞれ put() と get() です。
参考文章:
[1] https://blog.csdn.net/weixin_43026262/article/details/104291381
[2] https://www.jianshu.com/p/9b94651534c3
[3] https://zhuanlan.zhihu. com/p/110424854