Can queue elements be accessed like an array? If not, then what containers similar to a queue can?
-
Define "like an array". Do you mean "using the subscript operator", "in O(1) time", or what? – Brian Kelly May 04 '11 at 01:28
-
1Accessing elements like an array means using the subscript operator. – neuromancer May 04 '11 at 01:29
-
are you referring to STL's queue? IE `std::queue`? – Doug T. May 04 '11 at 01:37
8 Answers
This is a task ideal for std::deque. Its optimized for adding/removing onto the end but also provides random access to elements in the middle. To quote the linked article:
A deque is very much like a vector: like vector, it is a sequence that supports random access to elements, constant time insertion and removal of elements at the end of the sequence, and linear time insertion and removal of elements in the middle.
... deque also supports constant time insertion and removal of elements at the beginning of the sequence
So because it can efficiently add/remove from both ends, deque can be used efficiently as a queue with its push_back and pop_front methods:
std::deque<int> aDeque;
// enqueue
aDeque.push_back(1);
aDeque.push_back(2);
// dequeue
int top = aDeque.front();
aDeque.pop_front();
Accessing elements like an array means using the subscript operator
deque
also support the random access through the subscript operator:
std::cout << aDeque[0];
Can queue elements be accessed like an array?
Sure! As long as the underlying container (which defaults to deque) does, though you might want to call the code bad names...
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;
}
Notice the trick that allows you to change your std::queue variables to pubqueue variables and just access the container member directly. This lets you keep the push/pop (instead of push_back/pop_front, etc.) interface of std::queue.

- 13,952
- 4
- 37
- 63
Since you've clarified that you want subscript operator access, the answer is no. Queues are not a data structure that would ever require random element access. If you need random element access, use a vector, or an actual array.

- 19,067
- 4
- 53
- 55
The answer, it depends on the implementation of the queue. The queue provided by the Standard Template Library, doesn't give you random access to elements via the subscript operator, because the implementation of random access defeats the point of a queue.
Recall that a Queue is a datastructure that provides first-in-first-out behavior. This means you need to really concern yourself with the head-element, and thats it. Once you need access to elements beside the head, you no longer have a queue.
Now that doesn't mean you can't implement your own queue on top of an array/vector class, however it's not going to be efficient, as both arrays and vectors aren't ideal for adding and removing elements dynamically.

- 45,915
- 17
- 113
- 134
-
(`std::queue` uses a `std::deque` as its underlying container, FWIW.) – GManNickG May 04 '11 at 01:40
-
1I wouldn't implement a queue with anything *but* an array-like class. – Dennis Zickefoose May 04 '11 at 01:41
-
-
@Alan: Note he said array-like, which could include a deque, which has efficient front and back manipulations. In any case, linked-lists are possibly the worse container there is, slow in every regard (compared to other containers) except splicing and reversing, and the benefits of those are only noticeable when the primary operation is splicing or reversing. – GManNickG May 04 '11 at 03:38
-
@GMan: A deque isn't necessarily "Array-like." You can implement one with a growing array, but that's an implementation choice. Array-like, means the characteristics of an array (constant time access, contiguous memory allocation) etc. A deque doesn't guarantee either. A deque implemented via an dynamic array, has an amortized cost for inserts, where as and implementation using a list, has a fixed cost of O(1) for inserts at front and back. You add much more complexity which increases the likelihood of it being error prone if you use an array to implement your queue. – Alan May 04 '11 at 04:16
-
@Alan: First of all I said "could", not necessarily, but let's not argue semantics. Secondly, deque is required to have amortized constant complexity for both element access and manipulations of the front and back. And error-prone isn't relevant when we're using the standard library. – GManNickG May 04 '11 at 04:23
-
@GMan: Again, you are focusing on language specific implementations. Deque isn't required to have constant lookup for element access. A deque is required to provide push-pop from both the front and the end of the structure. That's it. When dealing with the STL, you don't have to worry about error prone. But say you have to implement your own queue (perhaps you can't make use of the STL), is an array always the best choice? You (nor Dennis) have given me any reason why I should always choose an array over a list. – Alan May 04 '11 at 05:11
-
@Alan: You realize this is tagged C++ and stl, right? And again, we said "array-like", which a deque is perfectly capable of being. Stop arguing semantics. – GManNickG May 04 '11 at 05:27
-
@GMan: The stl tag was added 3 hours ago, while I made my answer 4 hours ago, when the original question made no mention of the STL. The only one arguing semantics here is you ('array' vs 'array-like' and 'could' vs 'necessarily'). Pointing out that you are wrong about element access being a requirement for a deque, isn't a semantics argument. You are improperly using a specific implementation of a data-structure to generalize the behavior and characteristics of it. – Alan May 04 '11 at 05:50
-
@Alan: Uh, no. We said array-like, you're the one trying to strip that off and create a strawman, arguing that array-like *cannot possibly* mean deque. Note that is "not necessarily" is not the same as "necessarily not", and reread. – GManNickG May 04 '11 at 05:53
-
@Alan: That's not semantics, that's basic logic. Again, any array-like class is better than a list. A deque is an array-like class. A deque is better than a list. The statement holds. – GManNickG May 04 '11 at 06:12
-
@Alan: GMan covered what I was trying to get across. In a situation where I am forced to implement a queue by hand, without any library support, I would still start with an array-like structure, and only switch to a linked list if project requirements mandated it. Amortized constant inserts are good enough for me, the inefficiencies are more reasonable in my opinion, and implementing a double-ended queue on top of an array isn't exactly difficult. – Dennis Zickefoose May 04 '11 at 06:18
-
@GMan: `Again, any array-like class is better than a list.` Why? And how is List not an Array-Like structure? – Alan May 04 '11 at 06:42
-
@Alan: Let's ignore all the semantic and categorical issues we keep running into, because it's wasting our time. I'll make the claim: Given the choice between an array-like deque (the one required by the C++ standard library) and a linked list, the latter is the worse choice. Lists have terrible allocation times associated to each node and terrible cache coherency. Contrarily, deque allocation is also constant and doesn't dynamically allocate nearly as often, and has great cache coherency. – GManNickG May 04 '11 at 06:47
-
@Dennis: Thank you for answering my question. So it's really personal preference. Implementing a queue with an array might not be difficult, but certainly implementing one with a list would be even easier. I asked, because I wanted to know if there was any compelling reason to always use an array over a list, and there doesn't seem to be. – Alan May 04 '11 at 06:53
-
@GMan: You keep focusing on a very specific implementation. Given a choice between the `std::list` and `std::deque`, `std::deque` is a better choice, for every reason you have said. Now lets forget the STL for a moment, and talk broader terms. A list could be implemented on-top of an array, much like a deque can. If this were the case (as it is in C# for example), then every argument for using deque over list would seem moot, no? So your reason to `hate on list` appears to be due to how it is implemented in the STL, and not anything fundamentally to do with the abstract datastructure itself. – Alan May 04 '11 at 06:59
-
@Alan: Firstly, a C# list is a dynamic array, just like `std::vector`, and not a linked list. A linked list, by definition, allocates nodes and links them; that's the whole point. And yes, you can keep a freelist from an array of nodes to help eliminate the problems, but then all you've done is implemented a crude deque! So no, again, linked lists are, in general, the slowest container. – GManNickG May 04 '11 at 07:22
Instead of a queue, use a vector. Queue doesn't use the [] operator.

- 4,117
- 23
- 25
-
4Well vector's interface only lets you push/pop on the back. There's a performance hit when pushing or popping onto the front since everything needs to move down in the array. Vector would be better optimized for a stack with random access. – Doug T. May 04 '11 at 01:40
Out of STL following containers can use operator[] access: vector, dequeue, map, bitset.
The default container to use is vector container. In your case dequeue is the most valuable option (because you want to have queue operations as well as random access).
Have a look at reference sheet that shows available operations on STL containers: http://www.cplusplus.com/reference/stl/
Diagram to identify what type of container you need to use (at the bottom of the page): http://www.linuxsoftware.co.nz/cppcontainers.html

- 921
- 1
- 6
- 15
You can use vector like queue, example:
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

- 71
- 3
std::queue
has no random element access, it's a sequence container adaptor by default using std::dequeue
. However, it's worthy noting that if you're using microsoft's compiler cl
, you can use ._Get_container()
method that lets you access the underlying container and thus its individual elements, like so:
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';
}
hth.

- 4,728
- 8
- 44
- 68