2013-11-04 110 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 })));