order a vector of points based on another vector

僤鯓⒐⒋嵵緔 提交于 2019-12-01 15:55:45

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);

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.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!