删除数组中的重复项,同时保留C ++中的顺序

时间:2010-08-30 08:08:42

标签: c++ algorithm stl

  

可能重复:
  How to make elements of vector unique? (remove non adjacent duplicates)

是否有任何标准算法作为STL算法的一部分提供,可以在保留顺序的同时从阵列中删除重复项。例如,如果删除重复项后我有int a[] = {2,1,3,1,4,2};之类的数组,那么它应该是a[] = {2,1,3,4};。我无法使用std::unique,因为数组未排序。其他解决方案,例如将其插入std::set我会丢失顺序,因为元素将被排序。我还可以使用其他任何算法组合,或者我必须编写自己的算法吗?

3 个答案:

答案 0 :(得分:6)

没有标准算法,但实施起来相当容易。原则是保留到目前为止看到的std::set个项目,并在复制到新的向量或数组时跳过重复项。这在O(n lg n)时间和O(n)存储器中操作。如果你正在使用C ++ 0x,那么你可以使用std::unordered_set为看到的项目设置将其缩短到O(n)时间;这使用哈希表而不是二叉树,应该更快。

答案 1 :(得分:3)

由于问题相对“复杂”,我不会尝试仅通过使用标准算法强制解决方案(因为没有特殊的算法来解决您的问题。您可能使用remove_if,find和bind2nd或东西)。 为了自己实现算法,你基本上有两个选择,通常的内存与速度权衡。 第一种解决方案是迭代向量并搜索并删除当前项的重复项。这是cpu密集型方法。 可能更快的方法是创建第二个向量(与第一个向量相同以最小化内存重新分配)并将找到的项存储在那里。然后,对于原始矢量的每次迭代,仅需要搜索较短的第二矢量以找出是否应该删除当前项目。 第一种方法适用于每个迭代器,而第二种方法仅限于随机访问迭代器。 以下是实施:

#include <iostream>
#include <algorithm>
#include <vector>

using namespace std;

template<typename T>
void remove_duplicates_ordered_mem_intensive(T &container)
{
   std::vector<typename T::value_type> items;
   items.reserve (container.size());

   typename T::iterator i = container.begin();
   while (i != container.end())
   {
      if (find (items.begin(), items.end(), *i) != items.end())
         i = container.erase(i);
      else
      {
         items.push_back(*i);
         ++i;
      }
   }
} 

template<typename T>
void remove_duplicates_ordered_slow(T &container)
{
   typename T::iterator i = container.begin();
   while (i != container.end())
   {
      typename T::iterator f = i;
      ++f;
      while (f != container.end())
      {
         if (*f == *i)
            f = container.erase(f);
         else
            ++f;
      }
      ++i;
   }
} 

int main ()
{
   vector<int> v;
   v.push_back (2);
   v.push_back (1);
   v.push_back (3);
   v.push_back (1);
   v.push_back (4);
   v.push_back (2); 

   cout << "Old:\n";
   for (vector<int>::const_iterator i = v.begin(); i != v.end(); ++i)
      cout << *i << endl;


   vector<int> a (v), b (v);
   remove_duplicates_ordered_mem_intensive (a);
   remove_duplicates_ordered_slow (b); 

   cout << "\nRemoved duplicates with intensive memory usage:\n";
   for (vector<int>::const_iterator i = a.begin(); i != a.end(); ++i)
      cout << *i << endl; 

   cout << "\nRemoved duplicates somewhat slower, without copying:\n";
   for (vector<int>::const_iterator i = b.begin(); i != b.end(); ++i)
      cout << *i << endl;
}

答案 2 :(得分:1)

  

从数组中删除重复项

这在技术上是不可能的,因为数组不能改变大小。