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

Как отменить QList?

Я вижу qCopy и qCopybackward но ни один из них не позволяет мне сделать копию в обратном порядке. qCopybackward только копирует его в обратном порядке, но сохраняет элементы штопа в одном порядке! Все, что я хочу сделать, это вернуть копию списка в обратном порядке. Там имеет функцию для этого, правильно?

4b9b3361

Ответ 1

Если вам не нравится QTL, просто используйте STL. У них может не быть Qt-ish API, но STL API устойчив к року:) Тем не менее, qCopyBackward - это просто std::copy_backward, поэтому, по крайней мере, они совместимы.

Отвечая на ваш вопрос:

template <typename T>
QList<T> reversed( const QList<T> & in ) {
    QList<T> result;
    result.reserve( in.size() ); // reserve is new in Qt 4.7
    std::reverse_copy( in.begin(), in.end(), std::back_inserter( result ) );
    return result;
}

РЕДАКТИРОВАТЬ 2015-07-21: Очевидно (или, может быть, нет), если вы хотите использовать один-лайнер (и люди, похоже, предпочитают это, глядя на относительные варианты ответов через пять лет), и у вас есть не const list, описанный выше сворачивается на

std::reverse(list.begin(), list.end());

Но я думаю, что материал, работающий с индексом, лучше подходит для безопасности работы:)

Ответ 2

Обрати свой QList с помощью одной строки:

for(int k = 0; k < (list.size()/2); k++) list.swap(k,list.size()-(1+k));

Ответ 3

Вы можете использовать итератор стиля Java. Полный пример здесь (http://doc.qt.digia.com/3.2/collection.html). Найдите слово "reverse".

QList<int> list; // initial list

list << 1;
list << 2;
list << 3;

QList<int> rlist; // reverse list+

QListIterator<int> it(list);
while (it.hasPrevious()) {
    rlist << it.previous();
}

Ответ 4

@Marc Jentsch ответ хороший. И если вы хотите получить дополнительный 30% -ный прирост производительности, вы можете изменить его однострочный размер на:

for(int k=0, s=list.size(), max=(s/2); k<max; k++) list.swap(k,s-(1+k));

Один ThinkPad W520 с QList из 10 миллионов QTimers Я получил эти цифры:

  • Переполнение стека перевернутого списка заняло 194 мс
  • переполнение стека перевернутого списка с максимальным размером и размером 136 мс

Усиление - результат

  • выражение (list.size()/2) вычисляется только один раз при инициализации цикла, а не после каждого шага
  • выражение list.size() в swap() вызывается только один раз при инициализации цикла, а не после каждого шага

Ответ 5

[Переписать из оригинала]

Не ясно, хочет ли OP знать "Как [изменить] QList?" или на самом деле хочет обратную копию. Пользователь mmutz дал правильный ответ на обратную копию, но если вы просто хотите отменить QList на месте, вот что:

#include <algorithm>

И затем

std::reverse(list.begin(), list.end());

Или в С++ 11:

std::reverse(std::begin(list), std::end(list));

Красота стандартной библиотеки С++ (и шаблонов в целом) заключается в том, что алгоритмы и контейнеры являются отдельными. Сначала может показаться раздражающим, что стандартные контейнеры (и, в меньшей степени, контейнеры Qt) не имеют удобных функций, таких как list.reverse(), но рассмотрите альтернативы: что более элегантно: Предоставьте методы reverse() для всех контейнеров, или определить стандартный интерфейс для всех контейнеров, которые позволяют двунаправленную итерацию, и предоставить одну реализацию reverse(), которая работает для всех контейнеров, поддерживающих двунаправленную итерацию?

Чтобы проиллюстрировать, почему это элегантный подход, рассмотрите ответы на некоторые похожие вопросы:

"Как вы меняете std::vector<int>?":

std::reverse(std::begin(vec), std::end(vec));

"Как вы меняете std::deque<int>?":

std::reverse(std::begin(deq), std::end(deq));

Как насчет частей контейнера?

"Как вы отменяете первые семь элементов QList?": даже если авторы QList предоставили нам удобный метод .reverse(), они, вероятно, не предоставили бы нам эту функцию, но здесь это:

if (list.size() >= 7) {
    std::reverse(std::begin(list), std::advance(std::begin(list), 7));
} 

Но это становится лучше: поскольку интерфейс итератора совпадает с синтаксисом C-указателя, а потому, что С++ 11 добавил бесплатные функции std::begin() и std::end, вы можете сделать это:

"Как изменить массив float x[10]?":

std::reverse(std::begin(x), std::end(x));

или pre С++ 11:

std::reverse(x, x + sizeof(x) / sizeof(x[0])); 

(Это уродство, которое std::end() скрывает для нас.)

Продолжайте: "Как изменить буфер float* x размера n?":

std::reverse(x, x + n);

"Как изменить строку с нулевым завершением char* s?":

std::reverse(s, s + strlen(s));

"Как изменить строку char* s в необязательном порядке с нулевым завершением в буфере размера n?":

std::reverse(s, std::find(s, s + n, '\0'));

Обратите внимание, что std::reverse использует swap(), поэтому даже это будет выполняться в значительной степени, а также возможно:

QList<QList<int> > bigListOfBigLists;
....
std::reverse(std::begin(bigListOfBigLists), std::end(bigListOfBigLists));

Также обратите внимание, что все они должны выполняться так же, как и ручной цикл, поскольку, когда это возможно, компилятор превратит их в арифметику указателя. Кроме того, вы не можете четко написать многоразовую, общую, высокопроизводительную функцию reverse, подобную этой C.

Ответ 6

Для стандартных списков библиотек это будет выглядеть как

std::list<X> result;
std::copy(list.rbegin(), list.rend(), result.back_inserter());

К сожалению, Qt не имеет функций rbegin и rend, которые возвращают обратные итераторы (те, которые идут от конца контейнера к его началу). Вы можете написать их, или вы можете просто написать функцию копирования самостоятельно - реверсирование списка - отличный excersize. Или вы можете заметить, что QList на самом деле является массивом, что делает запись такой функции тривиальной. Или вы можете преобразовать список в std:: list и использовать rbegin и rend. Выберите все, что вам нравится.

Ответ 7

Реверсирование QList будет O (n), но вы это сделаете, поскольку QList не гарантирует, что его данные хранятся в памяти (в отличие от QVector). Вы можете рассмотреть просто перемещение списка в обратном порядке, где вам нужно, или использовать что-то вроде QStack, которое позволяет извлекать элементы в обратном порядке, которые они добавили.