在使用对象作为键时保持 std::map 平衡
Keeping std::map balanced when using an object as key
我正在编写一些代码,其中存储了许多我想根据设定的标准返回的对象。所以对我来说,使用带有对象的地图作为键是有意义的。其中对象将包含"设置标准"。
以下是我正在处理的对象类型的简化示例:
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( ( { 左 } else if (keyCompare(b,a(( { 右 } 还 { 平等 }所以我不能只使用 a.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;
}
}
但这不仅感觉有点笨拙,"长期未签名的int"还不足以容纳潜在的数字。我可以把它放在一个字符串中,但速度在这里是一个问题,我认为 std::string <很昂贵。总的来说,虽然我可以使这个对象越小越好。>
我想知道是否有人对如何做得更好有任何建议。也许我需要使用std::map以外的其他东西,或者可能有另一个重载。或者,也许我在这里错过了一些显而易见的东西。我真的觉得我把这件事复杂化了,也许我真的用地图吠错了树。
当我写这篇文章时,我突然想到除法是获得"唯一"数字的另一种方法,但这也可能等于非常大的数字
您所需要的只是实现严格的弱排序,您可以使用 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);
}
}
如果您没有所需的 C++11 支持,则可以使用 <tr1/tuple>
std::tr1::tie
或 boost 库中的等效版本。
我觉得 juanchopanza 有一个非常好的解决方案,对于那些没有 C++11 支持或提升库的人来说
我找到了一个非常简单的解决方案:定义类元素的词典比较的最简单方法是什么?
这个解决方案比元组更适合我的特定问题(因为我还有一个我想考虑的值数组(。但我强烈建议将来考虑元组,我也会。
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
}
}
感谢胡安乔潘扎的回答以及其他任何看过
- 如何导出包含具有"std::unique_ptr"值的"std::map"属性的
- 使用一个考虑到std::map中键值的滚动或换行的键
- 有没有办法对std::unordered_set、std::unrdered_map、std::set、std::map
- 将重物插入std::map
- 使用通用值初始化 std::map,不重复
- 仅包含可移动 std::map 的类的移动构造函数不起作用
- C++:当所有条目都保证是唯一时,替代 std::map
- 使用模板化的键类型定义 std::map,该键类型基于作为参数接收的函数
- 如果 KEY 是 std::list 或 std::vector 而不是值,那么 std::map 的默认行为是什么?
- C++如何创建 std::map
- 从其他容器中移动构造"std::map"
- 将 std::map::emplace 与返回 shared_ptr 的函数一起使用是否正确?
- C++中 std::map 的运行时复杂度是多少?
- 为什么在 std::map 上移动无法将元素从一个映射移动到另一个映射
- 使用重载 [] 运算符返回 std::map() 的可赋值
- std::map, std::unordered_map - 缩小初始值设定项列表中的转换范围
- C++ 使用枚举类对象分配 std::map 值
- 静态 std::map instatiation 在类的方法中调用构造函数吗?
- std::map:当元素不可默认构造时创建/替换元素
- Arduino编译器和STL:使用std::vector和std::map