2013-08-23 44 views
2

讓我們假設我們有一個:如何在線性時間內進行穩定的二進制值排序?

class Widget; 
std::vector<Widget>; 

而且我們有一個函數:

bool belongsToLeft(Widget w); 

我想按照這個謂詞的容器進行排序。到目前爲止,我通過這個算法。它從範圍的兩端進展。一旦找到一對同時屬於另一端的值,它就會交換它們。

template <typename TIterator, typename TPredicate> 
TIterator separate(TIterator begin, TIterator end, TPredicate belongsLeft) 
{ 
    while (true) 
    { 
     while (begin != end && belongsLeft(*begin)) 
      ++begin; 
     while (begin != end && !belongsLeft(*end)) 
      --end; 
     if (begin == end) 
      return begin; 
     std::swap(*begin, *end); 
    } 
} 

的問題是,這種算法並不穩定:

#include <vector> 
#include <iostream> 

int main() 
{ 
    std::vector<int> numbers = {6, 5, 4, 3, 2, 1}; 
    separate(numbers.begin(), numbers.end(), [](int x){return x%2 == 0;}); 

    for (int x : numbers) 
     std::cout << x << std::endl; 
    return 0; 
} 

輸出:

6 
2 
4 
3 
5 
1 

如何修改這個算法是穩定的,並保持線性的時間?

+0

你爲什麼不使用'的std :: stable_sort()'? – piwi

+0

我想利用這樣一個事實,即只有兩個可能的值,以便算法以線性時間運行。 –

+0

只有當'* end> * begin'不能被保證時纔會進行交換。將謂詞放在開始/結束處。 –

回答

8

使用std::stable_partition與謂詞來單獨numbers成兩個部分,線性複雜

#include <algorithm> 

std::stable_partition(
    numbers.begin(), numbers.end(), 
    [](int x) { return x % 2 == 0; } // or belongsToLeft() 
); 
+0

哇!謝謝!標準庫永遠不會令我驚歎! –

+2

如果您知道您的手寫算法需要做什麼,請考慮一個合適的名稱,然後使用同義詞庫查找類似於標準庫算法E.g.的替代名稱。 http://thesaurus.com/browse/separate並顯示分區爲條目 – TemplateRex

相關問題