我使用数组实现了一个队列,并将其视为循环缓冲区。 _tail
指向要读取的下一个元素,_head
指向要写入的下一个元素:
template<int SIZE>
class Q {
bool push(const int item){
if(false == isFull()){
_q[_head] = item;
_head = ++_head % SIZE;
return true;
}
return false;
}
bool pop(int& toReturn){
if(false == isEmpty()){
toReturn = _q[_tail];
_tail = ++_tail % SIZE;
return true;
}
return false;
}
private:
std::array<int, SIZE> _q;
std::atomic<int> _head;
std::atomic<int> _tail;
};
但是,我的isFull()
和isEmpty()
逻辑中存在一个错误,该问题由以下问题确定:
当队列最初为空时,_tail
和_head
都会指向_q[0]
。
当我写_q[0]
时,_q[1]
,_q[2]
和q[3]
再次_tail
和_head
将指向相同,那么清楚我无法使用_tail
== _head
来确定完整/空。
实现isEmpty()
和isFull()
逻辑的最简单方法是什么?我不确定我是否应该写一个&#34; BLANK&#34;读取队列项后的枚举?
答案 0 :(得分:0)
在类中声明一个数据成员(计数器),用于计算队列中的项目数。递增(推)并递减(弹出)。当它为(0)时,队列为空
答案 1 :(得分:0)
如果您愿意将队列的有效大小减少一个元素,那么逻辑相对简单:
head
和tail
相同时,队列为空。tail
递增1时,使用环绕生成head
,队列已满。这使得不可能插入作为“哨兵”的第N个元素。因此,对于N元素队列,您需要分配一个N + 1个元素的数组,并在处理环绕的所有表达式中使用(SIZE+1)
。
std::array<int,SIZE+1> _q;
实施说明:
这两行
_head = ++_head % SIZE;
_tail = ++_tail % SIZE;
具有未定义的行为,因为编译器可以灵活地应用在赋值结束之前或之后递增_head
和_tail
的副作用。如果编译器选择在赋值后应用副作用,则不会发生环绕效果。
由于您根本不需要复合赋值,因此修复很简单:
_head = (_head+1) % SIZE;
_tail = (_tail+1) % SIZE;
答案 2 :(得分:0)
如何更改实现有点像
从&#34; _head points to the next element to write into:
&#34;更改您的头部定义到&#34; _head points to latest element added
&#34;
然后isFull()
可以是
bool isFull()
{
if((_head + 1) % SIZE == _tail)
return true;
return false;
}
和isEmpty
可能是
bool isEmpty()
{
if(_head == _tail)
return true;
return false;
}
pop()
会相同但更改push()
并且不要忘记将_head
和_tail
初始化为-1
bool push(const int item){
if(false == isFull()){
if(_head == -1) //If adding the first element,
_tail = 0; // tail will point to it as it was inititiallty 0
_head = ++_head % SIZE;
_q[_head] = item;
return true;
}
return false;
}
答案 3 :(得分:0)
由于您使用模数来计算数组的索引,因此保留每次读写的运行计数可以简化逻辑。
改变这样的实现......
bool push(const int item){
if(false == isFull()){
_q[_head % SIZE] = item;
++_head;
return true;
}
return false;
}
bool pop(int& toReturn){
if(false == isEmpty()){
toReturn = _q[_tail % SIZE];
++_tail;
return true;
}
return false;
}
并使用这些......
bool isFull()
{
return _head - _tail == SIZE;
}
bool isEmpty()
{
if (_head == _tail)
{
_head = _tail = 0;
return true;
}
return false;
}