日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

c语言凸包算法,基于C语言的凸包算法实现

發(fā)布時間:2023/12/10 编程问答 47 豆豆
生活随笔 收集整理的這篇文章主要介紹了 c语言凸包算法,基于C语言的凸包算法实现 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

基于C語言的凸包算法實(shí)現(xiàn)

非計算機(jī)專業(yè),代碼有些的不好的地方,大佬輕噴^ _ ^

根據(jù)要求,需要使用C語言實(shí)現(xiàn)凸包算法——Graham掃描法,本文將從算法理解、實(shí)現(xiàn)思路、遇到的問題及其解決方案三個方面來闡述實(shí)現(xiàn)過程。

算法理解

凸包算法Graham掃描法,在不考慮排序算法的時間復(fù)雜度情況下,算法核心程序的時間復(fù)雜度為 O ( n l o g n ) O(n log n)O(nlogn),其主要算法思想如下:

首先是預(yù)處理過程,獲得一組隨機(jī)點(diǎn)集,選取位于二維空間中左下角的點(diǎn),即在縱坐標(biāo)(y)最小情況下橫坐標(biāo)(x)為最小的點(diǎn)P 0 P_0P0? 。以該點(diǎn)位極坐標(biāo)原點(diǎn)計算其余各點(diǎn)的極角θ \thetaθ,并根據(jù)極角大小進(jìn)行升序排序,若極角相同則按極徑大小按升序排列。由此得到一組按照極角排序的點(diǎn)集 { P 0 , P 1 , . . . , P n } \left\{P_0,P_1,...,P_n\right\}{P0?,P1?,...,Pn?}(如下圖所示)。

完成預(yù)處理之后即Graham算法的核心步驟,主要通過棧的方式來實(shí)現(xiàn)凸包點(diǎn)的計算。首先將P 0 , P 1 P_0,P_1P0?,P1?兩點(diǎn)壓棧,他們必然屬于凸包上的點(diǎn)。然后進(jìn)入迭代過程,以棧頂元素A [ t o p ] A[top]A[top]和次棧頂元素 A [ t o p ? 1 ] A[top-1]A[top?1]構(gòu)成的向量a ? \vec{a}a為基準(zhǔn)計算其與當(dāng)前P k P_kPk?點(diǎn)與棧頂元素A [ t o p ] A[top]A[top]構(gòu)成的向量b ? \vecb的叉積 ,若結(jié)果為正(零)則 b ? \vecb 位于 a ? \vec{a}a 的逆時針方向(共線),P k P_kPk?進(jìn)棧 ,若結(jié)果為負(fù)則 b ? \vecb 位于 a ? \vec{a}a 的順時針方向, A [ t o p ] A[top]A[top]出棧, P k P_kPk?進(jìn)棧,直至掃描至最后一個點(diǎn),將 P 0 P_0P0? 再次進(jìn)棧是凸包閉合。

由于要求順時針輸出凸包頂點(diǎn),則將棧中元素從棧頂向棧底依次輸出即可。

實(shí)現(xiàn)思路及過程

根據(jù)Graham掃描法的算法理解,將程序?qū)崿F(xiàn)分為了隨機(jī)點(diǎn)坐標(biāo)初始化、極角計算及排序、Graham核心算法和結(jié)果輸出四個模塊共計8個函數(shù)進(jìn)行編碼實(shí)現(xiàn)。

結(jié)構(gòu)體定義

// 點(diǎn)坐標(biāo)

typedef struct POINT {

int x;

int y;

}Point;

坐標(biāo)初始化

首先構(gòu)造存儲點(diǎn)坐標(biāo)的結(jié)構(gòu)體Point,該結(jié)構(gòu)體中僅包含橫坐標(biāo)x和縱坐標(biāo)y。根據(jù)要求需要隨機(jī)生成100個點(diǎn),使用宏定義點(diǎn)集大小(SIZE)為100。使用庫下的rand()函數(shù)以當(dāng)前系統(tǒng)時間為種子生成 0 ≤ x < 50 , 0 ≤ y < 50 0\le x<50,0\le y<500≤x<50,0≤y<50 的點(diǎn),并依次存入大小為SIZE的Point的類型的一維數(shù)組中。

void InitPoint(Point* p) {

int i;

srand(time(0));

for (i = 0; i < SIZE; i++) {

(p + i)->x = (int)(rand() % 50);

(p + i)->y = (int)(rand() % 50);

}

}

極角計算及排序

首先選取點(diǎn)集中位于左下角的點(diǎn),采用的方法為先找出縱坐標(biāo) 最小的坐標(biāo)點(diǎn)(集),然后在其中找出橫坐標(biāo) 最小的坐標(biāo)點(diǎn),記錄該點(diǎn)位于原始點(diǎn)集的位置,將其與第一個點(diǎn)進(jìn)行交換。接著使用庫下的atan()函數(shù)計算各點(diǎn)的極角,并將其記錄在double類型大小為SIZE的一維數(shù)組angle中,令極坐標(biāo)原點(diǎn)的極角: a n g l e [ 0 ] = 0 angle[0] = 0angle[0]=0。使用冒泡排序算法對極角進(jìn)行排序,同時改變點(diǎn)集中各點(diǎn)的順序。在排序是要考慮當(dāng)極角相同時按極徑從小到大排序。

Graham核心算法

根據(jù)算法分析結(jié)果,定義一個Point類型的一維數(shù)組作為??臻g,定義棧頂定位變量top,用于標(biāo)記棧頂元素在棧中的位置,定義臨時變量temp_point用記錄當(dāng)前掃描到的坐標(biāo)點(diǎn),定義叉積計算函數(shù),返回值為布爾類型。當(dāng)叉積為非負(fù)時返回true,否則返回false。判斷temp_point和棧頂元素,次頂元素三個點(diǎn)組成的兩個向量的方向,若叉積返回值為正,則將temp_point進(jìn)棧,否則將當(dāng)前棧頂元素出棧,繼續(xù)判斷現(xiàn)在的棧頂元素和次頂元素與temp_point三個點(diǎn)的向量叉積……

得到包含所有凸包頂點(diǎn)的棧數(shù)組,最后將 點(diǎn)進(jìn)棧形成封閉凸包,在形成封閉凸包前需要對 以及當(dāng)前棧頂和次頂元素進(jìn)行判斷是否符合凸包結(jié)構(gòu),若符合則將 進(jìn)棧,反之將當(dāng)前棧頂元素出棧,重復(fù)判斷步驟直至符合為止。

int myGraham(Point* p, Point* p_stack) {

int top = -1; //棧頂指針

int p_index = 0; //點(diǎn)索引

Point temp_point;

top++; p_stack[top] = p[0]; p_index++; //push

top++; p_stack[top] = p[1]; p_index++; //push

while (p_index < SIZE) {

temp_point = p[p_index];

if (X(p_stack[top - 1], p_stack[top], temp_point))

{

top++; p_stack[top] = temp_point;//push

}

else {

top--;//pop

continue;

}

p_index++;

}

while (TRUE) {

if (!X(p_stack[top - 1], p_stack[top], p[0])) {

top--;

}

else {

break;

}

}

top++; p_stack[top] = p[0];

return top;

}

結(jié)果輸出

為了使結(jié)果更直觀,定義了一個輸出函數(shù),能夠輸出凸包頂點(diǎn)坐標(biāo),并在二維坐標(biāo)中,顯示點(diǎn)。

運(yùn)行結(jié)果

來源:oschina

鏈接:https://my.oschina.net/u/4355012/blog/4274913

總結(jié)

以上是生活随笔為你收集整理的c语言凸包算法,基于C语言的凸包算法实现的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。