![](/img/trans.png)
[英]Optimization on Algorithm to check “Whether for a given directed graph there is only one way to sort the graph using topological sort or not”
[英]Optimization of a clockwise sort algorithm
所以這是一個優化問題,我找不到答案。
我已經寫了一些代碼來計算給定隨機點集的凸包。 為了進行比較,我制作了自己的慢速O(n³)算法,使用了一些舊的OpenGL可視化它。 由於慢凸殼算法的性質,這些點根本沒有排序。 因此,排序僅在計算CH之后進行。
我的問題是,直到1000點,我在不到一秒鍾的時間內就獲得了視覺效果。 但是,要獲得10000點,則需要15到20分鍾的時間(我沒有等待更多)。 但是,如果我跳過排序代碼,並讓opengl顯示未排序的凸包頂點,則只需不到一分鍾的時間。 因此,正是ClockWise排序一直困擾着我們。 檢查代碼(某些名稱沒有意義,因為它們是在其他地方定義的):
// This code actually compares every pair iteratively with respect to the center point
// Consider a given vector "convex", which contains all the convex hull points unsorted
.
..
...
....
int avgx,avgy,sumx=0,sumy=0;
for (int i=0;i<convex.size();i++){
sumx+=convex.at(i).at(0);
sumy+=convex.at(i).at(1);
}
avgx=sumx/(convex.size()/2.0); //something like an internal point
avgy=sumy/(convex.size()/2.0);
sort(convex.begin(),convex.end()); //x-sort
int det,tempx,tempy;
for (int i=0;i<convex.size()-1;i++){
x1=convex.at(i).at(0);
y1=convex.at(i).at(1);
x2=convex.at(i+1).at(0);
y2=convex.at(i+1).at(1);
det=(x1-avgx)*(y2-avgy)-(x2-avgx)*(y1-avgy);
if (det<0){ //on which side of O-X1 lies X2?
tempx=convex.at(i).at(0); //swapping points
tempy=convex.at(i).at(1);
convex.at(i).at(0)=convex.at(i+1).at(0);
convex.at(i).at(1)=convex.at(i+1).at(1);
convex.at(i+1).at(0)=tempx;
convex.at(i+1).at(1)=tempy;
i=-1; //check again the new vector from the beginning
}
}
return convex;
顯示部分:
glColor3f(0.8, 0.2, 0.2);
glPointSize(3);
glBegin(GL_LINE_LOOP);
for (int i=0;i<count;i++){
glVertex2f(convexHull.at(i).at(0),convexHull.at(i).at(1));
}
glEnd();
據我所知,這種方法(通過比較交叉產品)是最有效的。 但是,在此之前,我寫了一些骯臟的代碼,實際上速度更快,因為它在8分鍾內給了我視覺效果。 我不想保留它,因為它太臟太長了,它比較干凈但是很慢(如果它真的可以工作的話……)。 那么,我是否應該等待10000個凸點的CW這么多,還是我缺少什么?
如有任何想法,我將不勝感激,如果需要添加其他內容,請告知我。
一般來說,這個問題有點奇怪。 大多數2D凸包算法(我所知道的所有算法)都按順時針或逆時針順序給出點(頂點)列表,或者可以對其進行簡單修改。
無論如何,由於有幾種良好的2D凸包確定方法可以在O(N ^ 2)或更快的速度下運行,因此您可以使用其中一種將數據按順時針順序“排序”。 我的意思是,您可以對數據運行CH算法,並按所需順序獲得結果。
這是我想得到的示例代碼,它可以滿足您的要求:
#define TURN_DIR(p1,p2,p3) (p1.x * p2.y - p1.y * p2.x + \
p2.x * p3.y - p2.y * p3.x + \
p3.x * p1.y - p3.y * p1.x)
#define LAST(cntnr) (cntnr).back()
#define BEFORE_LAST(cntnr) (cntnr)[(cntnr).size() - 2]
void ConvexHull (std::vector<Point> & pts)
{
std::sort (pts.begin(), pts.end());
std::vector<Point> lower, upper;
for (unsigned i = 0; i < pts.size(); ++i)
{
while (lower.size() > 1 && TURN_DIR(BEFORE_LAST(lower), LAST(lower), pts[i]) <= 0)
lower.pop_back ();
while (upper.size() > 1 && TURN_DIR(BEFORE_LAST(upper), LAST(upper), pts[i]) >= 0)
upper.pop_back ();
lower.push_back (pts[i]);
upper.push_back (pts[i]);
}
upper.insert (upper.end(), lower.rbegin() + 1, lower.rend() - 1);
pts.swap (upper);
}
有幾點要考慮:
pts
返回其輸出。 Point
結構是一個簡單的結構(或類),具有兩個公共成員x
和y
,以及一個小於運算符( operator <
),該operator <
非常簡單地根據x
和y
。 while
循環中的<= 0
和>= 0
測試分別替換為< 0
和> 0
。 讓我強調一下:盡管上面的代碼是CH實現,但是您可以使用它僅按順時針纏繞順序對點進行排序(如果它們已經形成凸包)。
您已經實現了Bubble Sort ,它是O(n 2 )。 您可以通過將STL sort
與適當的比較函子一起使用來獲得O(n log(n))。
這是第一步。 它使用了非傳遞比較器,但似乎可以在我的測試用例中使用,並且我認為通常是正確的:
struct clockwise : public binary_function<vector<int>, vector<int>, bool>
{
bool operator()(vector<int> A, vector<int> B)
{
int det=(A[0]-avgx)*(B[1]-avgy)-(B[0]-avgx)*(A[1]-avgy);
return(det<0);
}
static int avgx, avgy;
};
int clockwise::avgx = 0;
int clockwise::avgy = 0;
...
int clockwise::avgx=sumx/(convex.size()/2.0);
int clockwise::avgy=sumy/(convex.size()/2.0);
sort(convex.begin(),convex.end(), clockwise()); //clockwise-sort
編輯:
非傳遞式比較器不是一個好主意。 這是更可靠的:
#include <math.h>
...
struct clockwise : public binary_function<vector<int>, vector<int>, bool>
{
bool operator()(vector<int> A, vector<int> B)
{
return(atan2(A[0]-avgx, A[1]-avgy) < atan2(B[0]-avgx, B[1]-avgy));
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.