我正在编写一些代码,我根据设置标准存储了许多我想要回来的对象。所以对我来说,使用带有对象的地图作为关键是有意义的。对象将包含“设置标准”。
以下是我正在处理的对象类型的简化示例:
class key
{
int x,y,w,h;
}
class object
{
...
}
std::map<key, object, KeyCompare> m_mapOfObjects;
很简单,首先想到的是创建一个像这样的比较函数:
struct KeyCompare
{
bool operator()(const key &a, const key &b)
{
return a.x < b.x || a.y < b.y || a.w < b.w || a.h < b.h;
}
}
然后我认为这种回归的可能性非常高。所以我认为这将导致一个非常不平衡的树,因此搜索速度慢。
我主要担心的是,据我所知,std :: map以这种方式使用了这一个函数: if(keyCompare(a,b)) { //左边 } 否则如果(keyCompare(b,a)) { //右边 } 其他 { //等于 } 所以我不能只使用a.x&lt; b.x,因为那时任何具有相同x的东西都会被认为是相等的,这不是我想要的。我不介意它以这种方式排序,但它的“平等”位我似乎无法解决而不会使其失衡。
我认为将它们全部加在一起是显而易见的原因。
因此,我能想出的唯一解决方案是在信息上创建一个“UID”:
typedef long unsigned int UIDType;
class key
{
private:
UIDType combine(const UIDType a, const UIDType b)
{
UIDType times = 1;
while (times <= b)
times *= 10;
return (a*times) + b;
}
void AddToUID(UIDType number)
{
if(number < m_UID)
{
m_UID = combine(number, m_UID);
}
else
{
m_UID = combine(m_UID, number);
}
}
UIDType UID;
public:
int x,y,w,h;
key()
{
AddToUID(x);
AddToUID(y);
AddToUID(w);
AddToUID(h);
}
}
struct KeyCompare
{
bool operator()(const key &a, const key &b)
{
return a.UID < b.UID;
}
}
但这不仅感觉有点hacky,“long unsigned int”还不足以容纳潜在的数字。我可以把它放在一个字符串中,但速度是一个问题,我假设一个std :: string&lt;太贵了。总体而言,虽然较小的我可以使这个对象更好。
我想知道是否有人对如何做得更好有任何建议。也许我需要使用std :: map之外的其他东西,或者可能还有另一个重载。或者也许有一些明显的东西我在这里失踪了。我真的觉得我过于复杂了,也许我真的用地图咆哮着错误的树。
当我写这篇文章时,我发现分歧是获得“独特”数字的另一种方式,但也可能等于非常大的数字
答案 0 :(得分:2)
您只需要实现一个strict weak ordering,您可以使用std::tie
轻松实现该operator<
,该#include <tuple>
struct KeyCompare
{
bool operator()(const key& a, const key& b) const
{
return std::tie(a.x, a.y, a.w, a.h) < std::tie(b.x, b.y, b.w, b.h);
}
}
的比较std::tr1::tie
执行lexicographical比较:< / p>
<tr1/tuple>
如果您没有所需的C ++ 11支持,则可以使用{{1}}中的{{1}}或来自boost库的同等版本。
答案 1 :(得分:0)
我觉得juanchopanza有一个非常好的解决方案,对于那些没有C ++ 11支持或提升库的人
我找到了一个非常简单的解决方案: What's the simplest way of defining lexicographic comparison for elements of a class?
这个解决方案适用于我的特定问题比元组更好(因为我还有一个我想考虑的值数组)。但我强烈建议将来考虑元组,我也一样。
struct keyCompare
{
bool operator()(const key &a, const key&b)
{
if(a.x != b.x) return a.x < b.x;
if(a.y != b.y) return a.y < b.y;
if(a.w != b.w) return a.w < b.w;
if(a.h != b.h) return a.h < b.h;
return false; //they must be equal
}
}
感谢juanchopanza的回答以及其他任何看过
的人