最小凸包演算法(Convex Hull)(1)-Graham掃描法 -計算幾何-演算法導論

來源:互聯網
上載者:User

基本問題:

平面上有n個點p1,p2, ..., pn, 要求求出一個面積最小的凸多邊形,使得這個多邊形包含所有平面上的點。

 

根據演算法導論上提供的兩個方法做一些介紹:

演算法1:

Graham掃描法

下面直接給出一段虛擬碼,方便描述:

GRAHAM-SCAN(Q)<br />{<br /> 1. 取出所有點鐘y座標最小的點作為初始點p0<br /> 2. 之後對於所有其他點,以p0為中心,點集中的所有點按關於p0的極角逆時針排序,形成p1,p2,..pn-1<br /> 3. push(p0,S)<br /> 4. push(p1,S)<br /> 5. push(P2.S)<br /> for(i: 3->m)<br /> {<br /> px = nexttoTop(S)<br /> py = Top(S)<br /> do while (如果(py->pi向量)相對於(px->py向量)是向右走的)<br /> pop(S)<br /> px = nextotTop(S)<br /> py = Top(S)<br /> push(pi, S);<br /> }<br /> return S;<br />}

最後S棧中儲存了所有凸多邊形的頂點集合

 

下面用圖示表示一下演算法的過程:

1.初始化所有的p0,p1,...pn-1

 

2.  p0,p1,p2入棧

 

3. 這時候棧頂元素是p2,次棧頂元素p1, 枚舉p3, 那麼可以看出, p2->p3的向量相對於p2->p1的向量是向右走的,所以棧中彈出p2, 壓入p3

 

 4. P4入棧,由於棧頂元素是p3,次棧頂元素是p1, 那麼p3->p4向量,相對於p1->p3向量是向左走的,所以壓入p4

 

 

5.由於棧頂元素是p4,次棧頂元素是p3, 那麼p4->p5向量,相對於p3->p4向量是向右走的,所以彈出p4,壓入p5

 

//xiaoxia版<br />#include <stdio.h><br />#include <math.h><br />#include <stdlib.h><br />typedef struct<br />{<br />double x;<br />double y;<br />}POINT;<br />POINT result[102];//儲存凸包上的點,相當於所說的棧S<br />POINT a[102];<br />int n,top;<br />double Distance(POINT p1,POINT p2)//兩點間的距離<br />{<br />return sqrt((p1.x-p2.x)*(p1.x-p2.x)+(p1.y-p2.y)*(p1.y-p2.y));<br />}<br />double Multiply(POINT p1,POINT p2,POINT p3) //叉積<br />{<br /> return ((p2.x-p1.x)*(p3.y-p1.y)-(p2.y-p1.y)*(p3.x-p1.x));<br />}<br />int Compare(const void *p1,const void *p2) //根據p0->p1的極值和p0->p2的極值進行比較,如果極值相同則用距離長度比較<br />{<br />POINT *p3,*p4;<br />double m;<br /> p3=(POINT *)p1;<br /> p4=(POINT *)p2;<br />m=Multiply(a[0],*p3,*p4) ;<br />if(m<0) return 1;<br />else if(m==0&&(Distance(a[0],*p3)<Distance(a[0],*p4)))<br />return 1;<br />else return -1;<br />}<br />//尋找凸包的過程,p0,p1,p2..的尋找過程在下面main中進行了<br />void Tubao()<br />{<br /> int i;<br /> result[0].x=a[0].x;<br /> result[0].y=a[0].y;<br /> result[1].x=a[1].x;<br /> result[1].y=a[1].y;<br /> result[2].x=a[2].x;<br /> result[2].y=a[2].y;<br /> top=2;<br /> for(i=3;i<=n;i++)<br /> {<br /> while(Multiply(result[top-1],result[top],a[i])<=0 && top>2)<br />top--;<br /> result[top+1].x=a[i].x;<br /> result[top+1].y=a[i].y;<br /> top++;<br /> }<br />}<br />int main()<br />{<br /> int i,p;<br /> double px,py,len,temp;<br /> while(scanf("%d",&n)!=EOF,n)<br /> {<br /> for(i=0;i<n;i++)<br /> scanf("%lf%lf",&a[i].x,&a[i].y);<br /> if(n==1)<br /> {<br /> printf("0.00/n");<br /> continue;<br /> }<br /> else if(n==2)<br /> {<br /> printf("%.2lf/n",Distance(a[0],a[1]));<br /> continue;<br /> }</p><p> //這裡的目的好像是找出y座標最小的點,之後把他定義為P0<br /> py=-1;<br /> for(i=0;i<n;i++)<br /> {<br /> if(py==-1 || a[i].y<py)<br /> {<br /> px=a[i].x;<br /> py=a[i].y;<br /> p=i;<br /> }<br /> else if(a[i].y==py && a[i].x<px)<br /> {<br /> px=a[i].x;<br /> py=a[i].y;<br /> p=i;<br /> }<br /> }<br /> //swap(a[0],a[p])<br /> temp=a[0].x;<br /> a[0].x=a[p].x;<br /> a[p].x=temp;<br /> temp=a[0].y;<br /> a[0].y=a[p].y;<br /> a[p].y=temp;</p><p> //用叉乘來實現排序的比較<br /> qsort(&a[1],n-1,sizeof(double)*2,Compare);<br /> a[n].x=a[0].x;<br /> a[n].y=a[0].y;</p><p> //調用tubao()<br /> Tubao();</p><p> len=0.0;<br /> for(i=0;i<top;i++)<br /> len=len+Distance(result[i],result[i+1]);<br /> printf("%.2lf/n",len);<br /> }<br /> return 0;<br />}<br /> 

 

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.