C++ 访问c++;像数组一样对元素进行排队

C++ 访问c++;像数组一样对元素进行排队,c++,stl,queue,C++,Stl,Queue,队列元素可以像数组一样访问吗?如果不是,那么类似于队列的容器可以是什么?这是一项理想的任务。它的优化是为了增加/删除端,但也提供了对中间元素的随机访问。引用链接文章: deque非常像一个 向量:和向量一样,它是一个序列 支持随机访问 元素、恒定时间插入和 在测试结束时移除元件 顺序和线性时间插入和去除元素在中间。 。。。deque还支持在序列开始时固定时间插入和删除元素 因此,由于deque可以有效地从两端添加/删除,因此它可以通过push_-back和pop_-front方法有效地用作队列:

队列元素可以像数组一样访问吗?如果不是,那么类似于队列的容器可以是什么?

这是一项理想的任务。它的优化是为了增加/删除端,但也提供了对中间元素的随机访问。引用链接文章:

deque非常像一个 向量:和向量一样,它是一个序列 支持随机访问 元素、恒定时间插入和 在测试结束时移除元件 顺序和线性时间插入和去除元素在中间。

。。。deque还支持在序列开始时固定时间插入和删除元素

因此,由于deque可以有效地从两端添加/删除,因此它可以通过push_-back和pop_-front方法有效地用作队列:

std::deque<int> aDeque;

// enqueue
aDeque.push_back(1);
aDeque.push_back(2);

// dequeue
int top = aDeque.front();
aDeque.pop_front();

既然您已经澄清您想要下标操作符访问,那么答案是否定的。队列不是一种需要随机元素访问的数据结构。如果需要随机元素访问,请使用向量或实际数组。

答案取决于队列的实现。标准模板库提供的队列不允许通过下标操作符对元素进行随机访问,因为随机访问的实现会破坏队列的点

回想一下,队列是一种提供先进先出行为的数据结构。这意味着您需要真正关注头部元素,仅此而已。一旦需要访问头部旁边的元素,就不再有队列


这并不意味着你不能在数组/向量类上实现你自己的队列,但是它不会很有效,因为数组和向量都不适合动态添加和删除元素。

使用向量代替队列。队列未使用[]运算符

以下STL以外的容器可以使用操作员[]访问: 向量,出列,映射,位集

要使用的默认容器是向量容器。在您的情况下,出列是最有价值的选择(因为您希望进行队列操作和随机访问)

查看显示STL容器可用操作的参考表:

标识您需要使用哪种容器类型的图表(在页面底部):

队列元素可以像数组一样访问吗

当然!只要底层容器(默认为deque)存在,尽管您可能希望将代码称为坏名称

template<class T, class C=std::deque<T> >
struct pubqueue : std::queue<T, C> {
  using std::queue<T, C>::c;

  static C& get_c(std::queue<T, C> &s) {
    return s.*&pubqueue::c;
  }
  static C const& get_c(std::queue<T, C> const &s) {
    return s.*&pubqueue::c;
  }
};

template<class T, class C>
C& get_c(std::queue<T, C> &a) {
  return pubqueue<T, C>::get_c(a);
}
template<class T, class C>
C& get_c(std::queue<T, C> const &a) {
  return pubqueue<T, C>::get_c(a);
}

int main() {
  std::queue<int> q;
  q.push(42);
  std::cout << get_c(q)[0] << '\n';

  pubqueue<int> p;
  p.push(3);
  std::cout << p.c[0] << '\n';

  return 0;
}
模板
结构pubqueue:std::queue{
使用std::queue::c;
静态C&get_C(标准::队列&s){
返回s.*&pubqueue::c;
}
静态C常量和get_C(标准::队列常量和s){
返回s.*&pubqueue::c;
}
};
模板
C&get_C(标准::队列和a){
return pubqueue::get_c(a);
}
模板
C&get_C(标准::队列常数&a){
return pubqueue::get_c(a);
}
int main(){
std::队列q;
q、 推(42);

std::cout
std::queue
没有随机元素访问,默认情况下它是使用
std::dequeue
的序列容器适配器。但是,值得注意的是,如果您使用的是microsoft编译器
cl
,则可以使用
\u Get\u container()
方法,该方法允许您访问底层容器及其各个元素,如下所示:

std::deque<int> dq;

std::queue<int, decltype(dq)> q;
q.push(23);
q.push(90);
q.push(38794);
q.push(7);
q.push(0);
q.push(2);
q.push(13);
q.push(24323);
q.push(0);
q.push(1234);

for (int i = 0; i < q.size(); i++)
{
    std::cout << q._Get_container()[i] << '\n';
}
std::deque dq;
std::队列q;
q、 推(23);
q、 推(90);
q、 推(38794);
q、 推(7);
q、 推(0);
q、 推(2);
q、 推(13);
q、 推(24323);
q、 推(0);
q、 推(1234);
对于(int i=0;istd::cout您可以使用类似向量的队列,例如:

std::vector<int> v;
int i=0;

v.push_back(1);
v.push_back(2);
v.push_back(3);
v.push_back(4);

// "dequeue"
i=v[0]; // get 1
v.erase[ v.begin() ); // remove 1 / "dequeue" 1

i=v[0]; // get 2
v.erase[ v.begin() ); // remove 2 / "dequeue" 2

i=v[0]; // get 3
v.erase[ v.begin() ); // remove 3 / "dequeue" 3

i=v[0]; // get 4
v.erase[ v.begin() ); // remove 4 / "dequeue" 4
std::vector v;
int i=0;
v、 推回(1);
v、 推回(2);
v、 推回(3);
v、 推回(4);
//“出列”
i=v[0];//获取1
v、 擦除[v.begin());//删除1/“出列”1
i=v[0];//获取2
v、 擦除[v.begin());//删除2/“出列”2
i=v[0];//得到3
v、 擦除[v.begin());//删除3/“出列”3
i=v[0];//得到4
v、 擦除[v.begin());//删除4/“出列”4

定义“像一个数组”。你的意思是“使用下标运算符”,“在O(1)时间内”,或者什么?访问数组之类的元素意味着使用下标操作符。你是指STL的队列吗?即
std::queue
?Well vector的界面只允许你在后面推/弹出。当推或弹出到前面时,性能会受到影响,因为数组中的所有东西都需要向下移动。vector在r具有随机访问的堆栈。(
std::queue
使用
std::deque
作为其底层容器FWIW。)我不会用类似数组的类来实现队列。@Dennis:为什么?在列表上使用数组有什么好处?@Alan:注意,他说的类似数组可以包括一个deque,它具有高效的前后操作。无论如何,链表可能是最糟糕的容器,在各方面都很慢(与其他容器相比)除了拼接和反转之外,它们的好处只有在主要操作是拼接或反转时才明显。@GMan:deque不一定是“类似数组的”。您可以使用不断增长的数组实现一个,但这是一种实现选择。类似数组表示数组的特性(固定时间访问、连续内存分配)等。deque也不能保证。通过动态数组实现的deque具有插入的摊销成本,其中as和使用列表的实现具有O(1)的固定成本对于前面和后面的插入。如果使用数组实现队列,会增加复杂性,从而增加出错的可能性。到std::deque的链接已断开:(
std::vector<int> v;
int i=0;

v.push_back(1);
v.push_back(2);
v.push_back(3);
v.push_back(4);

// "dequeue"
i=v[0]; // get 1
v.erase[ v.begin() ); // remove 1 / "dequeue" 1

i=v[0]; // get 2
v.erase[ v.begin() ); // remove 2 / "dequeue" 2

i=v[0]; // get 3
v.erase[ v.begin() ); // remove 3 / "dequeue" 3

i=v[0]; // get 4
v.erase[ v.begin() ); // remove 4 / "dequeue" 4