【发布时间】:2011-08-18 03:54:38
【问题描述】:
可以像数组一样访问队列元素吗?如果不是,那有什么类似于队列的容器可以呢?
【问题讨论】:
-
定义“像一个数组”。您的意思是“使用下标运算符”、“在 O(1) 时间内”还是什么?
-
像数组一样访问元素意味着使用下标运算符。
-
你指的是STL的队列吗?即
std::queue?
可以像数组一样访问队列元素吗?如果不是,那有什么类似于队列的容器可以呢?
【问题讨论】:
std::queue?
这是std::deque 的理想任务。它针对添加/删除到末尾进行了优化,但也提供了对中间元素的随机访问。引用链接的文章:
双端队列非常像 vector:和vector一样,是一个序列 支持随机访问 元素,恒定时间插入和 删除末尾的元素 序列,以及中间元素的线性时间插入和移除。
... 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();
像数组一样访问元素意味着使用下标运算符
deque也支持通过下标操作符随机访问:
std::cout << aDeque[0];
【讨论】:
可以像数组一样访问队列元素吗?
当然!只要底层容器(默认为双端队列)确实如此,尽管您可能希望将代码称为坏名...
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;
}
请注意允许您将 std::queue 变量更改为 pubqueue 变量并直接访问容器成员的技巧。这让您可以保留 std::queue 的 push/pop(而不是 push_back/pop_front 等)接口。
【讨论】:
既然您已经澄清您想要下标运算符访问,那么答案是否定的。队列不是需要随机元素访问的数据结构。如果您需要随机元素访问,请使用向量或实际数组。
【讨论】:
答案,这取决于队列的实现。标准模板库提供的队列不会让您通过下标运算符随机访问元素,因为随机访问的实现会破坏队列的点。
回想一下,队列是一种提供先进先出行为的数据结构。这意味着你需要真正关注头部元素,仅此而已。一旦你需要访问头部旁边的元素,你就不再有队列了。
现在这并不意味着您不能在数组/向量类之上实现自己的队列,但是它不会很有效,因为数组和向量都不适合动态添加和删除元素。
【讨论】:
std::queue 使用 std::deque 作为其底层容器 FWIW。)
使用向量代替队列。队列不使用 [] 运算符。
【讨论】:
STL 以下容器可以使用 operator[] 访问: 矢量、出列、映射、位集。
使用的默认容器是矢量容器。在您的情况下,出队是最有价值的选择(因为您希望进行队列操作以及随机访问)。
查看显示 STL 容器上可用操作的参考表: http://www.cplusplus.com/reference/stl/
确定您需要使用哪种类型的容器的图表(在页面底部): http://www.linuxsoftware.co.nz/cppcontainers.html
【讨论】:
std::queue 没有随机元素访问,它是一个序列容器适配器,默认使用std::dequeue。但是,值得注意的是,如果您使用的是微软的编译器cl,您可以使用._Get_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::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
【讨论】: