格雷厄姆扫描算法 -> sqrt 和 arctan2 巨大的价值

Posted

技术标签:

【中文标题】格雷厄姆扫描算法 -> sqrt 和 arctan2 巨大的价值【英文标题】:Graham Scan Algorithm -> sqrt and arctan2 huge values 【发布时间】:2013-12-09 23:50:50 【问题描述】:

我必须实现格雷厄姆扫描算法。 这是我的代码:

    /*
    Graham's algorithm'
    */

    #include <stdio.h>
    #include <stdlib.h>
    #include <conio.h>

    #include <stack>
    #include <vector>
    #include <math.h>

    #include <algorithm>
    #include <cstdlib>

    using namespace std;
    struct Tpoint
    
        int x;
        int y;
    ;

    struct AR
        double alpha;
        double r;
        int i;
    ; 


    bool operator<(AR p, AR q)
        if(p.alpha != p.alpha)
            return p.alpha < p.alpha;
         else 
            return p.r < p.r;
        
    



    int det(Tpoint p1, Tpoint p2, Tpoint p3)
        return p1.x*p2.y + p2.x*p3.y + p3.x*p1.y - p3.x*p2.y - p1.x*p3.y - p2.x*p1.y;
    


    int right_turn(stack<Tpoint,vector<Tpoint> > S,Tpoint p3)
        Tpoint p2;
        Tpoint p1;


        p2=S.top();
        S.pop();
        p1=S.top();
        S.push(p2);


        if (det(p1,p2,p3)>0)
        return 0;


        if (det(p1,p2,p3)<0)
        return 1;
    

    int main()

        vector<Tpoint> Q;

        //Stos pointów, na końcu zawiera wynik
        stack<Tpoint,vector<Tpoint> > S;

        Tpoint point;


    Tpoint array[]=3,-2, -3,-2, 6,4, -6,1, 4,5, 0,0, 3,4, -3,3, -2,2, 0,6;
    Tpoint point00=array[0];
    int xMax = array[0].x;
    int yMin = array[0].y;
    int i;
    for (i=0; i<10; i++)
        if (array[i].y<yMin)
            if(array[i].x>xMax)
                xMax=array[i].x;
                yMin=array[i].y;
                point00=array[i];


            
        
    

    //sorting section start

    printf("%d %d \n \n",point00.x, point00.y);
    Q.push_back(point00);

    Tpoint arrayCLONE[10];
    AR arrayAR[10];
    for (i=0; i<10; i++)
                arrayAR[i].alpha=0.0;
                arrayAR[i].r=0.0;
                arrayAR[i].i=i;
                arrayCLONE[i] = array[i]; 

                array[i].x-=point00.x;
                array[i].y-=point00.y;

    



    for (i=0; i<10; i++)
        if ((array[i].x != point00.x) && (array[i].y != point00.y)) 
            arrayAR[i].alpha=atan2(array[i].y, array[i].x);
            arrayAR[i].r=sqrt(array[i].x*array[i].x+array[i].y*array[i].y);


            printf("alpha= %d, r= %d \n",arrayAR[i].alpha,arrayAR[i].r);
            printf("x= %d, y= %d\n",array[i].x, array[i].y);
        else

        arrayAR[i].alpha=9999;
        arrayAR[i].r=9999;
        arrayAR[i].i=0;
        

    

    sort (arrayAR, arrayAR + 10);

    for (i=0; i<10; i++)
        if (arrayAR[i].alpha<1000)
            Q.push_back(arrayCLONE[arrayAR[i].i]);
        //  printf("i =%d \n",i);
            printf("x =%d \n",arrayCLONE[arrayAR[i].i].x);
            printf("y =%d \n",arrayCLONE[arrayAR[i].i].y);
            printf("_____ \n");

        //  printf("index i =%d \n",arrayAR[i].i);
        
    


    //sorting section end


    S.push(Q[0]);
    S.push(Q[1]);
    S.push(Q[2]);

    for (int i=3;i<10; i++)
    while (right_turn(S,Q[i])==1)
        S.pop();
        S.push(Q[i]);
    


    printf("points: \n");
    while (!(S.empty()))
    
        point=S.top();
        S.pop();
        printf("(%d,%d) ",point.x,point.y);
    
        printf("\n..");
        getch();
        return 0;
    

它在排序部分不起作用。函数 _arctan2() 和 _sqrt() 返回较大的值。即 sqrt 返回 -1464986461。为什么会发生? 结果,点不是按 alfa 排序的,而是以未知的方式排序的。如果我手动设置点的顺序,算法就可以正常工作。

你能告诉我它不工作的方式吗?

【问题讨论】:

我在年轻的时候做过一些 Graham 扫描实现,你实际上不需要计算 sqrt 或 atan(如果点具有 int 坐标,则只需 int 操作)。请记住 det(A,B,C)=0 当且仅当 A、B 和 C 共线(我使用了您已经定义的函数)。换句话说,在您的运算符中,您可以只检查 det 的符号,而不是您当前正在执行的 (alpha1-alpha2) 的符号。如果 det 为零,请检查距离的平方(sqrt 保留 i 等式,因此您可以跳过额外的、昂贵的、不需要的浮点运算) 【参考方案1】:

您正在尝试将浮点值打印为十进制 (int) 值。

改为这样做:

printf("alpha= %f, r= %f \n",arrayAR[i].alpha,arrayAR[i].r);

%d 表示有符号十进制整数。查看 documentation 的 printf

%f 表示十进制浮点数

【讨论】:

【参考方案2】:

好的,现在可以了:

    /*
    Graham's algorithm'
    */

    #include <stdio.h>
    #include <stdlib.h>
    #include <conio.h>

    #include <stack>
    #include <vector>
    #include <math.h>

    #include <algorithm>
    #include <cstdlib>

    using namespace std;
    struct Tpoint
    
        int x;
        int y;
    ;

    struct AR
        double alpha;
        double r;
        int i;
    ; 


    bool operator<(AR p, AR q)
        if(p.alpha != q.alpha)
            return p.alpha < q.alpha;
         else 
            return p.r < q.r;
        
    



    int det(Tpoint p1, Tpoint p2, Tpoint p3)
        return p1.x*p2.y + p2.x*p3.y + p3.x*p1.y - p3.x*p2.y - p1.x*p3.y - p2.x*p1.y;
    


    int right_turn(stack<Tpoint,vector<Tpoint> > S,Tpoint p3)
        Tpoint p2;
        Tpoint p1;


        p2=S.top();
        S.pop();
        p1=S.top();
        S.push(p2);


        if (det(p1,p2,p3)>0)
        return 0;


        if (det(p1,p2,p3)<0)
        return 1;
    

    int main()

        vector<Tpoint> Q;

        //Stos pointów, na końcu zawiera wynik
        stack<Tpoint,vector<Tpoint> > S;

        Tpoint point;


    Tpoint array[]=-3,-2, 6,4, -6,1, 4,5, 0,6, 3,4, -3,5, 3,-2,  -2,2, 0,0, 1,1;
    Tpoint point00=array[0];
    int xMax = array[0].x;
    int yMin = array[0].y;
    int i;
    for (i=1; i<9; i++)

        if (array[i].y<yMin)
            yMin=array[i].y;


            
        


    for (i=1; i<9; i++)

        if (array[i].y==yMin)
                if(array[i].x>xMax)
                xMax=array[i].x;

                point00=array[i];


            
        
    


    //sorting section start

    printf("point00 x=%d y=%d \n \n",point00.x, point00.y);
    Q.push_back(point00);

    Tpoint arrayCLONE[11];
    AR arrayAR[11];
    for (i=0; i<10; i++)
                arrayAR[i].alpha=0.0;
                arrayAR[i].r=0.0;
                arrayAR[i].i=i;
                arrayCLONE[i] = array[i]; 


                array[i].x-=point00.x;
                array[i].y-=point00.y;

        //printf("x2= %d, y2= %d\n",array[i].x, array[i].y);
    



    for (i=0; i<11; i++)

        if (((array[i].x != 0) || (array[i].y != 0))) 

            arrayAR[i].alpha=atan2(array[i].y, array[i].x);
            arrayAR[i].r=sqrt(array[i].x*array[i].x+array[i].y*array[i].y);

            arrayAR[i].i=i;
            printf("alpha= %f, r= %f , x= %d, y=%d\n",arrayAR[i].alpha,arrayAR[i].r,array[i].x, array[i].y);

        else

        arrayAR[i].alpha=9999;
        arrayAR[i].r=9999;
        arrayAR[i].i=16;
        

    

    sort (arrayAR, arrayAR +10);
    Tpoint temp;
    for (i=0; i<10; i++)
        if (arrayAR[i].alpha<1000 && arrayAR[i].alpha>0.0)

            Q.push_back(arrayCLONE[arrayAR[i].i]);
        //  printf("i =%d \n",i);
            printf("x =%d \n",arrayCLONE[arrayAR[i].i].x);
            printf("y =%d \n",arrayCLONE[arrayAR[i].i].y);
            printf("_____ \n");

        //  temp.x=arrayCLONE[arrayAR[i].i].x;
        //  temp.y=arrayCLONE[arrayAR[i].i].y;
        //  printf("index i =%d \n",arrayAR[i].i);
        
    

    //Q.push_back(temp);
    //sorting section end


    S.push(Q[0]);
    S.push(Q[1]);
    S.push(Q[2]);

    for (int i=3;i<10; i++)
    while (right_turn(S,Q[i])==1)
        S.pop();
        S.push(Q[i]);
    

    //  S.push(Q[5]);


    printf("points: \n");
    while (!(S.empty()))
    
        point=S.top();
        S.pop();
        printf("(%d,%d) ",point.x,point.y);
    
        printf("\n...");
        getch();
        return 0;
    

【讨论】:

你为什么把你的for循环改成for (i=1; i&lt;9; i++)?你意识到array[0] 是一个有效的索引,对吧?很高兴提及您更改的什么:您的operator&lt; 是错误的,并且正如我的回答所指出的那样,您确实将浮点数打印为小数。

以上是关于格雷厄姆扫描算法 -> sqrt 和 arctan2 巨大的价值的主要内容,如果未能解决你的问题,请参考以下文章

Python中的重复直到或等效循环[重复]

leetcode(js)算法89之格雷编码

数据结构与算法之深入解析“格雷编码”的求解思路与算法示例

在Java中按极角对点进行排序

C++ 数学与算法系列之认识格雷码

格雷码(Gray Code)与8421二进制码之间的转换算法 (LeetCode89)