将两个std :: pair(X,Y)视为与std :: pair(Y,X)相同

时间:2013-03-16 01:33:06

标签: c++

这是我的代码

typedef std::pair<unsigned long, unsigned long> link;

std::map<link, double> container;

我要做的是计算从X到Y的距离,并将其作为container.insert存储在容器中(std :: make_pair(link,distance)); 并说现在我必须计算从Y到X的距离,而不是重做整个计算,从容器中获取存储的值,即..,链接和距离。

我目前的实施仅适用于(X,Y)

std::map<link, double>::iterator It = container.begin();
std::pair<unsigned long, unsigned long> k = link(X,Y);
It = container.find(K);
if(It != container.end()) {   distance = It->second; } 
else { /* distance = /* complex calc */ container.insert(std::make_pair(k,distance)); }

如何使其一般化,以便将链接(X,Y)和链接(Y,X)视为相同?

3 个答案:

答案 0 :(得分:3)

为地图使用不同的键比较器,如下所示:

bool link_compare(link lhs, link rhs) // note: parameters taken by value
{
    if (lhs.first > lhs.second) std::swap(lhs.first,lhs.second);
    if (rhs.first > rhs.second) std::swap(rhs.first,rhs.second);
    return lhs < rhs;
}

std::map<link, double, bool(*)(link,link)> container(link_compare);

我认为,您应该考虑将link作为单独的类,使用特定于其的数据成员名称,而不是通用的firstsecond。在我看来,std::pair是一个快速修复,用于在必须将它们作为单个对象传递时包含不相关的数据。你所拥有的显然是非常相关的数据。仅仅因为std::pair碰巧能够容纳正确的数据成员,并不意味着你应该使用它。

答案 1 :(得分:1)

始终保持X和Y排序,即。插入,搜索,删除时,首先对该对进行排序,然后将该排序对与地图方法一起使用。

或者,创建自己的link构造函数帮助程序来强制执行该规则,并在构造它们的任何位置直接使用它,这样就不必进行必要的转换。

事实上,鉴于您已经定义了一个特定的类型,最好还是创建类型构造函数和运算符,这样如果将来该类型发生更改,您就不必完成所有类型代码来纠正它。

答案 2 :(得分:1)

制作自己的make_pair函数。通过这种方式,您可以始终保持订购。

typedef std::pair<unsigned long, unsigned long> link;
link make_my_pair(unsigned long x, unsigned long y) {
    if (x < y ) return std::make_pair(x, y);
    return std::make_pair(y, x);
}

我找到了解决方案here