1. 程式人生 > >C++11 sort, vector, lambda——vector 自定義排序

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 <iostream>
#include <chrono>
#include <random>
#include <vector>
#include <algorithm>
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<Foo> 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等裡面