【问题标题】:c++ set_intersection compare functionc++ set_intersection比较函数
【发布时间】:2015-07-24 16:21:37
【问题描述】:

在使用<algorithm> 中的函数时,通常有一个额外的参数来自定义比较。但是我不太明白关于论点的描述(Documentation of set_intersection)。

接受两个类型的参数的二进制函数 输入迭代器,并返回一个可转换为 bool 的值。价值 返回的表示第一个参数是否被认为是去 在它定义的特定严格弱排序中的第二个之前。这 函数不得修改其任何参数。这可以是一个 函数指针或函数对象。

它描述了函数应该返回两个参数的顺序。但是在匹配函数中呢,例如:

#include <algorithm>
#include <iostream>

using namespace std;

void print (const char* name, int* start, int* end) {
    cout << name << ": ";
    while (start < end) 
        cout << *start++ << ", ";
    cout << endl;
}

bool func1 (int a, int b) { return a==b; }
bool func2 (int a, int b) { return a+b == 8; }

int main() {
  int set1[6] = {0, 1, 2, 4, 2, 4};
  int set2[6] = {1, 2, 3, 4, 5, 6};

  int set_without_comp[6];
  int* end_wo = set_intersection(set1, set1+6, set2, set2+6, set_without_comp);
  print ("set_without_comp", set_without_comp, end_wo);

  int set_with_comp1[6];
  int *end_w1 = set_intersection(set1, set1+6, set2, set2+6, set_with_comp1, func1);
  print ("set_with_comp1", set_with_comp1, end_w1);

  int set_with_comp2[6];
  int *end_w2 = set_intersection(set1, set1+6, set2, set2+6, set_with_comp2, func2);
  print ("set_with_comp2", set_with_comp2, end_w2);
}

我们得到输出:

set_without_comp: 1, 2, 4, 
set_with_comp1: 0, 1, 2, 2, 4, // Expect 1, 2, 4, 
set_with_comp2: 0, 1, 2, 2, 4, // Expect 2, 4, (maybe 6)

如何解释结果,在使用&lt;algorithm&gt;函数时编写比较函数的正确方法是什么,以及如何编写一个可以给我预期结果的函数?

【问题讨论】:

  • 它接受std::less&lt;T&gt; 之类的参数——基本上是operator&lt;,就像所有其他对排序进行操作的算法一样。
  • @Konrad Rudolph 但有时我不需要顺序,我只需要匹配元素,就像我在帖子中写的那样,set_intersection 应该在两者中找到匹配的元素集,而不是订单。
  • 在 C++ 标准算法中,所有这些都是通过排序来表达的(因为这有助于有效地实现集合操作)。如果两个元素都不大于另一个,则两个元素相等。
  • 不确定,但我认为您应该提供总订单功能。
  • 如果您认为您的问题已得到解决,请选择一个答案作为解决方案。

标签: c++ algorithm comparison


【解决方案1】:

std::set_intersection 需要一个函数来关联两个元素,就像它们在集合中的存储方式一样。它不是一个函数来描述哪些元素是相同的,因为该函数在内部完成了这项工作。

因此,在您的示例中,set1 不是正确的集合,因为它没有按顺序(例如升序)。如果它是有序的,您可以在std::set_intersection 中使用相同的订购功能。例如:

int set1[6] = {0, 1, 2, 2, 2, 4}; // in order (<)

bool func1 (int a, int b) { return a < b; } // the only valid function

当您处理没有隐式顺序的复杂对象时,明确说明您想要使用的顺序函数的能力非常有用。例如:

struct Person {
  std::string name;
  int age;
};

bool ascendingAge(const Person& guy1, const Person& guy2) {
  return guy1.age < guy2.age;
}

...

std::intersection(..., ..., ascendingAge);

【讨论】:

  • 我把set1和set2改成如下:int set1[6] = {0, 1, 2, 2, 4, 4}; int set2[6] = {1, 2, 3, 4, 5, 6};,按一定的顺序,比较函数为:bool func1 (int a, int b) { return a&gt;b; } bool func2 (int a, int b) { return a&lt;b; },用func1的结果什么都没有,用的func21, 2, 4,
  • 所以您的意思是该函数仅用于指示集合保持的顺序,而不是比较两个集合中的元素。这样做的目的是为了降低复杂性?
  • 是的,这是为了表明集合的顺序。这样做的目的是增加管理非平凡类的灵活性。
  • 但对于某些情况,例如std::search,该函数似乎比较两个值。真的很困惑std::set_intersection不是比较而是排序。
  • @PanwenWang 原因是std::search 算法的工作方式不同。不同的算法有不同的要求。碰巧一个有效的集合交集算法要求元素通过某种排序是可比较的,而在无序列表中搜索则没有这样的要求。这只是关于算法的基本事实。
【解决方案2】:

bool func1 (int a, int b) { return a==b; }bool func2 (int a, int b) { return a+b == 8; } 都没有回答 a 是否必须在 b 之前。在传递比较器等函数后得到的结果不能被“解释”:它们是依赖于实现的废话,因为 STL 被错误地使用了——它需要一个函数来说明 a 是否必须在 b 之前,但得到一个函数做别的事情。 有效比较器的一些示例如下:

bool func1 (int a, int b) { return a<b; }
bool func2 (int a, int b) { return a>b; }

【讨论】:

    【解决方案3】:

    比较功能提供排序顺序。默认为 std::less,这里为 how to write such functions。如果要保持整数的升序排序,保持默认即可,不要指定任何比较函数。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-03-24
      • 1970-01-01
      • 2013-01-31
      • 2016-05-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多