问题
I am working on a C++ application.
I have 2 vectors of points
vector<Point2f> vectorAll;
vector<Point2f> vectorSpecial;
Point2f is defined typedef Point_<float> Point2f;
vectorAll has 1000 point while vectorSpecial has 10 points.
First Step:
I need to order the points in vectorSpecial depending on their order in vectorAll. So something like this:
For each Point in vectorSpecial
Get The Order Of that point in the vectorAll
Insert it in the correct order in a new vector
I can do a double loop and save the indexes. and then order the points based on their indexes. However this method is taking too long when we have lots of points (for example 10000 points in vectorAll and 1000 points in vectorSpecial so that's ten million iteration)
What are better methods of doing that?
Second Step:
Some points in vectorSpecial might not be available in vectorAll. I need to take the point that is closest to it (by using the usual distance formula sqrt((x1-x2)^2 + (y1-y2)^2)
)
This also can be done when looping, but if someone has any suggestions for better methods, I would appreciate it.
Thanks a lot for any help
回答1:
You can use std::sort
on vectorAll
with the Compare
function designed to take into account the contents of vectorSpecial
:
struct myCompareStruct
{
std::vector<Point2f> all;
std::vector<Point2f> special;
myCompareStruct(const std::vector<Point2f>& a, const std::vector<Point2f>& s)
: all(a), special(s)
{
}
bool operator() (const Point2f& i, const Point2f& j)
{
//whatever the logic is
}
};
std::vector<Point2f> all;
std::vector<Point2f> special;
//fill your vectors
myCompareStruct compareObject(all,special);
std::sort(special.begin(),special.end(),compareObject);
回答2:
For your First Step, you can use C++11 lambda's to great effect (special.size() = K, and all.size() = N)
#include <algorithm> // std::sort, std::transform, std::find, std::min_element
#include <iterator> // std::distance
std::vector<int> indices;
indices.reserve(special.size());
// locate exact index in all for every element of special. Complexity = O(K * N)
std::transform(special.begin(), special.end(), indices.begin(), [&all](Point2f const& s){
return std::distance(
all.begin(),
std::find(all.begin(), all.end(), s)
);
});
// sort special based on index comparison. Complexity = O(K * log(K))
std::sort(special.begin(), special.end(), [&indices](Point2f const& r, Point2f const& s){
auto i = std::distance(special.begin(), r);
auto j = std::distance(special.begin(), s);
return indices[i] < indices[j];
});
Explanation: first, for every point in special
, compute the distance between the beginning of all
and the location of the special element in all
, and store that result into the indices
vector. Second, sort all elements of special
by comparing for every pair of element the corresponding elements in the indices
vector.
For your Second Step, you only have to change the way you compute indices
// locate closest element in all for every element of special. Complexity = O(K * N)
std::transform(special.begin(), special.end(), indices.begin(), [&all](Point2f const& s){
return std::distance(
all.begin(),
std::min_element(all.begin(), all.end(), [&s](Point2f const& a){
return // Euclidean 2D-distance between a and s
});
);
});
Explanation: the only change compared to your First Step is that for every element in special
you find the element in all
that is closest to it, which you do by computing the minimum Euclidean distance as you suggested in your question.
UPDATE: You could make a space/time tradeoff by first storing the index of every element of all
into a std::unordered_map
hash table, and then doing the comparison between elements of special
based on lookup into that hash table. This reduces the time complexity of the first step to O(N) (assuming K < N), but adds O(N) of storage for the hash table.
来源:https://stackoverflow.com/questions/11341498/order-a-vector-of-points-based-on-another-vector