我一直在尝试用Python实现队列,而且我遇到了一个问题。
我正在尝试使用列表来实现Queue数据结构,但是我无法弄清楚如何进行enqueue
和dequeue
O(1)操作。
我在网上看到的每个例子似乎只是附加了enqueue
操作,并从dequeue
操作列表中删除了第一个元素。但这会使dequeue
操作O(n)(其中n是列表的大小)正确吗?
我错过了一些基本的东西吗?或者您是否必须使用LinkedLists有效地实现队列?
import unittest
class Queue():
def __init__(self):
self._queue = []
self.size = 0
self.maxSize = 10
def enqueue(self, item):
if self.size < self.maxSize:
self._queue.append(item)
def dequeue(self):
'''
Removes an item from the front of the list. Remove first element of
the array
'''
first = self._queue[0]
del self._queue[0]
return first
答案 0 :(得分:5)
作为Uri Goren精明地noted above,Python stdlib已经为您的幸运实现了一个高效的队列:collections.deque
。
通过自己手动滚动来避免重新发明轮子:
dequeue()
和enqueue()
方法的最坏情况时间复杂度降低到O(1),但collections.deque
类型已经这样做了。鉴于其基于C的传统,它也是线程安全的,并且可能更具空间和时间效率。enqueue()
方法会将最坏情况下的时间复杂度增加到 O(n)。因为从C中删除最后一项基于数组的数组,因此Python列表是一个常量时间操作,根据Python列表实现dequeue()
方法保留了与O(1)相同的最坏情况时间复杂度。但谁在乎? enqueue()
仍然非常缓慢。引用official deque
documentation:
虽然
list
个对象支持类似的操作,但它们针对快速固定长度操作进行了优化,并导致pop(0)
和insert(0, v)
操作的O(n)内存移动成本,从而改变了这两种操作的大小和基础数据表示的位置。
更关键的是,deque
还通过初始化时传递的maxlen
参数提供对最大长度的开箱即用支持,从而无需手动操作尝试限制队列大小(由于条件中隐含的竞争条件,这不可避免地会破坏线程安全性。)
相反,请按照以下标准Queue
类型实施您的collections.deque
课程:
from collections import deque
class Queue():
'''
Thread-safe, memory-efficient, maximally-sized queue supporting queueing and
dequeueing in worst-case O(1) time.
'''
def __init__(self, max_size = 10):
'''
Initialize this queue to the empty queue.
Parameters
----------
max_size : int
Maximum number of items contained in this queue. Defaults to 10.
'''
self._queue = deque(maxlen=max_size)
def enqueue(self, item):
'''
Queues the passed item (i.e., pushes this item onto the tail of this
queue).
If this queue is already full, the item at the head of this queue
is silently removed from this queue *before* the passed item is
queued.
'''
self._queue.append(item)
def dequeue(self):
'''
Dequeues (i.e., removes) the item at the head of this queue *and*
returns this item.
Raises
----------
IndexError
If this queue is empty.
'''
return self._queue.pop()
证据是地狱般的布丁:
>>> queue = Queue()
>>> queue.enqueue('Maiden in Black')
>>> queue.enqueue('Maneater')
>>> queue.enqueue('Maiden Astraea')
>>> queue.enqueue('Flamelurker')
>>> print(queue.dequeue())
Flamelurker
>>> print(queue.dequeue())
Maiden Astraea
>>> print(queue.dequeue())
Maneater
>>> print(queue.dequeue())
Maiden in Black
实际上,也不这样做。
最好只使用原始deque
对象,而不是尝试在Queue
包装器中手动封装该对象。上面定义的Queue
类只有 作为deque
API的通用实用程序的简单演示。
deque
课程提供significantly more features,包括:
...迭代,腌制,
len(d)
,reversed(d)
,copy.copy(d)
,copy.deepcopy(d)
,使用in运算符进行成员资格测试,以及d[-1]
等下标引用}。
只需在需要单端或双端队列的任何地方使用deque
。就是这样。
答案 1 :(得分:2)
您可以在queue class
class Node(object):
def __init__(self, item = None):
self.item = item
self.next = None
self.previous = None
class Queue(object):
def __init__(self):
self.length = 0
self.head = None
self.tail = None
def enqueue(self, x):
newNode = Node(x)
if self.head == None:
self.head = self.tail = newNode
else:
self.tail.next = newNode
newNode.previous = self.tail
self.tail = newNode
self.length += 1
def dequeue (self):
item = self.head.item
self.head = self.head.next
self.length -= 1
if self.length == 0:
self.last = None
return item
答案 2 :(得分:0)
使用Python中的列表执行队列,并按照内置队列数据结构处理入队和入队:
class queue:
def __init__(self, max_size, size=0, front=0, rear=0):
self.queue = [[] for i in range(5)] #creates a list [0,0,0,0,0]
self.max_size = max_size
self.size = size
self.front = front
self.rear = rear
def enqueue(self, data):
if not self.isFull():
self.queue[self.rear] = data
self.rear = int((self.rear + 1) % self.max_size)
self.size += 1
else:
print('Queue is full')
def dequeue(self):
if not self.isEmpty():
print(self.queue[self.front], 'is removed')
self.front = int((self.front + 1) % self.max_size)
self.size -= 1
else:
print('Queue is empty')
def isEmpty(self):
return self.size == 0
def isFull(self):
return self.size == self.max_size
def show(self):
print ('Queue contents are:')
for i in range(self.size):
print (self.queue[int((i+self.front)% self.max_size)])
# driver program
q = queue(5)
q.enqueue(1)
q.enqueue(2)
q.enqueue(3)
q.enqueue(4)
q.enqueue(5)
q.dequeue()
q.show()
答案 3 :(得分:0)
这是我使用数组的Queue实现,enqueue
和dequeue
都是O(1)操作。该实现基于CLRS。
class Queue:
def __init__(self, length):
"""a queue of at most n elements using an array of n+1 element size"""
self.length = length
self.queue = [None]*(length+1)
self.head = 0
self.tail = 0
def enqueue(self, x):
if self.is_full():
return 'Overflow'
self.queue[self.tail] = x
if self.tail == self.length:
self.tail = 0
else:
self.tail = self.tail + 1
def dequeue(self):
if self.is_empty():
return 'Underflow'
x = self.queue[self.head]
if self.head == self.length:
self.head = 0
else:
self.head = self.head + 1
return x
def is_empty(self):
if self.head == self.tail:
return True
return False
def is_full(self):
if self.head == self.tail+1 or (self.head == 0 and self.tail == self.length):
return True
return False
答案 4 :(得分:0)
# Linear Queue Implementation using Array
class Queue:
"""Class with List as Array """
def __init__(self):
self.v_list=[]
"""Storing the in FIFO order"""
def enqueue(self,value):
self.v_list.append(value)
"""Removing Element from Queue in FIFO order"""
def dequeue(self):
if len(self.v_list)==0:
print('Queue is Empty')
return
self.v_list.pop(0)
def print_queue(self):
print(self.v_list)
def size_of_queue(self):
return print(len(self.v_list))
object_queue=Queue()
object_queue.enqueue(0)
object_queue.enqueue(1)
object_queue.enqueue(2)
object_queue.enqueue(3)
object_queue.enqueue(4)
object_queue.enqueue(5)
object_queue.print_queue()
object_queue.dequeue()
object_queue.print_queue()
object_queue.dequeue()
object_queue.print_queue()
object_queue.size_of_queue()
#Circular Queue Implementation using Array
class CircularQueue():
def __init__(self):
"""Class to hold the Postions for insert and delete"""
self.start_pointer=0
self.end_pointer=-1
self.queue_list=[]
"""Storing the element in Circular order, with circular we can remove empty Block"""
def enqueue(self,value):
if len(self.queue_list)>10:
print("Circular Queue is Full")
return
"""Checking for Empty Block in Array and storing data and reseting the stat end point to process the element"""
if 'None' in self.queue_list:
self.queue_list[self.end_pointer]=value
self.end_pointer+=1
else:
self.queue_list.append(value)
self.end_pointer+=1
"""Removing element In FIFO order and reseting start ending point"""
def dequeue(self):
#self.queue_list.replace(self.queue_list[self.start_pointer],None)
self.queue_list = [str(sub).replace(str(self.queue_list[self.start_pointer]),'None') for sub in self.queue_list]
self.start_pointer+=1
for i ,j in enumerate(self.queue_list):
if j=='None':
self.end_pointer=i
break
"""For Printing Queue"""
def print_cq(self):
if len(self.queue_list)>10:
print("Circular Queue is Full")
return
print(self.queue_list,self.start_pointer,self.end_pointer)
cir_object=CircularQueue()
cir_object.enqueue(0)
cir_object.enqueue(1)
cir_object.enqueue(2)
cir_object.enqueue(3)
cir_object.enqueue(4)
cir_object.enqueue(5)
cir_object.enqueue(6)
cir_object.enqueue(7)
cir_object.enqueue(8)
cir_object.enqueue(9)
#cir_object.print_cq()
cir_object.dequeue()
cir_object.dequeue()
cir_object.print_cq()
cir_object.enqueue(15)
cir_object.enqueue(20)
cir_object.print_cq()
答案 5 :(得分:0)
class Queue:
def __init__(self,no):
self.no = no
self.SQueue = []
self.front = -1
self.rear = -1
def insert(self):
if self.rear == self.no -1:
print("Queue is Full.....")
else:
if self.front == -1:
self.front = 0
self.rear = 0
else :
self.rear += 1
n = int(input("enter an element :: "))
self.SQueue.insert(self.rear, n)
def delete(self):
if self.front == -1 and self.front == no - 1:
print("Queue is Empty.....")
else:
self.SQueue.pop(self.front)
self.front +=1
def disp(self):
if self.front == -1 and self.front == no - 1:
print("Queue is Empty.....")
else:
print("REAR \tELEMENT")
for i in range(len(self.SQueue)):
print(i," \t",self.SQueue[i])
no = int(input("ENTER Size :: "))
q = Queue(no)
while(True):
print(" 1: INSERT ")
print(" 2: DELETE ")
print(" 3: PRINT ")
print(" 4: EXIT ")
option = int(input("enter your choice :: "))
if option == 1:
q.insert()
elif option == 2:
q.delete()
elif option == 3:
q.disp()
elif option == 4:
print("you are exit!!!!!")
break
else:
print("Incorrect option")
答案 6 :(得分:-2)
在出队方法中没有任何循环。您只需要执行列表操作。因此,出队的时间复杂度也是O(n)(线性)。
class Queue:
def __init__(self):
self.items=[]
def enqueue(self,item):
self.items.append(item)
def dequeue(self):
return self.items.pop(0)
def isEmpty(self):
return self.items==[]
def __len__(self):
return len(self.items)