如何反转QList?

mpe*_*pen 26 qt

我看到qCopyqCopybackward但似乎都没有让我以相反的顺序复制.qCopybackward只能以相反的顺序复制它,但保持darn元素的顺序相同!我想要做的就是以相反的顺序返回列表的副本.有成为一个函数,对不对?

Mar*_*utz 30

如果您不喜欢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;
}
Run Code Online (Sandbox Code Playgroud)

编辑2015-07-21:显然(或者可能不是),如果你想要一个单行(并且人们似乎更喜欢那个,看看五年后不同答案的相对赞成)并且你有一个非const list上述崩溃至

std::reverse(list.begin(), list.end());
Run Code Online (Sandbox Code Playgroud)

但是我觉得索引摆弄的东西更适合工作安全:)


小智 21

用一行反转你的QList:

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

  • 但它应该,中间元素根本就没有交换,这很好,因为它也是反向列表中的中间元素. (2认同)

Rob*_*och 10

@Marc Jentsch的答案很好.如果你想获得额外30%的性能提升,你可以将他的单行改为:

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

一个QPad为1000万QTimers的ThinkPad W520我得到了这些数字:

  • 倒车列表堆栈溢出耗时194毫秒
  • 最大和大小的反向列表堆栈溢出需要136毫秒

提振是结果

  • 表达式(list.size()/ 2)在初始化循环时只计算一次,而不是在每一步之后计算
  • swap()中的表达式list.size()只在初始化循环时调用一次而不是在每一步之后调用


Xav*_*ret 9

您可以使用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();
}
Run Code Online (Sandbox Code Playgroud)


Ben*_*Ben 7

[原创改写]

目前尚不清楚OP是否想知道"我如何反转QList?" 或者实际上想要反转副本.用户mmutz给出了反向拷贝的正确答案,但是如果你只想反转QList,那就是:

#include <algorithm>
Run Code Online (Sandbox Code Playgroud)

然后

std::reverse(list.begin(), list.end());
Run Code Online (Sandbox Code Playgroud)

或者在C++ 11中:

std::reverse(std::begin(list), std::end(list));
Run Code Online (Sandbox Code Playgroud)

C++标准库(以及通常的模板)的优点在于算法和容器是分开的.起初看起来很烦人的是标准容器(以及较小程度上的Qt容器)没有类似的便利功能list.reverse(),但考虑其他选择:哪个更优雅:reverse()为所有容器提供方法,或者为其定义标准接口所有允许双向迭代的容器,并提供一个reverse()适用于支持双向迭代的所有容器的实现?

为了说明为什么这是一种优雅的方法,请考虑一些类似问题的答案:

"你怎么扭转std::vector<int>?":

std::reverse(std::begin(vec), std::end(vec));
Run Code Online (Sandbox Code Playgroud)

"你怎么扭转std::deque<int>?":

std::reverse(std::begin(deq), std::end(deq));
Run Code Online (Sandbox Code Playgroud)

容器的部分怎么样?

"你如何扭转a的前7个元素QList?":即使QList作者给了我们一个方便的.reverse()方法,他们可能也不会给我们这个功能,但这里是:

if (list.size() >= 7) {
    std::reverse(std::begin(list), std::advance(std::begin(list), 7));
} 
Run Code Online (Sandbox Code Playgroud)

但它变得更好:因为迭代器接口与C指针语法相同,并且因为C++ 11添加了free std::begin()std::end函数,所以你可以这样做:

"你如何反转阵列float x[10]?":

std::reverse(std::begin(x), std::end(x));
Run Code Online (Sandbox Code Playgroud)

或者预先C++ 11:

std::reverse(x, x + sizeof(x) / sizeof(x[0])); 
Run Code Online (Sandbox Code Playgroud)

(这就是std::end()我们隐藏的丑陋.)

让我们继续:"你如何反转float* x大小的缓冲区n?":

std::reverse(x, x + n);
Run Code Online (Sandbox Code Playgroud)

"你如何反转以null结尾的字符串char* s?":

std::reverse(s, s + strlen(s));
Run Code Online (Sandbox Code Playgroud)

"你如何char* s在一个大小的缓冲区中反转一个不一定以空值终止的字符串n?":

std::reverse(s, std::find(s, s + n, '\0'));
Run Code Online (Sandbox Code Playgroud)

请注意,即使这样std::reverse使用swap()也会尽可能地执行:

QList<QList<int> > bigListOfBigLists;
....
std::reverse(std::begin(bigListOfBigLists), std::end(bigListOfBigLists));
Run Code Online (Sandbox Code Playgroud)

还要注意,这些都应该像手写循环一样执行,因为在可能的情况下,编译器会将这些转换为指针算法.此外,您无法干净地编写reverse像C这样的可重用,通用,高性能的函数.

  • 我不知道......那有什么问题?;)ie:这真的是问题的答案吗?如果是这样的话 - 不要忘记这个网站上总共有n00bs可能无法理解您在宣传原始海报的内容......您是否介意解释一下您的答案,以便他们了解您要告诉OP的内容?:) (3认同)

P S*_*ved 5

对于标准库列表,它看起来像这样

std::list<X> result;
std::copy(list.rbegin(), list.rend(), result.back_inserter());
Run Code Online (Sandbox Code Playgroud)

不幸的是,Qt没有返回反向迭代器的rbegin和rend函数(从容器的末尾到它的begnning).您可以编写它们,或者您可以自己编写复制功能 - 反转列表是一个很好的例外.或者您可以注意到QList实际上是一个数组,这使得编写这样一个函数变得微不足道.或者您可以将列表转换为std :: list,并使用rbegin和rend.选择你喜欢的任何东西


Col*_*lin 5

反转QList将是O(n)然而你这样做,因为不保证QList将其数据连续存储在内存中(与QVector不同).您可能会考虑在需要的地方以向后的顺序遍历列表,或者使用类似QStack的东西,它允许您按照添加的相反顺序检索元素.