首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >向量的排序

向量的排序
EN

Stack Overflow用户
提问于 2013-11-04 14:41:42
回答 2查看 132关注 0票数 1

总之,我有以下问题。

考虑下面的类:

代码语言:javascript
复制
class A
{
public:
.....
private:
    int m_a, m_b;
    double m_c;
};

我有一个这个类的对象的向量。

此向量在网格中显示给用户,用户可以单击列标题对网格(向量)的元素进行排序。问题来自于用户可以按住CTRL键并单击行标题,在这种情况下,网格(向量)应该按2列(类的成员)排序。

我可以写一个简单的排序类,它将基于一个成员(列)进行排序,但我真的不知道如何选择第二个排序列并进行排序。

有人能帮帮忙吗?

EN

回答 2

Stack Overflow用户

发布于 2013-11-04 14:52:23

要做到这一点,最简单的方法是依次按每列排序,从最不重要的列开始。因此,如果用户选择按a then b then c排序,则首先按c排序,然后按b排序,最后按a排序。最后两个排序(ba)必须是一个稳定的排序(std::stable_sort),它保留了其他相同元素的现有顺序。

另一种方法是使用自定义的比较函数,这种方法几乎肯定更快,但可能不实用。但是想出一个自定义的比较函数并不容易。在您提供的示例中,只有三个变量,那么只有六个可能的比较函数( a、b、c的每个顺序对应一个--您可以将未指定的列放在末尾),但在一般情况下,您最终会有太多的可能性需要枚举。您可以使用复杂的switch语句集合来编写通用比较器,但该比较器的开销很可能不仅仅是对向量进行多次排序。

票数 2
EN

Stack Overflow用户

发布于 2013-11-04 17:33:29

既然您要求提供动态创建适当比较函数的代码...

免责声明:就性能而言,以下代码可能无法与使用稳定的排序算法(如std::stable_sort )多次对向量进行排序相比。它只是用来说明一个想法。以下代码是使用C++11功能编写的,您可能还无法使用这些功能。但是,可以使用例如boostC++03中轻松地重写它。

让我们假设每个成员变量都有类A和一些getter函数:

代码语言:javascript
复制
class A
{
    public:
        float getA() const;
        int getB() const;
        // and so on.
};

我们将定义返回-1的函数,如果A的一个实例小于另一个实例,如果它们相等,则返回0,否则返回1。这些函数可以更容易地组合在一起。

代码语言:javascript
复制
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

代码语言:javascript
复制
std::vector<comparator> comparators = {
    make_comperator( &A::getA ), make_comparator( &A::getB )
};

我们可以很容易地组合比较器函数:

代码语言:javascript
复制
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-like函数器:

代码语言:javascript
复制
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;
    };
}

在第一列之后排序,在第二列之后排序:

代码语言:javascript
复制
std::sort( instances.begin(), instances.end(),
            to_less( make_comparator( comparators, { 0, 1 } ) ) );
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/19762822

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档