从给定索引上的向量中删除元素,顺序无关紧要

时间:2014-09-01 08:45:55

标签: c++ vector

我所拥有的是 vector 元素,我不关心它们的顺序。 比我有N索引(每个索引在向量中的唯一位置)要从向量中删除的元素。我希望删除尽可能快。

我能想出的最好的方法是在集合(订单索引)中存储索引:

std::set<unsigned int> idxs;
for (int i=0; i<N; ++i)
    idxs.insert(some_index);

然后以相反的顺序迭代集合并将index替换为向量的最后一个元素。

std::set<unsigned int>::reverse_iterator rit;
for (rit = idxs.rbegin(); rit != idxs.rend(); ++rit) {
    vec[*rit].swap(vec[vec.size() - 1]);
    vec.resize(vec.size() - 1);
}

然而我在考虑是否有一些更有效的方法可以做到这一点,因为设置的使用对我来说似乎有点过分我希望避免排序所有

EDIT1: 让我们假设我使用向量并在之后对其进行排序。

std::vector<unsigned int> idxs;
for (int i=0; i<N; ++i)
    idxs.push_back(some_index);
std::sort(idxs.begin(), idxs.end());

我可以再推它吗?

EDIT2: 我应该提到矢量最多有10个元素。然而,我的程序中的删除经常发生(数十万次)。

2 个答案:

答案 0 :(得分:1)

set是个不错的选择。我猜使用另一个分配器(例如竞技场)会产生最大的影响。为什么不使用集合而不是元素向量来开始?

我看到以下相关变体:

  • 而不是删除,创建一个新的向量并复制保留的元素,然后交换回来 这可以使您的指数保持稳定(与删除不同,这需要对索引进行排序或更新)。

  • 使用与数据长度相同的bool向量,而不是索引向量。 长度为&#34;最大10&#34;给出一点掩码似乎就足够了

所以,粗略地说:

struct Index 
{
   DWORD removeMask = 0;  // or use bit vector for larger N
   void TagForRemove(int idx) { removeMask |= (1<<idx); }
   boll DoRemove(int idx) const { return (removeMask & (1<<idx)) != 0; }
}

// create new vector, or remove, as you like
void ApplyRemoveIndex(vector<T> & v, Index remove)
{
   vector<T> copy;
   copy.reserve(v.size());
   for (i=0..v.size())
     if (!remove.DoRemove(i))
       copy.push_back(v[i]);
   copy.swap(v);
}

答案 1 :(得分:0)

您可以使用swap / pop_back删除指定索引处的项目,并跟踪您使用哈希表移动的索引。它的线性空间&amp;删除次数的时间。

std::vector<T> vec = ...;
std::vector<unsigned int> idxs;
std::unordered_map<unsigned int, unsigned int> map;

for(auto index : idxs) {
  unsigned int trueIndex = index;
  while (trueIndex >= vec.size()) {
    trueIndex = map[trueIndex];
  }

  // element at index 'vec.size()-1' is being moved to index 'index'   
  map[vec.size()-1] = index; 
  swap(vec[trueIndex], vec[vec.size()-1]);
  vec.pop_back();   
}