我認爲首先要做的是按角度對所有街道進行排序,從而使所有平行的街道彼此靠近。
然後,假設一開始,你可以識別的角度正是和你需要對具有完全相同相同的角度街道。 (由於浮點精度以及由於所需街道在數據中可能不完全平行的事實,這並非真實情況,但我們暫時忘了這一點。)
然後所有排序的街道都可以被分成相同方向的組。在每個這樣的組中,存在如下定義的自然順序。考慮另一條垂直於所有街道的方向相同的線。對於任何這樣的街道,考慮與該垂直線的交叉點,並通過該交叉點對所有這些街道進行分類(我假設所有街道都是無限長的)。
此排序可以在沒有任何交集很容易做到,你只需要通過這個距離計算各街道從產地(或任何其他固定點)到街道線的距離和排序街道。 (如果你有一條由標準直線方程Ax+By+C=0
定義的街道,那麼這個距離原點的距離是C/sqrt(A*A+B*B)
。)
現在你已經擁有了所有需要的平行靠得很近的街道,這個排序順序非常接近。如果所有的街道都是無限長的,那麼最接近的兩條街道總是會一個接一個。有限長度的街道之間可能會有額外的街道,但我認爲在任何實際的數據中都會有很少的街道。所以,你可以採取一些距離差異的門檻,並檢查其中的所有對。
現在讓我們記住角度沒有精確定義。我可以建議那麼下面的方法。爲街道維護一個二叉搜索樹(類似於C++的std::map
),搜索鍵將是從原點到街道的距離。按順序沿街道排列,因爲它們按角度排序。在樹中,我們將保持角度相差小於某個閾值的所有街道。因此,在樹中的每條街道的每一次,其樹中的鄰居將具有不同於小於閾值的兩個角度,並且與起點的距離相差小於某個閾值。因此,對於每個街道,做到以下幾點:
- 這條街上添加到樹
- 對於這一切都在樹上,而是有自己的角度,從當前街道的角度也不同街道,清除這些從樹上的街道
- 現在處理添加的街道:查看樹中具有所需閾值內的搜索關鍵字(距離原點的距離)中的所有街道,並檢查一對(增加的街道,另一條街道)。
第一點是O(log N)
,第二個是O(log N)
每刪除街頭,如果你只是一味另一個指針指向一起到街上排序的角度陣列要刪除運行,第三個是O(log N)
%的人認爲鄰居街道。
一個非常粗糙的僞代碼:
sort lines by angle
r = 0 // the street to be deleted from the tree
for l=0..n-1
tree.add(street[l])
while street[r].angle<streel[l].angle-angle_threshold
tree.remove(street[r])
other_street=tree.prev(street[l])
while other_street.dist>street[l].dist-dist_threshold
process(street[l], other_street)
other_street = tree.prev(other_street)
other_street=tree.next(street[l])
while other_street.dist<street[l].dist+dist_threshold
process(street[l], other_street)
other_street = tree.next(other_street)
這裏tree.prev
找到以前的街道樹,即具有最大距離的街道是小於給定街的距離,tree.next
同樣發現了另一條街上。這兩項操作都可以在O(log N)
中完成。
這不會「循環」數組,即不會考慮一對位於排序數組非常末端而另一個位於最開始處的街道對,但這很容易解決。
你想做什麼?平行於起始節點和結束節點的街道平均具有相同的角度,但很可能不平行。你在尋找平行街道路段嗎?或者也許街道共享一個節點並朝同一個方向運行?你的問題描述得很好,但它看起來並不像你想解決的實際問題? –