2009-08-27 153 views
24

我看到qCopyqCopybackward,但似乎都沒有讓我按相反順序製作副本。 qCopybackward只會以相反的順序複製它,但保持darn元素的順序相同!我想要做的就是以相反的順序返回列表的副本。有是一個功能,對嗎?如何反轉QList?

+7

+1表示必須有一個函數爲它,完全同意。 PS的開源,我們都可以去建立它並提交它。 – Thirler

回答

26

如果你不喜歡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年7月21日:顯然(或者沒有),如果你想要一個班輪(和人似乎更喜歡,看着不同的答案五年後相對upvotes),你有一個非constlist上述崩塌到

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

但我猜指數擺弄STU ff對於工作安全來說更好:)

+0

只要STL庫在QList上工作,沒關係。我只是不想使用STL列表。我想我以前試過,但我不知道back_inserter,所以也許這就是我做錯了。 – mpen

+0

是的,所有Qt容器都是STL'序列'(儘管由於缺少功能它們可能不符合更高級別的概念)。 –

+0

'QList'與'std :: list'無關。前者是一個有效的'push_front()'(有點像'std :: deque'和'std :: vector'組合在一起)的矢量,當sizeof(T)> sizeof(void *)'時有趣的屬性,後者是一個雙向鏈表(Qt中的'QLinkedList')。去圖:/ –

5

標準庫列表它看起來像這樣

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

不幸的是,Qt不具有rbegin來咬函數返回反向迭代器(即從容器的結束到其begnning的那些) 。你可以寫他們,或者你可以自己寫複製功能 - 反轉列表是一個不錯的excersize。或者你可以注意到QList實際上是一個數組,這使得編寫這樣一個函數變得微不足道。或者你可以將列表轉換爲std :: list,並使用rbegin和rebnd。選擇你喜歡的任何。

+0

那麼,我寫了我自己的功能,但這讓我非常困擾。他們怎麼會把這件事留下?我確實在尋找rbegin和rend,但他們似乎也拋棄了這些(嘀咕一些關於雙向迭代器的東西?),儘管他們從STL實現了其他一切。 – mpen

+0

FTR:'QList'有從Qt 5.6開始的'rbegin()'/'rend()'。 –

5

反轉QList將會是O(n),但是你這樣做,因爲QList不能保證它的數據連續存儲在內存中(與QVector不同)。你可能會考慮只是在需要的地方以倒序的順序遍歷列表,或者使用類似QStack的東西,它可以讓你按照與添加順序相反的順序來獲取元素。

+0

好吧,我並不關心運行時間,只是認爲一個函數應該已經存在,這樣我就不必自己寫了。儘管我認爲應該是'n/2',而不是'/ 2'在Big-O中很重要。 – mpen

+0

+1「倒退」:-)爲什麼要反向如果你使用for-loop呢? (雖然我不習慣'我 - ' - 循環。) –

+0

呃?數據存儲與什麼有關?反轉*任何*列表類結構總是*將會是O(N),除非它專門針對這種情況進行了優化,並且執行了一些巧妙的索引間接。 (我懷疑你會碰到任何這樣的實現。) 理論上,QList可以比QVector更快地翻轉,因爲項目是間接存儲的,只有指針列表需要被顛倒(即不需要被複制基礎項目)。不過,我不知道Qt公開API來實現這一點。 – Matthew

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(); 
} 
18

與單線反轉您的QList:

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

+0

不錯!謝謝... – mpen

+0

偉大的一班。 –

+0

抱歉挖,但這不起作用! –

7

@Marc耶特斯的回答是好。如果你想獲得一個額外的30%的性能提升,你可以在他的一行改爲:用的QList

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

其中一臺ThinkPad W520 1000萬個QTimers我得到這些數字:

  • 倒車列表棧溢出了194毫秒
  • 倒車列表堆棧溢出,最大和大小了136毫秒

升壓是

  • 表達的結果(則爲list.size()/ 2)初始化環路而不是後的每一步
  • 在交換表達則爲list.size()()被調用時被只計算一次只有一次初始化時的循​​環,而不是之後的每一步
7

[由原來的改寫]

目前尚不清楚,如果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)); 
} 

但它變得更好:因爲Iterator接口是相同的爲C指針語法,因爲C++ 11加入的遊離std::begin()std::end功能,你可以做這些:

「你怎麼扭轉數組float x[10]?」:

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); 

「你怎麼扭轉空終止字符串char* s?」:

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

「你怎麼在尺寸n的緩衝扭轉一個不必然無效結尾的字符串char* s?」:

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.

+2

我不知道......那有什麼不對? ;)ie:這真的是這個問題的答案嗎?如果是的話 - 不要忘記這個網站上有n00bs的總數,可能不知道你在說什麼原始海報...你會介意解釋你的答案,讓他們明白你想告訴OP ? :) –