Std:: queue iteration
Мне нужно перебрать std::queue
.
www.cplusplus.com говорит:
По умолчанию, если для определенного класса очереди не указан класс контейнера, используется стандартный шаблон шаблона класса контейнера.
Так можно ли как-то добраться до очереди, лежащей в основе deque, и перебрать ее?
Ответы
Ответ 1
Если вам нужно выполнить итерацию по queue
, вам потребуется нечто большее, чем очередь. Точка стандартных контейнерных адаптеров - это минимальный интерфейс. Если вам нужно также выполнить итерацию, почему бы просто не использовать вместо этого deque (или список)?
Ответ 2
Хотя я согласен с другими, что предпочтительным решением является прямое использование итеративного контейнера, я хочу отметить, что стандарт С++ гарантирует достаточную поддержку для самостоятельного решения, если вы хотите его по какой-либо причине.
А именно, вы можете наследовать от std::queue
и использовать его защищенный член Container c;
для доступа к begin() и end() базового контейнера (при условии, что такие методы существуют там). Вот пример, который работает в VS 2010 и протестирован с ideone:
#include <queue>
#include <deque>
#include <iostream>
template<typename T, typename Container=std::deque<T> >
class iterable_queue : public std::queue<T,Container>
{
public:
typedef typename Container::iterator iterator;
typedef typename Container::const_iterator const_iterator;
iterator begin() { return this->c.begin(); }
iterator end() { return this->c.end(); }
const_iterator begin() const { return this->c.begin(); }
const_iterator end() const { return this->c.end(); }
};
int main() {
iterable_queue<int> int_queue;
for(int i=0; i<10; ++i)
int_queue.push(i);
for(auto it=int_queue.begin(); it!=int_queue.end();++it)
std::cout << *it << "\n";
return 0;
}
Ответ 3
Вы можете сохранить исходную очередь во временную очередь. Затем вы просто делаете обычное всплывающее окно во временной очереди, чтобы просмотреть исходную, например:
queue tmp_q = original_q; //copy the original queue to the temporary queue
while (!tmp_q.empty())
{
q_element = tmp_q.front();
std::cout << q_element <<"\n";
tmp_q.pop();
}
В конце tmp_q будет пустым, но исходная очередь не будет затронута.
Ответ 4
Почему бы просто не сделать копию очереди, которую вы хотите перебрать, и удалить элементы по одному, распечатывая их, когда идете? Если вы хотите сделать больше с элементами при повторении, то очередь будет неправильной структурой данных.
Ответ 5
Посмотрите изображение fooobar.com/questions/4286/..., а затем решите, какой контейнер лучше всего подходит вашим потребностям.
Ответ 6
в то время как ответ алексея Куканова может быть более эффективным, вы также можете перебирать очередь очень естественным образом, выталкивая каждый элемент из передней части очереди, а затем перемещая его назад:
#include <iostream>
#include <queue>
using namespace std;
int main() {
//populate queue
queue<int> q;
for (int i = 0; i < 10; ++i) q.push(i);
// iterate through queue
for (size_t i = 0; i < q.size(); ++i) {
int elem = std::move(q.front());
q.pop();
elem *= elem;
q.push(std::move(elem));
}
//print queue
while (!q.empty()) {
cout << q.front() << ' ';
q.pop();
}
}
выход:
0 1 4 9 16 25 36 49 64 81
Ответ 7
Если вам нужно итерировать очередь... очередь - это не тот контейнер, в котором вы нуждаетесь.
Почему вы выбрали очередь?
Почему бы вам не взять контейнер, который вы можете перебрать?
1.если вы выбираете очередь, тогда вы говорите, что хотите поместить контейнер в интерфейс "queue": - фронт - назад - От себя - поп -...
если вы также хотите итерации, очередь имеет неправильный интерфейс. Очередь - это адаптер, который предоставляет ограниченное подмножество исходного контейнера
2. Определение очереди - это FIFO, и по определению FIFO не является итерируемым
Ответ 8
Я использую что-то вроде этого. Не очень сложно, но должно работать.
queue<int> tem;
while(!q1.empty()) // q1 is your initial queue.
{
int u = q1.front();
// do what you need to do with this value.
q1.pop();
tem.push(u);
}
while(!tem.empty())
{
int u = tem.front();
tem.pop();
q1.push(u); // putting it back in our original queue.
}
Это будет работать, потому что когда вы извлекаете что-то из q1 и вставляете это в tem, это становится первым элементом tem. Таким образом, в итоге tem становится точной копией q1.
Ответ 9
Короче говоря: нет.
Есть хак, используйте vector в качестве нижележащего контейнера, поэтому queue::front
вернет действительную ссылку, преобразует ее в указатель итерирует до <= queue::back
Ответ 10
std::queue
является адаптером контейнера, и вы можете указать используемый контейнер (по умолчанию используется deque
). Если вам нужна функциональность, выходящая за рамки адаптера, просто используйте deque
или другой контейнер напрямую.