凸包演算法詳解

2021-09-12 08:47:36 字數 2414 閱讀 4460

凸包(convex hull)是乙個計算幾何(圖形學)中的概念。

在乙個實數向量空間v中,對於給定集合x,所有包含x的凸集的交集s被稱為x的凸包。

x的凸包可以用x內所有點(x1,...xn)的線性組合來構造.

在二維歐幾里得空間中,凸包可想象為一條剛好包著所有點的橡皮圈。

用不嚴謹的話來講,給定二維平面上的點集,凸包就是將最外層的點連線起來構成的凸多邊型,它能包含點集中所有的點。

例子:假設平面上有p0~p12共13個點,過某些點作乙個多邊形,使這個多邊形能把所有點都「包」起來。當這個多邊形是凸多邊形的時候,我們就叫它「凸包」。如下圖: 

graham掃瞄法

時間複雜度:o(n㏒n) 

思路:graham掃瞄的思想是先找到凸包上的乙個點,然後從那個點開始按逆時針方向逐個找凸包上的點,實際上就是進行極角排序,然後對其查詢使用。 

步驟:把所有點放在二維座標系中,則縱座標最小的點一定是凸包上的點,如圖中的p0。

把所有點的座標平移一下,使 p0 作為原點,如上圖。

計算各個點相對於 p0 的幅角 α ,按從小到大的順序對各個點排序。當 α 相同時,距離 p0 比較近的排在前面。例如上圖得到的結果為 p1,p2,p3,p4,p5,p6,p7,p8。我們由幾何知識可以知道,結果中第乙個點 p1 和最後乙個點 p8 一定是凸包上的點。 

(以上是準備步驟,以下開始求凸包)

以上,我們已經知道了凸包上的第乙個點 p0 和第二個點 p1,我們把它們放在棧裡面。現在從步驟3求得的那個結果裡,把 p1 後面的那個點拿出來做當前點,即 p2 。接下來開始找第三個點:

連線p0和棧頂的那個點,得到直線 l 。看當前點是在直線 l 的右邊還是左邊。如果在直線的右邊就執行步驟5;如果在直線上,或者在直線的左邊就執行步驟6。

如果在右邊,則棧頂的那個元素不是凸包上的點,把棧頂元素出棧。執行步驟4。

當前點是凸包上的點,把它壓入棧,執行步驟7。

檢查當前的點 p2 是不是步驟3那個結果的最後乙個元素。是最後乙個元素的話就結束。如果不是的話就把 p2 後面那個點做當前點,返回步驟4。

最後,棧中的元素就是凸包上的點了。 

以下為用graham掃瞄法動態求解的過程: 

下面靜態求解過程

;node vex[1000];//存入的所有的點

node stackk[1000];//凸包中所有的點

int xx,yy;

bool cmp1(node a,node b)//排序找第乙個點

int main()

double s=0;

//for(i=1; i<=top; i++)//輸出凸包上的點

//cout<

for(i=1; i<=top; i++) //計算凸包的周長

s+=dis(stackk[i-1],stackk[i]);

s+=dis(stackk[top],vex[0]);//最後乙個點和第乙個點之間的距離

/*s+=2*pi*l;

int ans=s+0.5;//四捨五入

printf("%d\n",ans);*/

printf("%.2lf\n",s);}}

}

凸包演算法詳解 Graham掃瞄法

凸包 給定二維平面上的點集,凸包就是將最外層的點連線起來構成的凸多邊型,它能包含點集中所有的點。如圖所示 來自wiki 步驟 1 先將點按從下向上,從左向右的順序排序。排完序的第乙個點,一定為凸包上的點,記為p0。2,計算各個點相對於 p0 的幅角 按從小到大的順序對各個點排序。當 相同時,距離 p...

凸包 Graham Scan演算法

graham scan演算法是一種靈活的凸包演算法,時間複雜度是o nlogn 演算法細節 1.選出最左下角的點 排序 x最小,其次是y最小 2.其餘點按極角排序,在極角相等的情況下距離極點 p 0 最近的優先 3.用乙個棧 陣列 儲存凸包上的點,先把p 0 p 1 壓入棧。4.掃瞄每乙個點,用叉積...

凸包 Andrew演算法

凸包的定義如下 在乙個點集d中,按一定順序選取子集q 使得q中所有點順次連線所構成的封閉凸多邊形包住d中所有點 可以形象地理解為 有許多個釘子釘在平面上,用一根牛皮筋把所有點包住 如下圖 andrew演算法是graham演算法的變種。其主要思想為把凸包上的點依次放入棧中,如果發現形成了凹多邊形 叉積...