Reputation: 477
I have a vector of points allPoints
and a vector of points badPoints
. I want to quickly get a set of goodPoints
where it is everything in allPoints that is not in badPoints. Currently I have:
int i = 0;
for (auto point : allPoints)
{
bool add = true;
for (auto x : badPoints)
{
if (point == x)
{
add = false;
break;
}
}
if (add)
{
goodPoints.insert(point);
}
i++;
}
I feel like this is slower than it should be but I don't know a better way to do it. Any ideas?
Upvotes: 1
Views: 837
Reputation: 2000
One approach you can do is to utilize use of another data structure called set unique;
Like instead of int, your point structure will come. For simplicity, I am making use of int.
So you implementation will look something like this
set<int> unique;
int i = 0;
for (auto point : badPoints)
{
unique.insert(point);
}
for(auto point : allPoints)
{
// it is not present in unique that means it's not a bad point
if(unique.find(point) == unique.end())
{
goodPoints.insert(point);
}
}
Hope this helps !
Upvotes: 0
Reputation: 73366
In case your data are not sorted, as suggested in the comments, use std::set_difference, like this:
#include <iostream> // std::cout
#include <algorithm> // std::set_difference, std::sort
#include <vector> // std::vector
int main () {
std::vector<int> allPoints = {5,10,15,20,25};
std::vector<int> badPoints = {50,40,30,20,10};
std::vector<int> v(10); // 0 0 0 0 0 0 0 0 0 0
std::sort(allPoints.begin(), allPoints.end()); // 5 10 15 20 25
std::sort(badPoints.begin(), badPoints.end()); // 10 20 30 40 50
std::vector<int>::iterator it = std::set_difference(
allPoints.begin(), allPoints.end(), badPoints.begin(), badPoints.end(), v.begin());
// 5 15 25 0 0 0 0 0 0 0
v.resize(it - v.begin()); // 5 15 25
std::cout << "Good points are " << (v.size()) << " in number:\n";
for (it=v.begin(); it!=v.end(); ++it)
std::cout << ' ' << *it;
std::cout << '\n';
return 0;
}
Output:
Georgioss-MacBook-Pro:~ gsamaras$ g++ -Wall -std=c++0x main.cpp
Georgioss-MacBook-Pro:~ gsamaras$ ./a.out
Good points are 3 in number:
5 15 25
Complexity
Up to linear in 2*(count1+count2)-1 (where countX is the distance between firstX and lastX): Compares and assigns elements.
Upvotes: 1
Reputation: 1047
Depending on the dimensions of the points, sorting might not be very viable (you can sort only in one dimension, for example). A better way would be to have a kD tree (e.g., if the points are in 2D, make a 2D-tree structure for the points), this way, instead of comparing all the points, you just need to compare with the points in the leaves of the tree.
Another, simpler but not as elegant, way is to divide your space into a grid. For example, if the points are in 2D, divide your plane into a NxN grid, and depending on which grid cell your cells fall in, check for overlap only inside that cell. You need to play with the size of the cells (or N) to find a balance between the number of cells and number of points inside the cells.
Upvotes: 2