C++:需要索引集

发布于 2024-08-27 01:27:50 字数 303 浏览 3 评论 0原文

我需要一个按如下方式操作的索引关联容器:

  • 初始为空,大小=0。

  • 当我向其中添加新元素时,它会将其放置在索引 [size] 处,与向量的 Push_back 非常相似。它增加大小并返回新添加元素的索引。

  • 如果该元素已存在,则返回其出现位置的索引。

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

在这种情况下,使用 set.begin() 进行差异处理是正确的做法吗?

I need an indexed associative container that operates as follows:

  • initially empty, size=0.

  • when I add a new element to it, it places it at index [size], very similar to a vector's push_back. It increments the size and returns the index of the newly added element.

  • if the element already exists, it returns the index where it occurs.

Set seems the ideal data structure for this but I don't see any thing like getting
an index from a find operation. Find on a set returns an iterator to the element.

Will taking the difference with set.begin() be the correct thing to do in this situation?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

奶气 2024-09-03 01:27:50

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迭代器的向量,每次使用map::insert并检查结果的bool部分以查看indexed是否需要更新等)

并获取一个元素:

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

就是这样。当然,一个问题是,一旦对象进入集合,就无法对其进行修改。这是这里实现方式的一种泄漏,因为映射键是常量,原因很明显——但事实上,我认为,无论实现如何,这都是我们想要的。如果您坚持不存在重复项,那么一旦某个对象位于列表中,它就不能被修改,以防任何修改都会使其成为另一个对象的重复项。

(另请注意,我在这里使用 size_t 进行了一些作弊——我认为 std::vector::size_type 可能更准确——这主要是为了简洁!)

There's no immediately-appropriate data structure in the STL for this, but one straightforward and fairly efficient way of implementing this would be to use a map and a vector of pointers. The map maps objects to their index in the array (so that checking whether an object exists is efficient, and, if the object does exist already, the index is at hand immediately), and the vector maps indexes to the object in the map (so that retrieving objects by index is efficient).

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

To add an element:

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

(Obvious alterations according to personal style might be to store a vector of map iterators, use map::insert every time and check the bool part of the result to see whether indexed needs updating, etc.)

And to get an element:

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

And that's that. One issue is of course that once an object is in the set, it can't be modified. This is a sort of leak from the way it's been implemented here, because map keys are const, for obvious reasons -- but in fact it's what's wanted anyway, I think, regardless of implementation. If you're insisting on having no duplicates, then once an object is in the list it mustn't be modifiable, in case any modifications would make it become a duplicate of another object.

(Also note that I've cheated a bit by using size_t here -- I suppose std::vector<const T *>::size_type might be more precisely correct -- this is mainly in the interests of brevity!)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文