计算几何凸包的算法 Andrew和Melkman算法

先介绍下二者的时间复杂度:

Andrew算法是葛立恒扫描法的变种,但是更快,时间O(nlogn)。

Melkman算法是采用双端队列,时间O(n)。

第一种是经典算法,第二种则是在解决时间要求高的问题上的一个也是目前我所知道最快的。

Andrew代码如下:

int Andrew(Point *p,int n,Point *q)
{
  sort(p,p+n);
  int m=0;
  for(int i=0;i<n;i++)
  {
    while(m>1&&Cross(q[m-1]-q[m-2],p[i]-q[m-2])<=0) m--;
    q[m++]=p[i];
  }
  int k=m;
  for(int i=n-2;i>=0;i--)
  {
    while(m>k&&Cross(q[m-1]-q[m-2],p[i]-q[m-2])<=0) m--;
    q[m++]=p[i];
  }
  if(n>1) m--;
  return m;
}
Melkman代码如下:

double Cross(Vector A,Vector B) { return A.x*B.y - A.y*B.x;}
double side(Point a,Point b,Point p)
{
  Vector A=Vector(b.x-a.x,b.y-a.y);
  Vector B=Vector(p.x-a.x,p.y-a.y);
  return Cross(A,B);
}
void Melkman(int n,int &head,int &tail)
{
  int i;
  head=tail=n;
  ch[tail++]=p[0];
  for(i=0;i<n;i++)
  {
    ch[tail]=p[i];
    if(side(ch[head],ch[head+1],p[i+1])) break;
  }
  if(n<3) return;
  ch[++tail]=ch[--head]=p[++i];
  if(side(ch[n],ch[n+1],ch[n+2])<0) swap(ch[n],ch[n+1]);
  for(++i;i<n;i++)
  {
    if(side(ch[head+1],ch[head],p[i])<0&&
       side(ch[tail-1],ch[tail],p[i])>0) continue;
    while(tail-head>1&&side(ch[head+1],ch[head],p[i])>=0)
      ++head;
    ch[--head]=p[i];
    while(tail-head>1&&side(ch[side-1],ch[tail],p[i])<=0)
      --tail;
    ch[++tail]=p[i];
  }
}




  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值