Geometri ve sayısal algoritmalar · 42 / 53
Convex hull, sweep line ve geometrik sağlamlık
Anla → iz sür → uygula → gerekçelendir
2 dk okuma · uygulama için ayrıca zaman ayırConvex hull, noktaları kapsayan en küçük dışbükey çokgendir, çember değildir. Andrew monotone chain önce noktaları sıralar, sonra alt ve üst zincir kurar. Üç noktanın yönünü cross product ile ölçeriz; yanlış dönüş yapan son nokta çıkarılır. Her nokta en fazla bir kez eklenip çıkarıldığı için zincir kurulması doğrusaldır. Graham scan aynı fikri kutupsal sıralamayla uygular; Jarvis march çıktıdaki h köşe için O(nh) çalışır.
Geometride işaret hatası bütün topolojiyi değiştirebilir. Floating-point değerlerine rastgele epsilon eklemek her ölçekte doğru değildir. Tam sayı koordinatlarında taşmayı önle; kayan noktalarda robust orientation predicates veya uygun exact arithmetic kullan. Tekrarlanan noktalar, bütün noktaların doğrusal olması ve sınırdaki doğrusal noktaların korunması sözleşmede belirtilmelidir.
Sweep line, x boyunca ilerleyen olaylar ve aktif küme üzerinden kesişim/alan problemlerini çözer. Olayların aynı x'te sıralanması ve aktif kümenin karşılaştırıcısı kritik ayrıntıdır. Voronoi/Delaunay yakınlık ilişkilerini modeller; her geometrik problem hull değildir. Mesafe karesiyle karşılaştırmak karekökten kaçınır ama koordinat taşmasını ortadan kaldırmaz.
Adım adım iz sürme
Kare köşeleri ve merkez noktası verildiğinde merkez zincirden çıkar; dört köşe kalır. <=0 testi doğrusal sınır noktalarını da çıkarır.
Maliyet ve varsayımlar
Monotone chain: O(n log n) zaman, O(n) alan. Kesişim algoritmasının maliyeti olay ve çıktı sayısına bağlıdır.
Çalıştırılabilir örnek
Python 3 ile çalıştır. Assert küçük bir örneği denetler; genel doğruluk ispatı değildir. Bazı ileri örnekler özellikle küçük model veya referans oracle'dır; tam üretim uygulaması değildir.
def hull(points):
points = sorted(set(points))
if len(points) <= 1: return points
def cross(a,b,c): return (b[0]-a[0])*(c[1]-a[1])-(b[1]-a[1])*(c[0]-a[0])
def chain(ps):
out=[]
for p in ps:
while len(out)>1 and cross(out[-2],out[-1],p)<=0: out.pop()
out.append(p)
return out
return chain(points)[:-1]+chain(points[::-1])[:-1]
assert len(hull([(0,0),(1,0),(1,1),(0,1),(.5,.5)]))==4KAVRADIĞINI KONTROL ET
Sıra sende
Bütün noktalar doğrusal olduğunda bu uygulama ne döndürür?
Çözümün mantığını göster
En uç iki nokta kalır. Sınırdaki bütün noktaları isteyen sözleşme için dönüş testi ve birleştirme ayrı ele alınmalıdır.
Bir adım ileri
- Örneği değiştirmeden önce girdi sözleşmesini ve invariantı yaz.
- Uygun olan boş, sınır, tekrar ve adversarial girdileri ekle. Basit bir oracle ile karşılaştır.
- Belirtilen modelde maliyeti çıkar; farklı girdi büyüklüklerini ölç ve farkları gerekçelendir.
Temel kaynaklar ve ders notları
Bu eğitimde özgün anlatım kullanıldı; aşağıdaki kaynaklar ispatlar ve ileri okumalar sunar. Bağlantılar daha geniş ders modülünü kapsayabilir.
Jeff Erickson · Algorithms ↗