如何使用std :: map将布尔映射到3d点结构?

问题描述

| 我如何使用以下结构:
struct point 
{
    int x;
    int y;
    int z;
};
作为
std::map<point,bool>
的钥匙?如何为两点定义
operator<
?     

解决方法

诸如ѭ3之类的标准库容器要求您的订购是“严格弱订购”,因此在设计容器时必须非常小心。 三元组的典型方法如下所示:
bool operator<(const point& other) const
{
   if (x != other.x)
       return (x < other.x);

   if (y != other.y)
       return (y < other.y);

   return (z < other.z);
}
这就像只比较
x
的比较器,但不同的是,如果两个
x
是相同的,则可以比较
y
。如果它们相同,那么类似地,您将陷入“ 8”比较。     ,当然,ѭ9将使这完全没有必要。 更新这里添加了全包式的“吃不饱”的解决方案。恕我直言,它摇滚!
#include <boost/tuple/tuple_comparison.hpp>

struct point 
{
    int x,y,z;
    point(int x,int y,int z) : x(x),y(y),z(z) {}
    bool operator<(const point& rhs) const 
    {
        return boost::tie(x,z) < boost::tie(rhs.x,rhs.y,rhs.z);
    }
};
关键在于:这一切都可以优化。编译:
int main()
{
    point a(1,2,3),b(3,1);
    bool lt = a<b;
    return lt?0:255;
}
使用g ++ -O2时,汇编结果如下。
main:
.LFB1132:
        pushl   %ebp
        xorl    %eax,%eax
        movl    %esp,%ebp
        popl    %ebp
        ret
.LFE1132:
编译器能够将整个程序优化为有效……13%。那太整齐了。 简单答案如下:
struct point 
{
    point(int x,int z) 
        : x(x),z(z) {}
    int x;
    int y;
    int z;
    bool operator<(const point& rhs) const 
    {
        if (x<rhs.x) return true;
        if (x==rhs.x) 
        { 
            if (y<rhs.y) return true;
            if (y==rhs.y) return z<rhs.z;
        }
        return false;
    }
};
另外,我会考虑寻找对结构的重新定义,以允许使用std :: lexicographical_compare
#include <algorithm>

// ...
bool operator<(const point& rhs) const 
{
    return std::lexicographical_compare(&xyz,&xyz+3,&rhs.xyz,&rhs.xyz+3);
}
    ,一种懒惰的方法:
bool operator<( point const &pt ) const
{
    return ::boost::make_tuple(x,z) <
           ::boost::make_tuple(pt.x,pt.y,pt.z);
}
    ,最简单的写法是这样的:
bool operator<(const point& p) const
{
    if(x < p.x)
    {
        return true;
    }
    else if(p.x < x)
    {
        return false;
    }

    if( y < p.y)
    {
        return true;
    }
    else if( p.y < y)
    {
        return false;
    }

    if( z < p.z)
    {
        return true;
    }
    else if(p.z < z)
    {
        return false;
    }

    return false;

}
    ,如果应该以某种方式订购它们,则需要指定确切的方式(例如,从0/0/0到欧氏距离)。如果您只想区分不同点,则可以执行以下操作
x == x2 ? (y == y2 ?  (z < z2) : y < y2) : x < x2 
    ,只是猜测,
bool operator<(const point& other) const
{
  return( memcmp( (void*) this,(void*) &other,sizeof(point)) < 0);
}
当然,由于x,y和z是带符号的值,所以这种顺序有点奇怪,但这应该适合于将其放入std :: map中,不是吗?