📜  使用比较器匿名函数 c++ 进行排序(1)

📅  最后修改于: 2023-12-03 15:36:40.363000             🧑  作者: Mango

使用比较器匿名函数 C++ 进行排序

在 C++ 中,我们可以使用比较器匿名函数进行排序。比较器匿名函数是一种回调函数,用于定义如何比较两个元素。这种回调函数非常有用,因为它可以在不修改排序算法本身的情况下,定义任何自定义排序规则。

用于排序的基本函数

在 C++ 中,我们可以使用 std::sort 函数对任何 STL 容器进行排序。以下是 std::sort 函数的定义:

template <typename RandomAccessIterator>
void sort(RandomAccessIterator first, RandomAccessIterator last);

该函数接受两个迭代器作为参数。以下是使用 std::sort 函数对 C++ 数组进行排序的示例代码:

#include <algorithm>
#include <iostream>
using namespace std;

int main() {
    int arr[] = {3, 2, 1};
    sort(begin(arr), end(arr));
    for (int x : arr) {
        cout << x << ' ';
    }
    return 0;
}

该代码将按顺序输出 1 2 3

简单示例

假设我们要对以下字符串向量进行排序:

#include <algorithm>
#include <iostream>
#include <string>
#include <vector>
using namespace std;

int main() {
    vector<string> vec = {"apple", "banana", "cherry", "date", "elderberry"};
    sort(vec.begin(), vec.end());
    for (const string& s : vec) {
        cout << s << ' ';
    }
    return 0;
}

该代码将按字典序从 A 到 Z 输出所有元素:apple banana cherry date elderberry

我们也可以使用比较器匿名函数来定义我们自己的排序规则:

#include <algorithm>
#include <iostream>
#include <string>
#include <vector>
using namespace std;

int main() {
    vector<string> vec = {"apple", "banana", "cherry", "date", "elderberry"};
    sort(vec.begin(), vec.end(), [](const string& s1, const string& s2) {
        return s1.size() < s2.size();
    });
    for (const string& s : vec) {
        cout << s << ' ';
    }
    return 0;
}

该代码将按字符串长度从小到大输出所有元素:date apple banana cherry elderberry

比较器匿名函数通常使用 Lambda 表达式来定义,该表达式的形式如下:

[capture list] (params list) mutable exception attribute -> return type { function body }

其中:

  • capture list:捕获语句,用于在 Lambda 表达式中访问位于其作用域外部的变量。
  • params list:参数列表,与普通函数定义类似,但可以省略参数类型。
  • mutable:可选的 mutable 修饰符,用于修饰 Lambda 表达式中的局部变量,使其可变。
  • exception attribute:C++11 引入的异常属性,用于定义 Lambda 表达式可能抛出的异常类型。
  • return type:返回类型,与普通函数定义类似,但可以省略。
  • function body:函数体,与普通函数定义类似,但可以省略大括号。
比较器的基本用法

比较器是一种函数,被用于定义两个元素之间的排序关系。比较器应该满足严格弱排序关系,即具有以下特点:

  • 反自反性:对于所有元素 a,比较器应返回 false。
  • 反对称性:对于所有元素 a 和 b,若 a 比 b 大,那么 b 不得比 a 大。
  • 传递性:对于所有元素 a、b 和 c,若 a 比 b 大,b 比 c 大,那么 a 也必须比 c 大。

一个简单的比较器的实现示例如下:

bool mycmp(const int& a, const int& b)
{
    return a > b;
}

该函数返回 a 是否比 b 大。

比较器通常用于 STL 容器的排序算法,例如 sortunique

例如,我们可以将任何 STL 容器按由大到小的顺序排序:

#include <algorithm>
#include <iostream>
#include <vector>
using namespace std;

int main() {
    vector<int> vec = {3, 2, 1};
    sort(vec.begin(), vec.end(), [](const int& a, const int& b) {
        return a > b;
    });
    for (int x : vec) {
        cout << x << ' ';
    }
    return 0;
}

该代码将输出 3 2 1

我们也可以在 unique 函数中使用比较器,用于移除容器中的相邻重复元素:

vector<int> vec = {1, 1, 2, 2, 3, 3, 3};
auto iter = unique(vec.begin(), vec.end(), [](const int& a, const int& b) {
    return a == b;
});
vec.erase(iter, vec.end());
for (int x : vec) {
    cout << x << ' ';
}

该代码将输出 1 2 3