格雷厄姆扫描算法 -> 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<9; i++)
?你意识到array[0]
是一个有效的索引,对吧?很高兴提及您更改的什么:您的operator<
是错误的,并且正如我的回答所指出的那样,您确实将浮点数打印为小数。以上是关于格雷厄姆扫描算法 -> sqrt 和 arctan2 巨大的价值的主要内容,如果未能解决你的问题,请参考以下文章