【问题标题】:Operator for Multiple Points in One Struct一个结构中的多个点的运算符
【发布时间】:2015-10-03 14:24:22
【问题描述】:

我有一个结构,它存储了两个应该可以互换的点。

struct Edge
{
    unsigned short firstIndex;
    unsigned short secondIndex;
    Edge(unsigned short firstIndex, unsigned short secondIndex) :
        firstIndex(firstIndex), secondIndex(secondIndex) {}
};

operator== 方法应该如下(使它们可以互换)

bool operator == (const Edge& e2) const
{
    return 
        first == e2.first && second == e2.second || 
        first == e2.second && second == e2.first;
}

我希望创建一个operator<operator> 方法,以便在std::map 中使用该结构

我尝试了以下方法(使用乘法),但它不起作用,因为在很多情况下不同的边返回相同的值

bool operator < (const Edge& e2) const
{
    return first * second < e2.first * e2.second;
}

我想使用的代码如下:

std::map<Edge, unsigned int> edgePoints;
Edge e1(0, 1);
Edge e2(1, 2);
Edge e3(2, 0);

edgePoints[e1] = 2;
edgePoints[e2] = 0;
edgePoints[e3] = 1;

虽然代码不适用于我的operator&lt; 方法,因为0 * 1 == 2 * 0 所以当我调用edgePoints[e3] 时地图返回2

有谁知道我可以使用的operator&lt;operator&gt; 方法,甚至是其他映射边缘的方法以使用std::map

【问题讨论】:

  • 如果您为 Edge 类型提供哈希函数,您可以使用 unordered_map 代替
  • 这似乎是我想要的,虽然我的哈希函数应该是什么?
  • If first
  • Boost 有一个 hash_combine 函数,你可以使用(或窃取):boost.org/doc/libs/1_55_0/doc/html/hash/combine.html
  • 我不想使用 boost。

标签: c++ algorithm struct operator-keyword


【解决方案1】:

我会以这样一种方式存储边缘的索引,即较小的索引始终是第一个索引。看起来内部表示与您的应用程序无关。地图不需要operator==。这是示例结构:

struct Edge
{
    typedef unsigned short Idx; // prefer strong typedef cf boost
    Edge(Idx a, Idx b) 
    :
        firstIndex(std::min(a, b)),
        secondIndex(std::max(a, b))
    {}

    Idx firstIndex;
    Idx secondIndex;

    bool operator<(Edge const & other)
    {
        if (firstIndex != other.firstIndex) 
            return firstIndex < other.firstIndex;
        return secondIndex < other.secondIndex;
    }
}; // Edge

如果你想让你的实现更好,一些小建议:

  • 首选std::array&lt;unsigned short, 2&gt;,而不是单独的变量firstIndexsecondIndex。这样做允许迭代索引。
  • 如果您使用的是array,您可以使用std::lexicographical_compare 缩短operator&lt;

【讨论】:

  • 没有编译器生成的operator==。无论如何,std::map 不需要它。
  • 旁注:std::tie(firstIndex, secondIndex)
  • @m8mble 这确实是一个更好的答案。
【解决方案2】:

考虑将它们作为排序对进行比较。

bool operator < (const Edge& e2) const
{
    if (min(first, second) != min(e2.first, e2.second))
        return min(first, second) < min(e2.first, e2.second);
    return max(first, second) < max(e2.first, e2.second);
}

编辑:当然,将最小值和最大值保存为局部变量可以写得更好,但这个想法应该很清楚。

编辑:其他答案中的想法更好:强制你的结构总是先小于第二,它会消除所有的最小值和最大值,并使比较像地狱一样快速运行)

【讨论】:

  • 这似乎适用于我所做的测试。在我将其标记为正确之前,让我再做一些测试。
  • 这个答案比我提供的要慢。我认为这对于小型测试并不重要。但我不会将它用于大型图形实例。
  • @m8mble 但如果边从 A 到 B 或 B 到 A(可能需要),它会保留信息
  • 它保留了被描述为“可互换”的信息。如果认为我们在这里处理的是无向边。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-01-24
  • 1970-01-01
  • 2022-01-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多