首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >C++简单循环缓冲队列

C++简单循环缓冲队列
EN

Stack Overflow用户
提问于 2017-05-05 21:10:53
回答 6查看 5.9K关注 0票数 1

我使用数组实现了一个队列,并将其视为循环缓冲区。_tail指向要读取的下一个元素,_head指向要写入的下一个元素:

代码语言:javascript
复制
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来确定full/empty。

实现isEmpty()isFull()逻辑的最简单方法是什么?我不确定是否应该在读取队列项之后编写一个“空白”枚举?

EN

Stack Overflow用户

发布于 2021-12-26 04:26:43

有很多关于循环缓冲区的虚假信息。首先,这是一个双人赛道。每当你看到2个指针或索引时,你可能正在处理一个双端队列,你会看到头部和尾部,以及与循环缓冲区相关的频繁读和写指针。但这都是错的,循环缓冲区是一个双队列,因此与双链表相关,后者也可以用作双队列。因此,您应该考虑的是第一个和最后一个节点,而不是头和尾,就像使用双向链表一样。然后,您可以选择first == last表示空,next(last) == first表示full。或者,first == last && first == nullptr代表empty,first == last && first != nullptr代表full,但这会使代码变得复杂。我们通常不关心丢失一个插槽,我们只关心性能。

还有第三种选择,这是有学术头脑的人更喜欢的。你可以有一个size成员,size == 0代表empty,size == capacity代表full。在这种情况下,first像以前一样指向第一个占用的时隙,但last指向最后一个占用的时隙,而不是刚刚超过的那个。

最重要的是查看有关deque的文献,因为不同的人倾向于以不同的方式实现他们的循环缓冲区(例如,头部和尾部经常交换角色),deque通常更多地在学术上处理,毫不含糊。

票数 0
EN
查看全部 6 条回答
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/43805858

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档