【问题标题】:c++ convex hull in recursion method递归方法中的c ++凸包
【发布时间】:2016-06-27 06:46:50
【问题描述】:

我正在尝试调试“凸壳”jarvis 的算法。 “凸包”问题是,给定平面中 n 个点的集合 P,找到一个子集 CH(P),它形成包含所有其他点的凸多边形的顶点。 递归地编写这个函数,但永远停留在一个循环中并返回分段错误

    int main()
{
    vector<Point> hull(20);
    int n,x,y;
    cin >> n;
    vector<Point> ps;
    Point p;
//  Point p1,p2,q1,q2;

    while(cin >> x >> y)
    {   
        p.x = x;
        p.y = y;
        ps.push_back(p);
    }
    int base = find_leftmost_point(ps, n);
    hull.push_back(ps[base]);
    vector<Point> po = convexHull(ps, base, hull);
    cout << perimeter(po) << endl;
    return 0;
}

vector<Point> convexHull(vector<Point> points, int base, vector<Point> &hull)
{

    int p, q;

    p = base;   
    q = (p+1) % points.size();
    if (points.size() <= 3) 
    {

        return hull;
    }
    if(q == base)
    {
        return hull;
    }
    else
    {   
                for (int i = 0; i < points.size(); i++)
        {   
            if (orientation(points[p], points[i], points[q]) == 2)
            {
                q = i;
            }

        }
        cout<<points[q].x<<points[q].y<<endl;
        hull.push_back(points[q]);
        return convexHull(points, q, hull);
    }
}

double perimeter(vector<Point> P)
{
    double r = 0;
    for(int i = 1;i < P.size(); i++)
        r += sqrt(pow(P[i].x - P[i-1].x, 2) + pow(P[i].y - P[i-1].y, 2));
    return r;
}
int orientation(Point p, Point q, Point r)
{
    int val = (q.y - p.y) * (r.x - q.x) - (q.x - p.x) * (r.y - q.y);

    if (val == 0) 
        return 0;
    return (val > 0) ? 1 : 2;
}

int find_leftmost_point(vector<Point> points, int n)
{
    int l = 0;
    for (int i = 1; i < n; i++)
        if (points[i].x < points[l].x)
            l = i;
    return l;

}

【问题讨论】:

  • 您丢弃从递归调用返回的任何内容,而不是将其返回到先前的调用,这可能不是您想要的。编译器没有警告您缺少“返回”吗?

标签: c++ recursion vector convex-hull


【解决方案1】:

您当然可以返回向量。这本身不会导致段错误。可能导致此类错误的原因是:

  • hull.push_back(points[p]); 因为无法保证向量中有p+1
  • orientation(points[p], points[i], points[q]) 因为无法保证向量中有 p+1nq
  • 您最终会陷入无限递归。这应该使用您使用的输入数据进行分析。但是如果 n>base,你最终会递归地调用函数,而没有可以阻止它减少的整数。

编辑和解决方案:

使用您提供的其他信息,可以确保n==points.size()base&lt;n。从那里可以清楚地看出,p、i 和 q 将始终小于 n。这消除了前两个可能的错误。

但是用一个小样本运行你的代码,表明你在无休止地循环:一旦你将最后一个点添加到船体,你又开始添加第一个点。缺少什么,因此请确保您添加的点不在船体中。

您可以通过在 for 循环之后添加以下代码来做到这一点:

    auto srch=find(hull.begin(), hull.end(), points[q]); 
    if (srch!=hull.end()) {
        cout << "ALREADY IN"<<endl; 
        return hull;
    }

这里是online demo

【讨论】:

  • @user6051947 如果你确定base&lt;nn==points.size() 那么你将保持在界限内。但假设你从base=0 开始。然后将q 设置为循环中的下一个点。在这个阶段没有机会q==base,除非n ==1。因此,您的 for 循环将修复一个新的 q 并递归调用该函数。然后重新开始。它可以再次找到相同的 q,您将永远循环!我怀疑您的条件 if (q==base) ... 实际上应该在 for 循环之后:如果连续两次找到相同的 q,这将结束递归......
  • @user6051947 在您的附加代码和输入之后,我进行了显示无限递归的编辑,方法是检查您没有向船体添加一个已经存在的点。简单的好奇:您使用哪种凸包算法?
  • 贾维斯算法
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-02-07
  • 1970-01-01
  • 2014-03-07
  • 1970-01-01
  • 2018-11-12
  • 1970-01-01
  • 2018-07-11
相关资源
最近更新 更多