有没有办法使用单次传递对点进行排序?

时间:2014-01-13 14:42:31

标签: sorting math geometry coordinates computational-geometry

我在太空中有两个点,我需要找到点[xmin, ymax]。我可以使用x然后y在2次传球中完成,但我想在一次传球中完成。

有没有办法可以将这些值组合成一个浮点数,这样我就可以通过一种方式找到正确的点?

我想过做x+y,但我不知道这是否可靠,很可能不是,如[5,2],[2,5],最后一个会有更高的优先级。< / p>

有什么想法吗?

4 个答案:

答案 0 :(得分:3)

您不应对点列表进行排序以查找最大值和最小值,因为这将花费大约O(n * log(n))时间。相反,遍历列表一次,保持对您找到的最高和最低值的引用。这将花费O(n)时间。

min_x = myPoints[0].x;
max_y = myPoints[0].y;
for(Point p in myPoints){
    if (p.x < min_x){min_x = p.x;}
    if (p.y > max_y){max_y = p.y;}
}

编辑:来自维基百科的格雷厄姆扫描文章:

  

此算法的第一步是找到y坐标最低的点。如果最低y坐标存在于集合中的多个点中,则应选择候选中具有最低x坐标的点。

因此,分别找到min x和max y是不合适的,因为你要找的那个点可能没有。我们可以修改上面的代码,使用这些新标准。

candidate = myPoints[0];
for (Point p in myPoints){
    if (p.y < candidate.y or (p.y == candidate.y and px < candidate.x)){
        candidate = p;
    }
}

根据您对“最低”的定义,可能有必要将这些“小于”符号中的一些更改为“大于”符号。在某些坐标系中,(0,0)位于图形的左上角,屏幕越低,Y越大。在这种情况下,您应该使用if (p.y > candidate.y代替

答案 1 :(得分:1)

如果您试图根据词典顺序的某个变体(或者甚至是2D点上的某种其他顺序)找到最小点,那么只需遍历您的一组点,但使用自定义比较来查找/保留最低。以下是C ++中的一个示例,min_element来自STL,只是一个简单的循环(http://www.cplusplus.com/reference/algorithm/min_element/):

#include <algorithm>
#include <iostream>

using namespace std;

struct Point {
    int x, y;
};

struct PointCompare {
    bool operator()(const Point& p1, const Point& p2) const {
        if (p1.x < p2.x)
            return true;

        if (p1.x == p2.x)
            return p1.y > p2.y; // Your order: xmin then ymax?
          //return p1.y < p2.y; // Standard lexicographic order

        return false;
    }
};

int main()
{
    //      + 3
    // + 4
    //      + 0
    // + 2
    //          + 1
    const Point points[] = {
        { 1, 1 }, // 0
        { 2,-1 }, // 1
        { 0, 0 }, // 2
        { 1, 3 }, // 3
        { 0, 2 }, // 4
    };

    const Point* first = points;
    const Point* last = points + sizeof(points) / sizeof(Point);
    const Point* it = min_element(first, last, PointCompare());

    cout << it->x << ", " << it->y << endl;
}

答案 2 :(得分:1)

看起来你想要找到一个 max-min 点 - 一个在x坐标最小的点之间具有最大y坐标的点,对吗?

如果是,您可以将所有点存储在STL multimap 中,将x坐标映射到y坐标。此地图将自动排序,并且有可能在此地图中具有最小x坐标的点将只有一个。如果它不是单个点,则可以使用相同(最小)x坐标扫描所有点,以找到具有最大y坐标的点。它仍然需要两次传球,但第二次传球在统计上应该非常短。

如果你真的想要单通道解决方案,那么你可以将你的点存储到STL map ,将x坐标映射到y坐标的 set 。它需要更多的工作,但最终你会得到你的观点 - 你将在地图的开头看到它的x坐标,它的y坐标将在集合的末尾,对应于这个x坐标。

答案 3 :(得分:0)

1.可按排序值排序:x +(MAX * y)或y +(MAX * x)

  • 其中MAX足够大MAX> = abs(max(x)-min(x))或MAX> = abs(max(y)-min(y))

2.如果你有足够的记忆并且需要极速的速度

  • 然后您可以忽略排序并将排序值用作地址
  • x,y值必须转换为非负
  • x,y差异必须> = 1.0(理想情况下= 1.0),因此可以将它们用作地址
  • 排序后不允许或不需要重复点
  • 创建足够大的数组pnt []并将它们设置为未使用(例如x = -1,y = -1)
  • 像这样对输入点pnt0 []进行排序

    for (i=0i<points;i++)
     {
     x=pnt0[i].x;
     y=pnt0[i].y;
     pnt[x+(MAX*y)]=pnt[0];
     }
    
  • 如果需要,您可以打包pnt []数组以删除未使用的点,但这可以视为另一个传递

  • 但你可以记住最小,最大地址和仅在它们之间循环