C++ 比较两对整数的最有效方法

C++ 比较两对整数的最有效方法,c++,c++11,C++,C++11,一个类包含两个整数;这个类有两个实例。我想对它们进行比较,以确保这两个实例包含相同的两个数字(它们的顺序无关紧要) 我可以这样做: bool operator==(const Edge &e, const Edge &f) { return ((e.p1 == f.p1) || (e.p1 == f.p2)) && ((e.p2 == f.p1) || (e.p2 == f.p2)); } 这是最好的方式吗?会有很多这样的比较,所以我想确保我做出了最有效

一个类包含两个整数;这个类有两个实例。我想对它们进行比较,以确保这两个实例包含相同的两个数字(它们的顺序无关紧要)

我可以这样做:

bool operator==(const Edge &e, const Edge &f) {
    return ((e.p1 == f.p1) || (e.p1 == f.p2)) && ((e.p2 == f.p1) || (e.p2 == f.p2));
}

这是最好的方式吗?会有很多这样的比较,所以我想确保我做出了最有效的选择。顺便说一句,操作符主要由
std::unordered_set
类使用,以防这些信息起作用

我觉得你的逻辑有点混乱。。。如果我理解正确,给定对(a,b)和(x,y),你想检查(a,b)==s(x,y),对于一些置换

bool operator==(const Edge &e, const Edge &f) {
    return ((e.p1 == f.p1) && (e.p2 == f.p2)) ||
           ((e.p2 == f.p1) && (e.p1 == f.p2));
}

至于表现。。。这里没有什么可优化的。如果你的程序很慢,就去别的地方看看。

这对两个人来说都可以。然而,对于更多的人来说,它显然变得非常丑陋非常快。事实上,您需要执行
n比较,如果以“朴素”的方式执行此操作,则在有
n
变量时进行检查

更简单的方法如下所示:

static constexpr Edge::number()
{
    return <number_of_values>;
}

bool operator==(const Edge& e, const Edge& f)
{
    constexpr size = Edge::number();
    std::array<int, size> earr = {{e.p1, e.p2, ..., e.pn}};
    std::array<int, size> farr = {{f.p1, f.p2, ..., f.pn}};
    return std::is_permutation(earr.begin(), earr.end(), farr.begin());
}
static constexpr Edge::number()
{
返回;
}
布尔运算符==(常数边和e、常数边和f)
{
constexpr size=Edge::number();
数组耳环={{e.p1,e.p2,…,e.pn};
数组farr={{f.p1,f.p2,…,f.pn};
return std::is_置换(arr.begin()、arr.end()、farr.begin());
}
如果始终为2,您可以简单地将其写成:

bool operator==(const Edge& e, const Edge& f)
{
    std::array<int, 2> earr = {{e.p1, e.p2};
    std::array<int, 2> farr = {{f.p1, f.p2}};
    return std::is_permutation(earr.begin(), earr.end(), farr.begin());
}
bool运算符==(常数边&e,常数边&f)
{
数组耳环={e.p1,e.p2};
数组farr={{f.p1,f.p2};
return std::is_置换(arr.begin()、arr.end()、farr.begin());
}
测试无序相等性与测试一个序列是否是另一个序列的置换相同


编辑:这对我来说应该是显而易见的,可以通过检查排序序列是否相等来测试。将
std::is_permution
替换为
std::sort
std::equal
,这将是
O(n log n)
而不是
O(n^2)

根据我对您问题的理解,我建议您采用以下解决方案:

只需在类中添加函数,如下所示:

bool isExist(int point)
{
  if(this.p1==point || this.p2==point)
    return true;
  else
   return false;
}
您可以通过调用此函数应用您的逻辑


如果我错了,请纠正我…

这可能不是最快的,它需要C++11。但它又好又短:

bool operator==(const Edge& e, const Edge& f) {
  return std::minmax(e.p1, e.p2) == std::minmax(f.p1, f.p2);
}

它还建议了一个优化(我通常使用):保持
p1
p2
的顺序,这样就不需要每次调用
minmax
。这样你就有了一个最佳的解决方案。

忘记优化。我认为你的逻辑是错误的。这两个条件可能是正确的:(e.p1==f.p1)(e.p2==f.p1)如果不考虑f.p2,你的函数将返回true。如果不知道用例的详细信息,就无法优化此函数。例如,是否有比创建边更多的比较?我们是否可以向边结构添加额外的数据,或者内存是否有溢价?这些整数是否在生命周期内不可变类实例,或者它们可以更改吗?(但很可能,优化它没有意义。)如果你担心这个操作会被多次执行,而且数字的顺序并不重要,那么你最好确保p1总是等于或小于p2,然后你可以直接比较它们
e.p1==f.p1&&e.p2==f.p2
@SteveWellens好主意!我不敢相信我错过了:(@Arthur有趣的建议!对于大型集合,使用
std::sort()
,它是O(N log N),而不是
std::is_permutation()
,它是O(N^2)。为什么不对它们进行排序呢?即使你必须将它们复制到另一个结构中,它仍然比排列更快。你的解决方案是否适用于两个值的情况(如我所需)比我的解决方案快多少(尽管有正确的逻辑,这要感谢Steve和Dietrich)?涉及STL对象不是一种过分的杀伤力吗?嗯,好的一点。我只是查了一下
is\u permutation
。实际上没有意识到它是
O(N^2)
@deepak不,它比较慢,因为它构造了中间对象。只有两个对象,您的(更正的)逻辑就可以了。更重要的是“如果它扩展到3个或更多,那么这种方式将非常、更可读”。虽然这很好,但一次只比较一个元素。要将边缘的两个点对齐,我必须调用两次。“这里没有什么需要优化的。如果你的程序太慢,就去别的地方看看。”"-并非如此-正如rici所说,可能值得探索预先排序的值;然后,例如,将两个Int32打包成一个带有int64的联合体-允许单个
e.as_int64==f.as_int64
,在避免短路计算的情况下,这很容易比上面的代码快一个数量级。当然,这可能是在整个项目的背景下,这可能是重要的,但问题是“许多这样的比较”“想要……最有效的选择”-如果忽略这一点,回答就没有意义。