C++ 使用STL队列的循环队列?
我在互联网上搜索了一段时间,但似乎找不到这个问题的答案 我打算使用stl::queue进行一些模拟。我想知道是否可以使用stl::queue创建一个循环队列?据我所知,stl::queue是线性的,默认情况下不是循环的 如果这是可能的,是否有任何实现参考,我可以参考C++ 使用STL队列的循环队列?,c++,stl,queue,C++,Stl,Queue,我在互联网上搜索了一段时间,但似乎找不到这个问题的答案 我打算使用stl::queue进行一些模拟。我想知道是否可以使用stl::queue创建一个循环队列?据我所知,stl::queue是线性的,默认情况下不是循环的 如果这是可能的,是否有任何实现参考,我可以参考 谢谢。std::deque被相当仔细地定义为一个线性队列。它的设计并不真正适合循环队列 特别是,它将队列分成许多大小相等的块,因此如果队列是合理平衡的(即,平均而言,数据的消耗速度与数据的生成速度差不多),通常会丢弃块并准备好重新使
谢谢。
std::deque
被相当仔细地定义为一个线性队列。它的设计并不真正适合循环队列
特别是,它将队列分成许多大小相等的块,因此如果队列是合理平衡的(即,平均而言,数据的消耗速度与数据的生成速度差不多),通常会丢弃块并准备好重新使用,因此可以在最小堆碎片的情况下长时间使用一个块
为了实现这一点,deque(至少正常情况下)使用两级存储机制。也就是说,它有一个可扩展的指针数组,每个指针指向一个包含实际数据的大小相等的块
然而,对于循环缓冲区,这是毫无意义和不必要的。对于循环缓冲区,通常在创建内存块时分配内存块,并继续使用相同的内存块,直到销毁它。在这种情况下,deque使用的两级存储只是为每个访问添加了额外的间接级别,而没有完成任何有用的操作
对于循环缓冲区,您还可以使用一块平坦的内存来保存数据,并在该内存块中创建/销毁对象。下面是我不久前编写的一个简单实现:
#ifndef CBUFFER_H_INC
#define CBUFFER_H_INC
template <class T>
class circular_buffer {
T *data;
unsigned read_pos;
unsigned write_pos;
unsigned in_use;
const unsigned capacity;
public:
circular_buffer(unsigned size) :
data((T *)operator new(size * sizeof(T))),
read_pos(0),
write_pos(0),
in_use(0),
capacity(size)
{}
void push(T const &t) {
// ensure there's room in buffer:
if (in_use == capacity)
pop();
// construct copy of object in-place into buffer
new(&data[write_pos++]) T(t);
// keep pointer in bounds.
write_pos %= capacity;
++in_use;
}
// return oldest object in queue:
T front() {
return data[read_pos];
}
// remove oldest object from queue:
void pop() {
// destroy the object:
data[read_pos++].~T();
// keep pointer in bounds.
read_pos %= capacity;
--in_use;
}
~circular_buffer() {
// first destroy any content
while (in_use != 0)
pop();
// then release the buffer.
operator delete(data);
}
};
#endif
\ifndef CBUFFER\u H\u公司
#定义CBUFFER_H_公司
模板
类循环缓冲区{
T*数据;
未签名读取位置;
未签名写入位置;
未签字的在用;
常数无符号容量;
公众:
循环缓冲区(无符号大小):
数据((T*)运算符新建(大小*大小(T)),
读取位置(0),
写入位置(0),
在使用中(0),
容量(大小)
{}
无效推力(T常数和T){
//确保缓冲区中有空间:
如果(在用==容量)
pop();
//将对象的副本就地构造到缓冲区中
新(&data[write_pos++])T(T);
//将指针保持在边界内。
写入位置%=容量;
++在用;
}
//返回队列中最早的对象:
T前面(){
返回数据[读取位置];
}
//从队列中删除最旧的对象:
void pop(){
//销毁对象:
数据[read_pos++].~T();
//将指针保持在边界内。
读取位置%=容量;
--在用;
}
~circular_buffer(){
//首先销毁任何内容
while(正在使用!=0)
pop();
//然后释放缓冲区。
操作员删除(数据);
}
};
#恩迪夫
如果您可以使用Boost库,那么已经有一个类模板实现了front()
、back()
、push_back()
和pop_front()
成员函数,因此可以用作容器适配器的底层容器:
#include <queue>
#include <boost/circular_buffer.hpp>
#include <cassert>
template<typename T>
using Queue = std::queue<T, boost::circular_buffer<T>>;
auto main() -> int {
Queue<int> q(boost::circular_buffer<int>(3)); // capacity of the queue is 3
q.push(0);
q.push(1);
q.push(2);
assert(q.front() == 0);
assert(q.back() == 2);
q.push(3);
assert(q.front() == 1);
assert(q.back() == 3);
q.pop();
assert(q.front() == 2);
assert(q.back() == 3);
}
#包括
#包括
#包括
模板
使用Queue=std::Queue;
auto main()->int{
队列q(boost::circular_buffer(3));//队列的容量为3
q、 推(0);
q、 推(1);
q、 推(2);
断言(q.front()==0);
断言(q.back()==2);
q、 推(3);
断言(q.front()==1);
断言(q.back()==3);
q、 pop();
断言(q.front()==2);
断言(q.back()==3);
}
正确,std::queue
就是这样。但是你希望你的“循环队列”如何工作呢?谢谢你的回复。这就是我所困惑的,是否可以使用std::queue
实现循环队列。互联网上有很多循环队列,但它没有利用std::queue
。据我所知,循环队列会重新连接队列的末端,因此在对象退出队列时不会浪费内存空间。您可以通过使用std::deque
并在每次添加新项时删除第一个元素来伪造它,该项会将大小推过指定的缓冲区限制。不像真正的循环缓冲区那么便宜,但是非常容易写。你的意思是你想要一个循环(又名环)缓冲区吗?你提前知道最大尺寸吗?Boost有一个循环缓冲区:我重复一遍,不,std::queue
就是它。它不是一个循环队列,无法将自身转换为循环队列。std::list将