混合矢量/列表容器

Hybrid vector/list container?

本文关键字:列表 混合      更新时间:2023-10-16

我需要一个同时具有向量和列表属性的容器。我需要快速随机访问容器中的元素,但我也需要能够在不移动其他元素的情况下移除容器中间的元素。我还需要能够迭代容器中的所有元素,并一目了然(无需迭代)容器中有多少元素。

经过一番思考,我已经找到了如何创建这样一个容器,使用向量作为基本容器,并将实际存储的数据包装在一个结构中,该结构还包含记录元素是否有效的字段,以及指向向量中下一个/上一个有效元素的指针。再加上一些重载之类的,听起来应该是相当透明的,并满足我的要求。

但在我真正创建另一个容器之前,我很好奇是否有人知道实现这一功能的现有库?我宁愿使用有效的东西,也不愿花时间调试自定义实现。我已经浏览了Boost库(我已经在使用它),但在那里没有找到这个。

如果顺序无关紧要,我只需要使用一个将整数映射到指针的哈希表。std::tr1::unordered_map<int, T *>(或者如果C++0x正常则为std::unordered_map<int, unique_ptr<T>>)。

哈希表的元素可以四处移动,这就是为什么您需要使用指针,但它将支持非常快速的插入/查找/删除。迭代也很快,但元素会以不确定的顺序出现。

或者,我认为您可以将自己的想法实现为std::vectorstd::list的简单组合。只需同时维护一个list<T> my_list和一个vector<list<T>::iterator> my_vector。要添加对象,请将其推到my_list的背面,然后将其迭代器推到my_vector上。(将迭代器设置为my_list.end(),并将其递减以获得最后一个元素的迭代器。)要查找,请在向量中查找,然后取消对迭代器的引用。要删除,请从列表中移除(可以通过迭代器执行),并将向量中的位置设置为my_list.end()

std::list保证删除中的元素时它们不会移动。

[更新]

我感觉很有动力。实现的第一关:

#include <vector>
#include <list>
template <typename T>
class NairouList {
public:
  typedef std::list<T> list_t;
  typedef typename list_t::iterator iterator;
  typedef std::vector<iterator> vector_t;
  NairouList() : my_size(0)
  { }
  void push_back(const T &elt) {
      my_list.push_back(elt);
      iterator i = my_list.end();
      --i;
      my_vector.push_back(i);
      ++my_size;
  }
  T &operator[](typename vector_t::size_type n) {
      if (my_vector[n] == my_list.end())
          throw "Dave's not here, man";
      return *(my_vector[n]);
  }
  void remove(typename vector_t::size_type n) {
      my_list.erase(my_vector[n]);
      my_vector[n] = my_list.end();
      --my_size;
  }
  size_t size() const {
      return my_size;
  }
  iterator begin() {
      return my_list.begin();
  }
  iterator end() {
      return my_list.end();
  }
private:
  list_t my_list;
  vector_t my_vector;
  size_t my_size;
};

它缺少一些实施质量方面的内容。。。比如,你可能想要更多的错误检查(如果我删除同一个元素两次怎么办?),也许还需要operator[]begin()end()的一些const版本。但这只是一个开始。

也就是说,对于"几千个"元素,一张地图可能至少也会起到同样的作用。一个很好的经验法则是"永远不要优化任何东西,直到你的剖析器告诉。

看起来您可能想要一个std::deque。移除元素不如std::list有效,但因为deque通常是通过使用非连续内存"块"创建的,这些块通过容器内部的额外指针数组/向量进行管理(每个"块"都是N个元素的数组),因此移除deque内部的元素不会导致与向量相同的重新洗牌操作。

编辑:第二次,在查看了一些评论之后,虽然我认为std::deque可以工作,但我认为std::mapstd::unordered_map实际上会对您更好,因为它将允许您想要的数组语法索引,同时还可以快速删除元素。