用于查找到元素集的 id 映射的良好数据结构 (c++)

Posted

技术标签:

【中文标题】用于查找到元素集的 id 映射的良好数据结构 (c++)【英文标题】:Good datastructure for look up of an id mapping to set of elements (c++) 【发布时间】:2009-06-23 19:12:08 【问题描述】:

没有提升,请简单的 STL。

我有一个类 Foo* 映射到一组类 ID 的指针。

我需要将指向 ID 实例的指针映射到 FOO 类。

说我有这个功能:

void FindXXX(const ID* pID)


 /*find the containing FOO class quickly, but not at expense of an ugly code*/


现在我将每个 ID* 映射到 FOO* 从而得到类似的东西

映射我的地图;我认为这有点丑陋和多余。

请推荐

【问题讨论】:

什么值得反对?请建议我如何提高此问题的质量以赢得您的支持? 是否保证每个ID对应一个Foo?如果是这样,类 ID 是否可以包含指向它所属集合的指针?那么保留一张 set* => Foo* 的地图就足够了。 是的,这是有保证的。但是,保持 set* => foo,将不允许您查询,例如查找特定 ID* 的 FOO* 实例 但是如果每个ID在逻辑上都属于一个FOO,为什么不在ID中包含一个指向FOO的指针作为成员变量呢? 因为我无法修改这些类。 【参考方案1】:

现在我将每个 ID* 映射到 FOO* 有类似的东西

映射我的地图;我认为这是一种 丑陋而多余。

我假设你有这样的东西:

map<ID*, Foo*> myMap;

为什么会很丑?

【讨论】:

请将 cmets 发布到我的问题的评论部分。谢谢...因为我为许多许多 ID 存储了同一个 Foo* 实例,因为每个 ID 在逻辑上属于 Foo*【参考方案2】:

听起来像是 std::map 的工作,但您的言论似乎表明您不想使用它,是这样吗?

std::map <key_type, data_type, [comparison_function]>

【讨论】:

不正确 我确实想使用一个,只是不知道如何正确设置它。我已经拥有的那个似乎浪费了很多空间,因为我为多个 ID 存储重复的 Foo* 嗯,它是一个哈希,所以默认情况下它会比简单的数组消耗更多的空间。【参考方案3】:

嗯,这取决于两个集合(ID* 和 foo*)的大小。我假设您有 #ID >> #FOO,并且 #FOO 大到足以保证通过它们进行线性搜索。

我假设 ID Foo 是一对多映射。

您可以将映射存储为一组 >> 并以这种方式对它们进行排序: 该集合按 ID* 的升序排序(指针值顺序可以) set> 按对中第一个 ID* 的值的升序排序。第二个。

搜索时,您需要找到 Foo* 的范围,其中第一个 ID* 的(指针)值低于被搜索项,最后一个值更高。这将导致希望迭代它们的集合的项目集要小得多。 然后,遍历这些并找到包含您要查找的 ID* 的那个。

你需要一个比较器来匹配这对 > 像这样:

typedef Item pair<Foo*, set<ID*> >;

// Sorter in ascending order of first ID*, then ascending order of last ID*
struct IDOrdering: public binary_function<Item, Item, bool> 
  bool operator ()(const Item& lhs, const Item& rhs) 
    return *(lhs.second.begin()) < *(rhs.second.begin())
        || *(lhs.second.rbegin()) < *(rhs.second.rbegin());
  
;


// your global map
set<Item, FirstIDOrdering> myMap;
typedef set<Item, FirstIDOrdering>::iterator ItemIterator;

// search for the item
Foo* FindXXX(const ID* pId) 
   Item criterion;
   criterion.second.insert(pId);
   ItemIterator start = myMap.lower_bound(criterion);
   while (start != myMap.end() && *(start->second.rbegin()) > pId) 
     if (start->second.count(pId))
       return start->first;
   
   return NULL;

您可以在这里节省一些内存,因为 Foo* 和 ID* 只存储一次,但它会以一些复杂性和可能的​​一些性能为代价。

请注意,此示例未考虑各种边界情况(空列表),并且在将新项目插入全局 myMap 时必须小心,因为您可能可以将新 ID* 添加到一对的列表,但您需要确保整个集合再次排序,以便查找真正起作用。

但是,很难知道什么最适合您,因为关于您尝试实现的目标的信息很少:数百万的 Foo*,数百万的 ID*,这个函数是将 ID* 解析为 Foo* 经常调用?在系统的性能关键部分?所有这些都有助于权衡代码的可读性、复杂性和性能。

【讨论】:

以上是关于用于查找到元素集的 id 映射的良好数据结构 (c++)的主要内容,如果未能解决你的问题,请参考以下文章

寒假 5

布隆过滤器(Bloom Filter)

布隆过滤器(Bloom Filter)

java 用于映射数据集的简单学习矢量量化(LVQ)神经网络

python 用于PASCAL VOC数据集的颜色映射函数的Python实现。

如何使用分析窗口 SQL 函数在同一数据集的多组行中查找 id 值