【问题标题】:order a vector of points based on another vector根据另一个向量对点向量进行排序
【发布时间】:2012-07-05 16:34:08
【问题描述】:

我正在开发一个 C++ 应用程序。

我有 2 个点向量

vector<Point2f> vectorAll;
vector<Point2f> vectorSpecial;  

Point2f 定义为typedef Point_&lt;float&gt; Point2f;

vectorAll 有 1000 分,而 vectorSpecial 有 10 分。

第一步:

我需要根据它们在 vectorAll 中的顺序对 vectorSpecial 中的点进行排序。 所以是这样的:

For each Point in vectorSpecial
    Get The Order Of that point in the vectorAll
    Insert it in the correct order in a new vector

我可以做一个双循环并保存索引。然后根据它们的索引对点进行排序。但是,当我们有很多点时(例如,vectorAll 中的 10000 个点和 vectorSpecial 中的 1000 个点,所以这是一千万次迭代),这种方法花费的时间太长了

有什么更好的方法?

第二步:

vectorSpecial 中的某些点可能在 vectorAll 中不可用。我需要取离它最近的点(使用通常的距离公式sqrt((x1-x2)^2 + (y1-y2)^2))

循环时也可以这样做,但如果有人对更好的方法有任何建议,我将不胜感激。

非常感谢您的帮助

【问题讨论】:

  • 请注意,调用 STL 算法并不能消除循环,它只是将它们隐藏在抽象层后面。

标签: c++ sorting c++11 vector stl-algorithm


【解决方案1】:

您可以在vectorAll 上使用std::sort 和Compare 函数,该函数旨在考虑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);

【讨论】:

  • 看来这就是我需要的。但有两件事:1)在运算符函数中,它以2个点作为输入,我比较它们的x和y? 2)我需要对“特殊”向量而不是“全部”进行排序,所以我是否通过调用std::sort(special.begin(),special.end(),compareObject); 对其进行排序?我对 C++ 不是很有经验,谢谢你的回答
  • @Youssef 好的。然后您的操作员应该将 2 个点作为参数,而不是整数 - 这只是一个示例。对于第二个问题,是的,我以为您想对所有内容进行排序。将编辑。
  • @LuchianGrigore,算子的输入可以是不同的类型吗?那么 Point2f 和 Point3f 呢?与逻辑和其他输入相匹配?
  • 可以,但是你不能有不同类型的容器。
【解决方案2】:

对于你的第一步,你可以使用 C++11 的 lambda 来达到很好的效果(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];
});

解释:首先,对于special中的每个点,计算all的开头到all中特殊元素的位置之间的距离,并将结果存储到indices 向量。其次,通过比较每对元素与indices 向量中的对应元素,对special 的所有元素进行排序。

对于您的第二步,您只需更改计算索引的方式

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

解释:与您的第一步相比,唯一的变化是对于special 中的每个元素,您会在all 中找到最接近它的元素,您可以通过计算最小值来做到这一点您在问题中建议的欧几里得距离。

更新:您可以通过首先将all 的每个元素的索引存储到std::unordered_map 哈希表中,然后在@987654333 的元素之间进行比较来进行空间/时间权衡@ 基于对该哈希表的查找。这将第一步的时间复杂度降低到了 O(N)(假设 K

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-12-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多