Удаление дубликатов из std::vector

Рейтинг: 3Ответов: 4Опубликовано: 10.04.2011

Есть 3 вектора координат: x_vect, y_vect, z_vect. Они содержат координаты точек, т.е. координата одной i-ой точки - это (x_vect[i], y_vect[i], z_vect[i]). Но точки повторяются. Необходимо сделать так, чтобы в итоге остались все точки, но без повторений. Необходимо убрать дубликаты точек.

Ответы

▲ 10

Можно использовать множество, std::set:

UPD

struct Point {
    int x;
    int y;
    int z;
};

std::set<Point> pointsSet;

UPD2

Пример на пальцах.

▲ 10

Строить set для удаления дубликатов не хорошо, так как set гораздо медленнее вектора, и потребляет порядочно больше памяти. Для такой простой задачи гораздо лучше просто отсортировать вектор. Известно, что из отсортированной последовательности удалить дубликаты легко, причём за линейное время. Более того, в STL для этого уже есть готовая функция unique.

//для вектора
#include <vector>
//для sort и unique
#include <algorithm>
using namespace std;

struct Point
{
    int x,y,z;
    Point(int x=0,int y=0,int z=0):x(x),y(y),z(z){}
};

//оператор меньше для sort
bool operator<(const Point& a, const Point& b)
{
    return a.x<b.x || a.x==b.x && (a.y<b.y || a.y==b.y && a.z<b.z);
}
//оператор проверки на равенство для unique
bool operator==(const Point& a, const Point& b)
{
    return a.x==b.x && a.y==b.y && a.z==b.z;
}

...

vector<Point> p;
...//как-то заполняем p
//сортируем
sort(p.begin(),p.end());
//и удаляем дубликаты
p.resize(unique(p.begin(),p.end())-p.begin());
//всё, теперь p содержит только уникальные точки
▲ 3

Добавить методы для инициализации, что бы удобней было заполнять структуру. И в чем именно у вас проблемы с insert ?

struct {
    int x;
    int y;
    int z;
    Point(){ x = 0; y = 0; z = 0; }
    Point(int _x, int _y, int _z){ x = _x; y = _y; z = _z; }

}typedef Point;

std::set<Point> pointsSet;

for(;;){
   Point p(x,y,z);
   pointsSet.insert(p);
}

как то так ...

▲ 2

Если не хочется избавляться от векторов, то можно сделать так:

class Point {
    typedef std::vector<int> Coords;
public:
    Point(size_t index,
          const Coords& x,
          const Coords& y,
          const Coords& z)
        : index_(index),
          x_(x),
          y_(y),
          z_(z)
    {}

    bool operator<(const Point& other) const {
        return (x() < other.x())
               || (x() == other.x() && y() < other.y())
               || (x() == other.x() && y() == other.y() && z() < other.z());
    }

    int x() const {
        return x_[index_];
    }

    int y() const {
        return y_[index_];
    }

    int z() const {
        return z_[index_];
    }

private:
    size_t index_;
    const Coords& x_;
    const Coords& y_;
    const Coords& z_;
};

void removeDuplicates(std::vector<int>& x,
                      std::vector<int>& y,
                      std::vector<int>& z)
{
    std::set<Point> points;
    for (size_t i = 0; i < x.size(); ++i) {
        points.insert(Point(i, x, y, z));
    }
    std::vector<int> newX, newY, newZ;
    for (std::set<Point>::const_iterator it = points.begin();
         it != points.end();
         ++it)
    {
        newX.push_back(it->x());
        newY.push_back(it->y());
        newZ.push_back(it->z());
    } 
    x.swap(newX);
    y.swap(newY);
    z.swap(newZ);
}