C ++:需要索引集

时间:2010-04-01 16:36:17

标签: c++ set containers indexed

我需要一个索引关联容器,其操作如下:

  • 最初为空,尺寸= 0。

  • 当我向它添加一个新元素时,它将它放在index [size],非常类似于vector的push_back。它递增大小并返回新添加元素的索引。

  • 如果元素已经存在,则返回它出现的索引。

Set似乎是理想的数据结构,但我没有看到任何像get的东西 来自查找操作的索引。在集合上查找返回元素的迭代器。

在这种情况下,采取与set.begin()的区别是正确的吗?

1 个答案:

答案 0 :(得分:3)

STL中没有立即适当的数据结构,但实现这一点的一种简单而有效的方法是使用映射和指针向量。 map将对象映射到数组中的索引(这样检查对象是否存在是有效的,如果对象确实存在,则索引就在眼前),vector映射索引到地图中的对象(以便通过索引检索对象是有效的)。

std::map<T,size_t> objects;
std::vector<const T *> indexed;

添加元素:

size_t add_element(const T &v) {
    std::map<T,size_t>::iterator it=objects.find(v);
    if(it==objects.end()) {
        it=objects.insert(std::map<T,size_t>::value_type(v,objects.size())).first;
        indexed.push_back(&it->first);
    }
    return it->second;
}

(根据个人风格的明显改变可能是存储地图迭代器的向量,每次使用map :: insert并检查结果的bool部分以查看indexed是否需要更新等。)< / p>

获得元素:

const T &get_element(size_t index) {
    return *indexed[index];
}

就是这样。一个问题当然是一旦对象在集合中,就无法修改它。这是从它在这里实现的方式的一种泄漏,因为地图键是常量,显而易见的原因 - 但实际上它是我想的,无论如何,无论实现如何。如果你坚持不重复,那么一旦一个对象在列表中,它就不能被修改,以防任何修改使它成为另一个对象的副本。

(另请注意,我在这里使用size_t作了一些欺骗 - 我认为std::vector<const T *>::size_type可能更准确 - 这主要是为了简洁!)