在使用对象作为键时保持 std::map 平衡

Keeping std::map balanced when using an object as key

本文关键字:std map 平衡 对象      更新时间:2023-10-16

我正在编写一些代码,其中存储了许多我想根据设定的标准返回的对象。所以对我来说,使用带有对象的地图作为键是有意义的。其中对象将包含"设置标准"。

以下是我正在处理的对象类型的简化示例:

    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 
          }   
    }

感谢胡安乔潘扎的回答以及其他任何看过

的人