如何将独特的项目插入向量?

时间:2014-05-24 12:06:20

标签: c++ vector stl containers

我有一个名为Neighbors的类型:

typedef vector<pair<data,int>> Neighbors;

以及data

struct data
{
    int par[PARAMETERS];
    int cluster;
    bool visited;
    bool noise;
};

我试图编写一个函数,将_NeighborPts的值插入NeighborPts(但只有NeighborPts中已有的值):

void insert_unique(Neighbors* NeighborPts, const Neighbors& _NeighborPts)
{
    Neighbors_const_it _it = _NeighborPts.begin();
    while(_it != _NeighborPts.end())
    {
        if(/* _it->first.par isn't in *NeighborPts */)
            NeighborPts->push_back(*_it);
        ++_it;
    }
}

我已经有一个函数equal()来检查2 par是否相等。

所以我必须在while循环中迭代NeighborPts并检查是否找到了该项目?或者我可以使用一些内置的findfind_if函数为我做这个吗?

3 个答案:

答案 0 :(得分:1)

您可以维护已排序的矢量。使用C ++算法中的lower_bound函数每次都能找到插入位置。如果插入位置的元素等于insert元素,那么你有一个副本。

除非矢量变得太大,否则性能将非常好。您使用套装或无序套装更好的地方会有所不同,您需要通过基准测试才能找到它。

答案 1 :(得分:0)

你当前使用vector的解决方案将在O(N ^ 2)时间运行,这是无效的。 对于有效的解决方案,关联容器会很棒 - 例如std :: set。 你还需要一些&#34;较少的操作员&#34; (而不是&#34; equal()&#34;),传递给函数。

template < class T,                        // set::key_type/value_type
           class Compare = less<T>,        // set::key_compare/value_compare
           class Alloc = allocator<T>      // set::allocator_type
           > class set;

所以你需要提供比较类

struct data_compare {
    bool operator() (const data& lhs, const data& rhs) const{
      //...
    }
};

set<int64_t, data_compare> exising_items;

您可以定义这样的功能,或覆盖&#34;运算符&lt;&#34;在struct data。

插入所有&#34;数据&#34;来自&#34; _NeighborPts&#34;进入集合 - O(N * log(N))时间

std :: set other_items; 在循环中 - 迭代_NeighborPts并插入数据元素

other_items.insert (_NeighborPts [i]);

std :: set my_items; 在循环中 - 迭代_NeighborPts并插入数据元素

my_items.insert (NeighborPts [i]);

现在你需要比较两组: 你可以使用std::set_intersection来做 。或者在集合上构建一个简单的循环&#34; my_items&#34; 如果other_items中的当前元素不在_my_items中,请将其插入&#34; NeighborPts&#34;

此解决方案将在 O(Nlog(N))时间

运行

答案 2 :(得分:0)

  1. 无法绕过_NeighborPts中的项目进行迭代。
  2. 只要您使用std::vector,就无法检查项目是否在NeighborPts之前插入其中。
  3. 您可以使用std::for_each和仿函数让代码更容易阅读。

    struct UniqueItemInserter
    {
       UniqueItemInserter(Neighbors* neighborsIn) : neighbors(neighborsIn) {}
    
       void operator(pair<data,int> const& item)
       {
         if ( std::find(neighbors->begin(), neighbors->end(), item) != neighbors->end() )
         {
            neighbors->push_back(item);
         }
       }
    
       Neighbors* neighbors;
    };
    
    void insert_unique(Neighbors* NeighborPts, const Neighbors& _NeighborPts)
    {
        std::for_each(_NeighborPts.begin(), _NeighborPts.end(), UniqueItemInserter(NeighborPts));
    }