Подтвердить что ты не робот

Std:: queue iteration

Мне нужно перебрать std::queue. www.cplusplus.com говорит:

По умолчанию, если для определенного класса очереди не указан класс контейнера, используется стандартный шаблон шаблона класса контейнера.

Так можно ли как-то добраться до очереди, лежащей в основе deque, и перебрать ее?

4b9b3361

Ответ 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 или другой контейнер напрямую.