我需要一些帮助来编写一个python程序,它将实现循环队列数据结构(支持数组)。我已经完成了一些方法但是在添加和删除队列中的东西以及检查其中的值时我有点难过。我相信这是先进先出的结构。这是我到目前为止身体所拥有的东西
class Queue:
''' Constructor '''
def __init__(self, limit):
self.limit = limit
self.data = [None] * limit
self.queue = []
self.head = -1
self.tail = -1
self.count = 0
def dequeue(self):
if self.count == 0:
raise RuntimeError
else:
self.head = 0
x = self.queue.pop(0)
if self.head == self.tail:
self.head = -1
self.tail = -1
else:
self.tail -= 1
self.count -= 1
#self.head += 1
return x
def enqueue(self, item):
if self.count == self.limit:
raise RuntimeError
else:
self.count += 1
self.queue.append(item)
self.tail += 1
def __str__(self):
return " ".join([str(v) for v in self.queue])
def resize(self, new_limit):
new_q = [None]*self.limit
old_q = self.queue
for i in range(len(old_q)):
new_q[i] = old_q[i]
self.limit = new_limit
self.queue = new_q
def empty(self):
return 0 == self.count
def iter(self):
listt = []
for v in self.queue:
listt.append(v)
return listt
到目前为止我写的内容对我来说最有意义但是如果我用下面的代码块测试它,我会收到一个错误,说10!= 4.这段代码将失败第9行测试,tc.assertEqual(q.data.count(None), 4)
我不确定为什么我的代码在此时产生值10。什么允许这个类通过给定的测试?
from unittest import TestCase
tc = TestCase()
q = Queue(10)
for i in range(6):
q.enqueue(i)
tc.assertEqual(q.data.count(None), 4)
for i in range(5):
q.dequeue()
tc.assertFalse(q.empty())
tc.assertEqual(q.data.count(None), 9)
tc.assertEqual(q.head, q.tail)
tc.assertEqual(q.head, 5)
for i in range(9):
q.enqueue(i)
with tc.assertRaises(RuntimeError):
q.enqueue(10)
for x, y in zip(q, [5] + list(range(9))):
tc.assertEqual(x, y)
答案 0 :(得分:2)
我很确定使用self.queue
的所有代码都是错误的。根本不需要该属性。 data
属性的重点是使用它来存储值。使用索引head
和tail
来确定data
放置内容的位置(以及从哪里取出):
class Queue:
''' Constructor '''
def __init__(self, limit):
self.limit = limit
self.data = [None] * limit
self.head = 0
self.tail = -1
self.count = 0
def dequeue(self):
if self.count == 0:
raise RuntimeError
else:
x = self.data[self.head]
self.head = (self.head + 1) % self.limit
self.count -= 1
return x
def enqueue(self, item):
if self.count == self.limit:
raise RuntimeError
else:
self.count += 1
self.tail = (self.tail + 1) % self.limit
self.data[self.tail] = item
def __str__(self):
return " ".join([str(v) for v in self]) # use __iter__
def resize(self, new_limit):
if new_limit < self.count:
raise RuntimeError
new_data = [None]*new_limit
for i, item in enumerate(self):
new_data[i] = item
self.data = new_data
self.head = 0
self.tail = self.count - 1
def empty(self):
return 0 == self.count
def __bool__(self): # this is better than empty()
return self.count != 0
def __iter__(self): # renamed from iter so you can use it in a for loop
for i in range(self.count):
return self.data[(self.head + i) % self.limit]
您可能还应该使用__len__
方法。
答案 1 :(得分:1)
我收到一条错误,指出Queue类没有数据属性
我在您的代码上运行测试时没有提到错误。
答案 2 :(得分:0)
如果由于某些原因您不想使用内置的collections.deque模块,请参见以下示例,了解如何实现自己的循环缓冲区:
"""
Example of circular buffer using regular list
"""
class CircularBuffer:
def __init__(self, size):
self.buffer = [None] * size
self.size = size
self.count = 0
self.tail = 0
self.head = 0
@property
def is_empty(self):
return self.count == 0
@property
def is_full(self):
return self.count == self.size
def __len__(self):
return self.count
def add(self, value):
# if buffer is full overwrite the value
if self.is_full:
self.tail = (self.tail + 1) % self.size
else:
self.count += 1
self.buffer[self.head] = value
self.head = (self.head + 1) % self.size
def remove(self):
if self.count == 0:
raise Exception("Circular Buffer is empty")
value = self.buffer[self.tail]
self.tail = (self.tail + 1) % self.size
self.count -= 1
return value
def __iter__(self):
index = self.tail
counter = self.count
while counter > 0:
yield self.buffer[index]
index = (index + 1) % self.size
counter -= 1
def __repr__(self):
return "[]" if self.is_empty else "[" + ",".join(str(i) for i in self) + "]"