C ++ STL sort()函数,二元谓词

时间:2011-09-10 13:47:00

标签: c++ sorting stl

我有一段令我困惑的代码:

   sort(data, data+count, greater<int>() );

它是C标准库中的排序函数。我无法弄清楚第三个论点的含义。我已经读过它被称为二元谓词。这意味着什么?我如何制作自己的谓词呢?

4 个答案:

答案 0 :(得分:25)

第三个参数称为predicate。您可以将谓词视为一个函数,该函数接受多个参数并返回truefalse

因此,例如,这是一个谓词,告诉您整数是否为奇数:

bool isOdd(int n) {
    return n & 1;
}

上面的函数只接受一个参数,因此您可以将其称为 unary 谓词。如果它改为使用两个参数,则称其为 binary 谓词。这是一个二元谓词,告诉你它的第一个参数是否大于第二个:

bool isFirstGreater(int x, int y) {
    return x > y;
}

谓词通常由非常通用的函数使用,以允许函数的调用者通过编写自己的代码来指定函数的行为(当以这种方式使用时,谓词是 {的特殊形式。 {3}} 的)。例如,在必须对整数列表进行排序时,请考虑sort函数。如果我们想要在所有偶数之前对所有奇数进行排序怎么办?每次我们想要更改排序顺序时,我们不希望被强制编写新的排序函数,因为排序的机制(算法)显然与细节无关(我们希望它以什么顺序)排序)。

因此,让我们给sort一个我们自己的谓词,使其反向排序:

// As per the documentation of sort, this needs to return true
// if x "goes before" y. So it ends up sorting in reverse.
bool isLarger(int x, int y) {
    return x > y;
}

现在这将按相反的顺序排序:

sort(data, data+count, isLarger);

这种方法的工作方式是sort在内部比较整数对,以决定哪一个应该先于另一个整数。对于这样一对xy,它通过调用isLarger(x, y)来完成此操作。

所以在这一点上你知道谓词是什么,你可以在哪里使用它,以及如何创建自己的谓词。但greater<int>是什么意思?

callback是一个二元谓词,它告诉它的第一个参数是否大于第二个参数。它也是模板struct ,这意味着它根据参数的类型有许多不同的形式。需要指定此类型,因此greater<int>是类型int模板特化(如果您认为有必要,请阅读有关C ++模板的更多信息)。

因此,如果greater<T>struct,它又如何成为谓词?我们不是说谓词是函数吗?

嗯,greater<T>是一个函数,因为它是 callable :它定义了运算符bool operator()(const T& x, const T& y) const;,这使得写法合法:

std::greater<int> predicate;
bool isGreater = predicate(1, 2); // isGreater == false

可调用的类类型(或struct s,在C ++中几乎相同)的对象称为 greater<T> 仿函数

答案 1 :(得分:6)

有一个名为greater的类模板需要一个类型参数。所以你提供int作为一个。它变为greater<int>并且您创建此类的实例并将其作为第三个参数传递给函数。

这样的对象在C ++中称为function object or simply functor,因为类会重载()运算符。它是一个可调用的实体。它是这样的:

template<typename T>
struct greater
{
   bool operator()(const T &a, const T &b)
   {
      //compare a and b and return either true or false.
      return a > b;
   }
};

如果你创建一个greater<int>的实例,比如说对象是g,那么你可以编写g(100,200)来计算一个布尔值,作为表达式{{1} }调用g(100,200),将operator()作为第一个参数传递,将100作为第二个参数传递,200比较它们并返回operator()true

false

输出:

       std::cout << g(100,200) << std::endl;
       std::cout << g(200,100) << std::endl;

在线演示:http://ideone.com/1HKfC

答案 2 :(得分:2)

二元谓词是接收两个对象(因此是二进制)并返回bool(因此predicate)的任何函数/对象;我们的想法是评估两个对象是否满足某些特定条件 - 在本例中,如果一个对象大于另一个对象。

您可以通过定义具有正确签名的函数来创建谓词

bool IsIntGreater(int First, int Second)
{
    return First>Second;
}

并传递函数的名称作为参数(这将导致传递函数指针),或创建函数对象(仿函数),即重载函数调用运算符的对象因此可以用作功能; std::greater<T>类型是模板函子,在您的代码段中创建了std::greater<int>类型的临时对象并将其传递给std::sort算法。

Functors比函数有几个优点,特别是当它们必须作为参数传递时,请查看here以获取有关此函数的更多信息。

答案 3 :(得分:1)

请参阅http://www.cplusplus.com/reference/algorithm/sort/

中的comp

这是进行比较的功能。