在指针向量中添加非重复值的最有效方法

Most efficient way to add non-duplicate values in vector of pointers

本文关键字:有效 方法 向量 指针 添加      更新时间:2023-10-16

我有一个这样的矢量

vector<Point*> points;

我想给这个向量添加一个新的点。然而,我有最多50个内部向量点,但其中许多是重复的。实现添加非重复值的最有效方法是什么?到目前为止,我是这样做的:

boolean add_point(vector<Point*> *p, int x, int y){
  for(vector<Point*>::iterator i = p->begin(); i != p->end(); i++){
    if((*i)->x == x && (*i)->y == y)
        return false;
  }
  p->push_back(new Point(x,y));
  return true;
}

然而,当我调用这个函数百万次时,我的应用程序的执行时间增加了很多。

根据堆栈主题之一,我已经尝试过了:

sort( points.begin(), points.end() );
points.erase( unique( points.begin(), points.end() ), points.end() );

但是两种代码的结果是不同的。排序/擦除工作很好对指针矢量?

有什么建议可以解决这个问题吗?

假设您的Point结构类似于

struct Point { int x, y; }

则仅将Points本身存储在vector中,并提供比较函数

bool operator==(Point const& p1, Point const& p2)
{
  return p1.x == p2.x && p1.y == p2.y
}
bool operator<(Point const& p1, Point const& p2)
{
  return p1.x != p2.x ? p1.x < p2.x : p1.y < p2.y;
}

之后,您可以使用以下命令删除重复项:

std::sort(vec.begin(), vec.end());
vec.erase(std::unique(vec.begin(), vec.end()), vec.end());

如果您希望您的容器自动防止重复使用std::set<Point>/std::unordered_set<Point>(您需要为后者提供std::hash的专门化),尽管使用具有最终排序和删除重复的向量总体上可能更快。正如@PorkyBrain指出的那样,你可以在插入时使用std::lower_bound来保持向量排序,并避免最终排序。

所有这些方法中最有效的方法完全取决于您的用例,因为总是首先使用最简单的方法编写程序,然后配置文件查看是否需要改进。

使用std::unordered_map

这些点将被散列,因此在检查大量重复项时存储速度应该更快。

直接将点放入向量中可能更快。在处理POD类型时,保持排序向量(通过使用lower_bounds添加)通常是最快的,因为它是最适合缓存的。下面是一个例子:

void addToSortedVector(std::vector<Point>& v, Point p){
    auto it = std::lower_bound(v.begin(),v.end(),p);
    if(it == v.end() || !(*it == p)){
        v.emplace(it,std::move(p));
    }
}

您可以在这里看到大约1.5倍的速度差异:http://ideone.com/E2gqOd但是您的速度差异将根据缓存效果和架构而变化,因此对此测量持保留态度