混合载体/列表容器?

时间:2011-06-14 03:23:33

标签: c++ stl

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

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

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

2 个答案:

答案 0 :(得分:6)

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

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

或者,我认为您可以将自己的想法实现为std::vectorstd::list的非常简单的组合。只需维护list<T> my_listvector<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;
};

它缺少一些实施质量触摸......就像,你可能想要更多的错误检查(如果我删除相同的元素两次怎么办?)和const operator[]begin(),{ {1}},end()。但这是一个开始。

也就是说,对于“几千个”元素,地图可能至少也会起作用。一个好的经验法则是“在你的探查器告诉你之前,不要优化任何东西”。

答案 1 :(得分:3)

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

编辑:第二,虽然在审核了一些评论后,虽然我认为std::deque可行,但我认为std::mapstd::unordered_map实际上对你来说会更好,因为它允许你想要的数组语法索引,同时也可以快速删除元素。