找到从列表到一个参考列表的最近点

时间:2012-11-02 14:20:06

标签: c++ algorithm stl

我有一对int坐标列表,如

list<pair<int,int> > coordinates;

我需要找到一个点原点的最近点,

class Point{
public:
float x;
float y;
};

我可以找到自定义比较器对象和排序,但我想知道有更快的方式与min?我试过了

class DistanceComparator{
public:
    DistanceComparator(const Point& p){origin=p;}
    inline bool operator<(std::pair<int,int> & lhs,std::pair<int,int > & rhs)
    {
        float deltaX1=lhs.first-origin.x;
        float deltaY1=lhs.second-origin.y;
        float deltaX2=rhs.first-origin.x;
        float deltaY2=rhs.second-origin.y;
        return (deltaX1*deltaX1+deltaY1*deltaY1)<(deltaX2*deltaX2+deltaY2*deltaY2);
    }
private:
    Pointorigin;
};

但是&lt;只需要一个参数。怎么做?

3 个答案:

答案 0 :(得分:5)

您的解决方案不是最佳的,因为它需要对整个列表进行排序,这是不需要的。您只需要最小元素,不需要对其余元素进行排序。我可能建议你研究std::partial_sort或者只是去突击队员并进行迭代(O(n)而不是O(n*log(n))排序)。

答案 1 :(得分:2)

正如Luchian Grigore所说,你不应该对点数进行排序。但是,我想在这里解决你的语法问题。

您不能将比较运算符作为类成员来比较两个其他对象。您只有两种可能性来定义比较运算符:

  1. 成员函数bool T::operator<(const U& rhs) const,其中this是左侧操作数。 (const-reference是可选的,我认为,但当然强烈推荐。)请注意T == U不一定是真的。

  2. 非成员函数bool operator<(const T& lhs, const U& lhs) const再次与T == U不一定是真的。

  3. 所以你不能有一个比较运算符,它可以访问你想拥有的三个对象:两个操作数,有点像“上下文”,可以参数化比较。

    为了解决这个问题,我知道以下两个解决方案(可能还有更多):

    1. 开始使用比较运算符时,将附加参数设置为全局变量。当然,这非常脏(全局变量在OOP中总是很脏)并且使排序不可重入。由于它太脏了我永远不会推荐它(但它仍然是可能的解决方案),因此我不会在这里给出示例代码。

    2. 使用谓词而不是operator <。有多种方法可以做到这一点。这是两个:

      如果你有c ++ 0x / c ++ 11可用:使用 lambda函数,它可以从客户端上下文中获取附加参数(你在哪里运行{ {1}}):

      std::sort

      如果您没有可用的c ++ 0x / c ++ 11:您仍然可以定义自定义谓词,以便在没有lambda函数的情况下以自定义方式比较这两个对象。您必须定义比较器辅助类:

      Point origin = ...;
      std::sort(..., [origin](const Point & a, const Point & b){
          return distance(a, origin) < distance(b, origin);
      });
      

      当然,你可以(像你一样)优化代码,不使用平方根来计算距离。示例代码只能让您了解如何对比较进行参数化。

答案 2 :(得分:1)

如果您需要多次查询坐标列表,可能需要考虑使用 Kd-tree 进行最近邻搜索。这将具有 O(log n)时间复杂度。 构建和查询Kd树大约是15-20行(可读)C ++代码。 看看Kd-tree wikipedia article 另请查看std::nth_element,您可以使用它来有效地构建您的Kd树(选择枢轴点并对容器进行分区(左右childeren,请参阅维基百科文章中的python代码)。

更新:我使用K最近邻搜索创建C++ N-dimensional K-d tree implementation。它包括一些单元测试,向您展示如何使用它。