如何反转QList?

我看到qCopy和qCopybackward但似乎都没有让我以相反的顺序复制。
qCopybackward
只能以相反的顺序复制它,但保持darn元素的顺序相同!我想要做的就是以相反的顺序返回列表的副本。必须有一个功能,对吧?     
已邀请:
如果您不喜欢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());
但我觉得索引摆弄的东西更适合工作安全:)     
用一行反转你的QList:
for(int k = 0; k < (list.size()/2); k++) list.swap(k,list.size()-(1+k));
    
您可以使用Java样式迭代器。这里有完整的例子(http://doc.qt.digia.com/3.2/collection.html)。寻找“反向”这个词。
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();
}
    
@Marc Jentsch的答案很好。如果你想获得额外30%的性能提升,你可以将他的单行改为:
for(int k=0, s=list.size(), max=(s/2); k<max; k++) list.swap(k,s-(1+k));
一个QPad为1000万QTimers的ThinkPad W520我得到了这些数字: 倒车列表堆栈溢出耗时194毫秒 最大和大小的反向列表堆栈溢出需要136毫秒 提升的结果是 表达式(list.size()/ 2)在初始化循环时仅计算一次,而不是在每个步骤之后计算 swap()中的表达式list.size()仅在初始化循环时调用一次,而不是在每个步骤之后调用     
[原创改写] 目前尚不清楚OP是否想知道“我如何反转QList?”或者实际上想要反转副本。用户mmutz给出了反向副本的正确答案,但是如果你只想反转QList,那就是:
#include <algorithm>
然后
std::reverse(list.begin(), list.end());
或者在C ++ 11中:
std::reverse(std::begin(list), std::end(list));
C ++标准库(以及通常的模板)的优点在于算法和容器是分开的。起初,标准容器(以及较小程度上的Qt容器)没有像
list.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指针语法相同,并且因为C ++ 11添加了免费的
std::begin()
std::end
函数,所以你可以这样做: “你如何扭转数组?26:”:
std::reverse(std::begin(x), std::end(x));
或者预先C ++ 11:
std::reverse(x, x + sizeof(x) / sizeof(x[0])); 
(那就是
std::end()
为我们隐藏的丑陋。) 我们继续: “你如何扭转尺寸
n
的缓冲区
float* x
?”:
std::reverse(x, x + n);
“你如何反转以null结尾的字符串
char* s
?”:
std::reverse(s, s + strlen(s));
“你如何在一个大小为ѭ31的缓冲区中反转一个不一定为空的字符串
char* s
?”:
std::reverse(s, std::find(s, s + n, ''));
请注意,
std::reverse
使用
swap()
,所以即使这样也会尽可能地执行:
QList<QList<int> > bigListOfBigLists;
....
std::reverse(std::begin(bigListOfBigLists), std::end(bigListOfBigLists));
还要注意,这些都应该像手写循环一样执行,因为在可能的情况下,编译器会将这些转换为指针算法。此外,您无法干净地编写可重用,通用,高性能的
reverse
功能,如此C.     
对于标准库列表,它看起来像这样
std::list<X> result;
std::copy(list.rbegin(), list.rend(), result.back_inserter());
不幸的是,Qt没有返回反向迭代器的rbegin和rend函数(从容器的末尾到它的begnning)。您可以编写它们,或者您可以自己编写复制功能 - 反转列表是一个很好的例外。或者你可以注意到QList实际上是一个数组,是什么让编写这样一个函数变得微不足道。或者您可以将列表转换为std :: list,并使用rbegin和rend。选择你喜欢的任何东西     
反转QList将是O(n)然而你这样做,因为QList不能保证其数据连续存储在内存中(与QVector不同)。您可能会考虑在需要的地方以向后的顺序遍历列表,或者使用类似QStack的东西,它允许您按照添加的相反顺序检索元素。     

要回复问题请先登录注册