如何插入唯一的项目到向量

How to insert unique items into vector?

本文关键字:项目 向量 唯一 何插入 插入      更新时间:2023-10-16

我有一个类型叫Neighbors:

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

这是data:

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

我试图写一个函数,插入值从_NeighborPtsNeighborPts(但只有那些还没有在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;
    }
}

和i已经有一个函数equal(),它检查两个par s是否相等。

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

您可以维护一个排序的向量。每次使用c++算法中的lower_bound函数来定位插入位置。如果插入位置的元素等于插入元素,则存在重复元素。

这种方法的性能将非常好,除非向量变得太大。您最好使用set或unordered_set的点是不同的,您需要通过基准测试来找到它。

您当前的vector解决方案将在O(N^2)时间内运行,这是不高效的。对于高效的解决方案,一个关联容器将是很好的——比如std::set。此外,您还需要一些"operator less"(而不是"equal()")来传递给函数。

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;
所以你需要提供compare class
struct data_compare {
    bool operator() (const data& lhs, const data& rhs) const{
      //...
    }
};
set<int64_t, data_compare> exising_items;

您可以定义这样的函数,或者在struct data中重写"operator <"

将"_NeighborPts"中的所有"data"插入到O(N*log(N)) time集合中

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

other_items.insert (_NeighborPts [i]);

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

my_items.insert (NeighborPts [i]);

现在你需要比较这两个集合:你可以用std::set_intersection来做. 或者对集合"my_items"构造一个简单的循环如果other_items中的当前元素不在_my_items中,则将其插入"NeighborPts"

此解决方案将运行在O(Nlog(N)) time

  1. _NeighborPts中没有绕过迭代项目。
  2. 只要你正在使用std::vector,没有绕过检查,以确定一个项目是否在NeighborPts插入之前。

通过使用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));
}