2013-11-04 157 views
1

ALL, 我有以下問題。排序的矢量

考慮下面的類:

class A 
{ 
public: 
..... 
private: 
    int m_a, m_b; 
    double m_c; 
}; 

,我有這個類的對象的向量。

該向量在網格中呈現給用戶,並且他可以單擊列標題對網格(向量)的元素進行排序。 問題出在用戶可以按住CTRL鍵並單擊行標題的情況,在這種情況下,網格(矢量)應該按2列(類的成員)排序。

我可以編寫一個簡單的排序器類,它將根據一個成員(列)進行排序,但我真的不知道如何拾取第二個排序列並進行排序。

有人可以幫忙嗎?

+1

首先,你可能想了解['標準:: sort']啓動(http://en.cppreference.com/w/cpp/algorithm /分類)。如果你的編譯器足夠新,可以閱讀[lambda函數](http://en.cppreference.com/w/cpp/language/lambda)。 –

+0

輕鬆完成多種方法。你知道函數或lambda是什麼嗎?你需要一種你想要的每種排序方法,然後用它作爲['std :: sort']的比較器(http://en.cppreference.com/w/cpp/algorithm/sort)。有關如何使用默認排序以及自定義排序(您需要)的示例位於提供的「std :: sort」鏈接中。 – WhozCraig

+0

至於對您的問題更具體的幫助,一個非常簡單的解決方案是有七個不同的排序功能,一個用於三個變量的每個組合。 –

回答

2

執行此操作的最簡單方法是依次按每列進行排序,從最不重要的列開始。因此,如果用戶按a then b then c選擇排序,那麼您首先按c排序,然後按b排序,最後按a排序。最後兩種(ba)必須是穩定排序std::stable_sort),它保留了現有順序,否則就是相等的元素。

做這件事的另一種方式 - 這幾乎肯定是更快但可能不實際 - 是使用自定義比較功能。但想出自定義比較函數並不容易。在你提供的例子中,只有三個變量,那麼只有六個可能的比較函數(a,b,c的每個排序都有一個 - 你可以把未指定的列放在最後),但在一般情況下,你最後列舉了太多的可能性。您可以使用一組複雜的開關語句來編寫一個通用比較器,但該比較器的開銷可能不僅僅是多次對向量進行排序。

+0

不幸的是這個類RICI含有大量的超過3名成員 - 。64確切所以爲了滿足這些要求,我將需要2^64的組合,我覺得寫這麼多的東西是不可行的,任何更簡單的解決方案,謝謝 – Igor

+0

@igor:是的,我在第一段中提到的方式(不是2^64,它是64 !,這個更大) – rici

+0

@Igor除了rici提出的解決方案之外,你可能想要保存一個函數指針數組(例如成員函數),並從這些函數中組裝你的比較函數,這是一個完整的比擁有一個「複雜的收藏家」容易得多切換語句的切換「,但基本上是做同樣的事情。如果表現是您的主要擔憂之一,我會考慮實施這兩種方法。 –

1

既然你要求提供一個動態創建一個合適的比較函數代碼...

免責聲明:下面的代碼可能是沒有可比性與像std::stable_sort穩定的排序算法多次排序向量在性能方面。它只是用來說明一個想法。以下代碼是使用C++11功能編寫的,這些功能可能尚未提供給您。但是,可以使用例如boost輕鬆地將其重寫爲C++03

讓我們假設你有你的A類和每一個成員變量一些getter函數:

class A 
{ 
    public: 
     float getA() const; 
     int getB() const; 
     // and so on. 
}; 

我們要定義將要返回-1功能,如果A一個實例是其中一個比另一個更小,0,如果它們相等,則爲1。這些功能可以更容易地組合。現在

using comparator = std::function<int (const A&, const A&)>; 

template <class T> 
comparator 
make_comparator(T (A::*f)() const) 
{ 
    return [f](const A& lhs, const A& rhs) -> int { 
     if((lhs.*f)() < (rhs.*f)()) 
      return -1; 
     else if((lhs.*f)() == (rhs.*f)()) 
      return 0; 
     else 
      return 1; 
    }; 
} 

,對於每個成員函數,我們定義一個comparator

std::vector<comparator> comparators = { 
    make_comperator(&A::getA), make_comparator(&A::getB) 
}; 

我們可以很容易地結合比較器功能:

comparator 
make_comparator(
    const std::vector<comparator> &comparators, 
    std::deque<unsigned int> indices) 
{ 
    if(indices.empty()) 
    { 
     return [](const A&, const A&) -> int { return 0; }; 
    } 
    unsigned int first = indices.front(); 
    indices.pop_front(); 
    return [first, &comparators, indices](const A& lhs, const A& rhs) -> int { 
     int firstCompared = comparators[first](lhs, rhs); 
     if(firstCompared != 0) 
     { 
      return firstCompared; 
     } 
     else 
     { 
      return make_comparator(comparators, indices)(lhs, rhs); 
     } 
    }; 
} 

這些功能可以被轉換爲less樣函子:

std::function<bool (const A&, const A&)> 
to_less(std::function<int(const A&, const A&)> f) 
{ 
    return [&f](const A& lhs, const A& rhs) -> bool { 
     return f(lhs, rhs) < 0; 
    }; 
} 

後先排序,比第二欄:

std::sort(instances.begin(), instances.end(), 
      to_less(make_comparator(comparators, { 0, 1 })));