Algorithm & Data Structure - Queue(1)
Queue
Qはスタックと同様に,資料構造に不可欠な代表的な資料構造であり,線形構造の資料構造である.しかし、スタックとは逆に、FIFOの先入先出の特徴を有する.先入先出という意味はコンビニでアルバイトをしていればわかりますが、先入先出という意味は先出という意味で、アトラクションを考えるのは簡単です.アトラクション列(単線や予約は含まれていません...)先に来た人が先にアトラクションに乗って出てくる仕組みは、FIFOといってもいいでしょう.
キューの基本演算
キューはデフォルトでenqueue/dequeueを実行し、enqueueはスタックの最後にデータ要素を追加し、dequeueはスタックの一番前に削除してデータ要素を返します.
Q.enqueue(A) # A
Q.enqueue(B) # A -> B
r1 = Q.dequeue() # return A / B
Q.enqueue(C) # B -> C
上のコードのようにデータ入出力が可能です.キューの実装
キュー抽象データ構造を実装する方法は、次の2つです.
あります.まずスタックのように、キューの演算を定義して実現します.
キュー内の演算
演算がある.
アレイ別キュー
class ArrayQueue:
def __init__(self):
self.data = []
def size(self):
return len(self.data)
def isEmpty(self):
return self.size() == 0
def enqueue(self, item):
self.data.append(item)
def dequeue(self):
return self.data.pop(0)
def peek(self):
return self.data[0]
このように、popを使用してdequeue時に0番インデックスの値を削除し続けるため、実装は簡単です.配列によって実現されるキューの演算の複雑さは、次のとおりです.
計算複雑度size()O(1)isEmpty()O(1)enqueue()O(1)Dequeue()O(n)peek()O(1)
双方向接続リストを使用したキューの実装
class Node:
def __init__(self, item):
self.data = item
self.prev = None
self.next = None
class DoublyLinkedList:
def __init__(self):
self.head = Node(None)
self.tail = Node(None)
self.head.prev = None
self.tail.next = None
self.head.next = self.tail
self.tail.prev = self.head
self.nodeCount = 0
def getLength(self):
return self.nodeCount
def getAt(self, pos):
if pos < 1 or pos > self.nodeCount:
return None
if pos > self.nodeCount // 2:
i = self.nodeCount + 1
curr = self.tail
while i > pos:
curr = curr.prev
i -= 1
else:
i = 0
curr = self.head
while i < pos:
curr = curr.next
i += 1
return curr
def insertAfter(self, prev, newNode):
next = prev.next
next.prev = newNode
prev.next = newNode
newNode.next = next
newNode.prev = prev
self.nodeCount += 1
def insertAt(self, pos, newNode):
if pos < 1 or pos > self.nodeCount+1:
return False
prev = self.getAt(pos-1)
return self.insertAfter(prev, newNode)
def popAfter(self, prev):
curr = prev.next
next = curr.next
prev.next = next
next.prev = prev
self.nodeCount -= 1
return curr.data
def popAt(self, pos):
if pos < 1 or pos > self.nodeCount:
raise IndexError()
prev = self.getAt(pos-1)
return popAfter(prev)
class LinkedListQueue:
def __init__(self):
self.data = DoublyLinkedList()
def size(self):
return self.data.nodeCount
def isEmpty(self):
return self.size() == 0
def enqueue(self, item):
node = Node(item)
self.data.insertAt(self.size()+1, node)
def dequeue(self):
return self.data.popAt(1)
def peek(self):
return self.getAt(1).data
として表すことができる簡単な双方向接続リストの観点から復習したが、詳細については下一篇を参照してください.接続リストを用いてキューを実現する演算の複雑さが同じである場合には,キュー部分をO(1)に改良することができ,popat(1)は常に固定されているので,キューを実現するためには,接続リストのpopat部分でpopAfterを用いずにprevを直接head訪問質問とすればよい.
from pythonds.basic.queue import Queue
同様に、Pythonは基本的にキューを提供しているので、直接導入して使用することができます.
整理する
今回はQしか知りませんでしたが、次はQを利用したリングQについてお話しします.可能であれば、できるだけ簡単なアルゴリズムの問題を解いてみます.
Reference
この問題について(Algorithm & Data Structure - Queue(1)), 我々は、より多くの情報をここで見つけました https://velog.io/@eslerkang/TIL-Algorithm-Data-StructureQueue-1テキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol