std :: map unique std :: less<>将2D点作为键的功能

时间:2011-11-30 22:33:00

标签: c++ stl binary-tree std

好吧,经过四个小时的调试,我很困惑,我发现了问题的原因......

我正在制作一些程序,可以在std :: map中保存一些点并在窗口中渲染它们。 但奇怪的是,有些观点未能将其纳入地图。

std::map<Point2, Prop*> m_Props_m;

void AddProp(std::pair<Point2, Prop*> p)
{
    m_Props_m.insert(p);
}

struct Point2
{
unsigned int Point2::x;
unsigned int Point2::y;
//--------
Point2::Point2()
    :x(0)
    ,y(0)
{}

bool Point2::operator< (const Point2& b) const
{
    return ( x+y < b.x+b.y );
}

bool Point2::operator> (const Point2& b) const
{
    return ( x+y > b.x+b.y );
}
};

感谢上帝,我对二叉树有一些经验,所以我可以找出问题的原因。

想象一下,我们有2个Point2。

Point2 a(0,1);
Point2 b(1,0);

如您所见,运营商&lt;方法我写的它会返回false,而运算符&gt;也会返回假。因此,如果a已经在地图中,并且插入了b,则插入失败。

现在,这一切都很好,但我该如何解决这个问题呢?有没有什么方法可以为2D点设置一个小于操作符,以便我可以在地图中存储每个唯一的点?

3 个答案:

答案 0 :(得分:11)

std::map根本不使用operator>,因此您不必担心这一点。

要对多个字段(在本例中为两个字段)进行排序,请使用所谓的&#34;字典排序&#34;,这意味着第一个字段最重要,第二个字段断开关系:

bool operator<(const Point2 &lhs, const Point2 &rhs) {
    return (lhs.x < rhs.x) || ((lhs.x == rhs.x) && (lhs.y < rhs.y));
}

答案 1 :(得分:2)

如果坐标之和相等,则您的比较函数会考虑等效点。例如,(2,5)相当于(3,4),因为2 + 5 = 3 + 4.在地图中已经具有等价物的点将不会成功。

更好的想法是首先比较x,如果两个点的x值相等,则按y秒。

bool operator< (const Point2 &lhs, const Point2 &rhs) {
    return (lhs.x < rhs.x) || ((lhs.x == rhs.x) && (lhs.y < rhs.y));
}

答案 2 :(得分:1)

这应该可以解决问题:

bool Point2::operator< (const Point2& b) const
{
    if (x<b.x) return true;
    else if (!(b.x<x) && y<b.y) return true;
    else return false;
}

std::map仅使用operator<。如果!(a<b) && !(b<a)ab相等(不相同),则地图只会存储其中一个。 <{1}}未使用。

在其他情况下比较Point2可能没有意义,所以为了避免误解,我建议您为地图提供比较功能,并从班级中删除operator>

operator<

在我看来,操作符重载只应在对给定类型有意义时使用,并且2D空间中的一个点大于2D空间中的另一个点是不直观的。