[转] C++11 sort, vector, lambda——vector 自定义排序

前言

std::sort大法好!很多情况下,快速排序是排序的不二选择。#include < algorithm >中的 sort( ),完美的实现了这个快速排序。

std::vector大法好!很多情况下,vector是顺序容器的不二选择。#include < vector >就可以使用了。

lambda大法好!这个东西来源自“函数式编程“的思想,现在已经影响了几乎所有面向对象语言了:C++11,Java8都已经支持lambda。C#, python 等语言更早就开始支持lambda了。(我理解的lambda就是一个“匿名函数”,不知道准不准确,但是貌似可以把我所看见的代码“解释得通了”)

那么把sort( ) 和 vector,lambda相结合,可以擦出什么火花呢?


Talk is cheap, show me the code~

#include 
#include 
#include 
#include 
#include 
using namespace std;

class Foo
{
public:
    int a;
    int b;

    Foo():a(0), b(0){}
    ~Foo(){}

    Foo(int a, int b)
    {
        this->a = a;
        this->b = b;
    }

    // 规定对象排序的算法:先按照 a 从小到大排序;如果 a 相等,则按照 b 从小到大排序
    bool operator<(const Foo &bar)
    {
        if (this->a < bar.a)
        {
            return true;
        }
        else if (this->a == bar.a)
        {
            return this->b < bar.b;
        }
        return false;
    }

    // 规定对象排序的算法:先按照 a 从大到小排序;如果 a 相等,则按照 b 从大到小排序
    bool static decrease(const Foo &foo1, const Foo &foo2)
    {
        if (foo1.a > foo2.a)
        {
            return true;
        }
        else if (foo1.a == foo2.a)
        {
            return foo1.b > foo2.b;
        }
        return false;
    }

    friend inline ostream & operator<<(ostream &out, Foo &foo)
    {
        out << foo.a << " " << foo.b << endl;
        return out;
    }
};

int main()
{
    unsigned seed = chrono::system_clock::now().time_since_epoch().count();
    minstd_rand0 generator(seed);    // minstd_rand0 is a standard linear_congruential_engine

    vector myVec(10, Foo());

    for (Foo &foo : myVec)           // 随机赋值
    {
        foo.a = generator() % 5;
        foo.b = generator() % 5;
        cout << foo;
    }

    sort(myVec.begin(), myVec.end()); // 排序一:默认从小到大,调用 operator <
    cout << endl << "after sorting using operator <" << endl;
    for (Foo &foo : myVec)
    {
        cout << foo;
    }

    sort(myVec.begin(), myVec.end(), Foo::decrease);  // 排序二:按照 Foo::decrease 的规则从大到小排序
    cout << endl << "after sorting using Foo::decrease()" << endl;
    for (Foo &foo : myVec)
    {
        cout << foo;
    }

    sort(myVec.begin(), myVec.end(), [](const Foo &foo1, const Foo &foo2)
    {                                                 // 排序三:使用 lambda 的方式进行排序,排序的方法和 Foo::decrease 一样
        if (foo1.a > foo2.a)
        {
            return true;
        }
        else if (foo1.a == foo2.a)
        {
            return foo1.b > foo2.b;
        }
        return false;
    }   );
    cout << endl << "after sorting using lambda" << endl;
    for (Foo &foo : myVec)
    {
        cout << foo;
    }

    system("pause");
    return 0;
}


运行结果

从控制台”黑框框“复制过来的。(如果你不知道那个黑框框还可以复制的话,我告诉你:可以复制的!)

4 4
2 0
0 1
1 4
4 3
3 2
1 4
0 3
2 0
2 1

after sorting using operator <
0 1
0 3
1 4
1 4
2 0
2 0
2 1
3 2
4 3
4 4

after sorting using Foo::decrease()
4 4
4 3
3 2
2 1
2 0
2 0
1 4
1 4
0 3
0 1

after sorting using lambda
4 4
4 3
3 2
2 1
2 0
2 0
1 4
1 4
0 3
0 1
请按任意键继续. . .


代码分析

sort其实有3个参数,前两个参数不用说,第三个参数是一个“函数名字”,默认等于operator<

vector中的元素如果是对象(而不是int, double之类的)的话,有以下3种方法进行自定义排序:

  1. 对operator<进行重载,这样sort()依然只用写两个参数
  2. 专门一个排序规则的函数,写法参照上述的代码。这个函数可以是静态方法,即类方法;也可以是全局的方法(我认为静态方法更加,毕竟这是专门属于某一个类的排序规则)。然后在使用sort()的时候,第三个参数写上函数名字即可
  3. 使用lambda,写法参照上述代码。如果比较规则的代码行数较少的话,可以使用lambda。我个人感觉lambda里面的函数体如果比较长的话,看上去“怪怪”的,可读性比较差。据说lambda真正有用的地方在于多线程,用在std::thread, std::future等里面

你可能感兴趣的:(C++基础,c++,算法,排序算法)