Algoritmusok és adatszerkezetek II.



Hasonló dokumentumok
Geometriai algoritmusok

9. Geometriai algoritmusok

Geometriai algoritmusok

Geometriai algoritmusok

Algoritmusok és adatszerkezetek II.

Algoritmizálás, adatmodellezés 10. előadás

Geometriai algoritmusok. pont helyzete, konvex burok, ponthalmaz legközelebbi és legtávolabbi pontpárja, metsző szakaszpárok keresése

Számláló rendezés. Példa

Algoritmusok és adatszerkezetek II.

Algoritmizálás. Horváth Gyula Szegedi Tudományegyetem Természettudományi és Informatikai Kar

17. előadás: Vektorok a térben

14. Mediánok és rendezett minták

Specifikáció. B logikai formula, a bemeneti feltétel, K logikai formula, a kimeneti feltétel, A az algoritmus, amelyre az állítás vonatkozik.

8. Mohó algoritmusok Egy esemény-kiválasztási probléma. Az esemény-kiválasztási probléma optimális részproblémák szerkezete

Algoritmusok és adatszerkezetek II.

2. Rekurzió. = 2P2(n,n) 2 < 2P2(n,n) 1

Adatszerkezetek I. 10. előadás

Bánsághi Anna 2014 Bánsághi Anna 1 of 68

Geometriai algoritmusok

A számítástudomány alapjai. Katona Gyula Y. Számítástudományi és Információelméleti Tanszék Budapesti Műszaki és Gazdaságtudományi Egyetem

Edényrendezés. Futási idő: Tegyük fel, hogy m = n, ekkor: legjobb eset Θ(n), legrosszabb eset Θ(n 2 ), átlagos eset Θ(n).

Specifikáció. B logikai formula, a bemeneti feltétel, K logikai formula, a kimeneti feltétel, A az algoritmus, amelyre az állítás vonatkozik.

Koordináta-geometria feladatok (emelt szint)

A félév során előkerülő témakörök

GEOMETRIA 1, alapszint

Mindent olyan egyszerűvé kell tenni, amennyire csak lehet, de nem egyszerűbbé.

1. Alapfogalmak Algoritmus Számítási probléma Specifikáció Algoritmusok futási ideje

Számjegyes vagy radix rendezés

Mindent olyan egyszerűvé kell tenni, amennyire csak lehet, de nem egyszerűbbé. (Albert Einstein) Halmazok 1

Függvények Megoldások

1. ábra. Számláló rendezés

Algoritmusok helyességének bizonyítása. A Floyd-módszer

Információ megjelenítés Számítógépes ábrázolás. Dr. Iványi Péter

Algoritmusok és adatszerkezetek II.

b) Ábrázolja ugyanabban a koordinátarendszerben a g függvényt! (2 pont) c) Oldja meg az ( x ) 2

GEOMETRIAI FELADATOK 1. (ESETTANULMÁNY)

10. előadás. Konvex halmazok

Minimális feszítőfák Legyen G = (V,E,c), c : E R + egy súlyozott irányítatlan gráf. Terjesszük ki a súlyfüggvényt a T E élhalmazokra:

Adatszerkezetek. Nevezetes algoritmusok (Keresések, rendezések)

Nagy András. Feladatok a koordináta-geometria, egyenesek témaköréhez 11. osztály 2010.

Amortizációs költségelemzés

= Y y 0. = Z z 0. u 1. = Z z 1 z 2 z 1. = Y y 1 y 2 y 1

Felvételi vizsga mintatételsor Informatika írásbeli vizsga

Keresés és rendezés. A programozás alapjai I. Hálózati Rendszerek és Szolgáltatások Tanszék Farkas Balázs, Fiala Péter, Vitéz András, Zsóka Zoltán

MATEMATIKA ÉRETTSÉGI TÍPUSFELADATOK KÖZÉPSZINT Függvények

Elmaradó óra. Az F = (V,T) gráf minimális feszitőfája G-nek, ha. F feszitőfája G-nek, és. C(T) minimális

4. Fuzzy relációk. Gépi intelligencia I. Fodor János NIMGI1MIEM BMF NIK IMRI

... fi. ... fk. 6. Fabejáró algoritmusok Rekurzív preorder bejárás (elsőfiú-testvér ábrázolásra)

10. Gráf absztrakt adattípus, gráfok ábrázolása

MATEMATIKA ÉRETTSÉGI TÍPUSFELADATOK MEGOLDÁSAI KÖZÉPSZINT Függvények

INFORMATIKA javítókulcs 2016

Tartalom Keresés és rendezés. Vektoralgoritmusok. 1. fejezet. Keresés adatvektorban. A programozás alapjai I.

Oktatási Hivatal. 1 pont. A feltételek alapján felírhatók az. összevonás után az. 1 pont

Önszervező bináris keresőfák

Az egyenes és a sík analitikus geometriája

Gráfok, definíciók. Gráfok ábrázolása. Az adott probléma megoldásához ténylegesen mely műveletek szükségesek. Ábrázolások. Példa:

Érdekes informatika feladatok

Egyenes és sík. Wettl Ferenc szeptember 29. Wettl Ferenc () Egyenes és sík szeptember / 15

A hiperbolikus síkgeometria Poincaré-féle körmodellje

A 2017/2018 tanévi Országos Középiskolai Tanulmányi Verseny második fordulójának feladatai. INFORMATIKA II. (programozás) kategória

9. Írjuk fel annak a síknak az egyenletét, amely átmegy az M 0(1, 2, 3) ponton és. egyenessel;

Algoritmizálás. Horváth Gyula Szegedi Tudományegyetem Természettudományi és Informatikai Kar

Intergrált Intenzív Matematika Érettségi

8. előadás. Kúpszeletek

Síkbeli egyenesek. 2. Egy egyenes az x = 1 4t, y = 2 + t parméteres egyenletekkel adott. Határozzuk meg

Programozás I. 3. gyakorlat. Szegedi Tudományegyetem Természettudományi és Informatikai Kar

Módosítható Prioritási sor Binomiális kupaccal. Wednesday, March 21, 12

Gyakorló feladatok ZH-ra

Algoritmusok és adatszerkezetek gyakorlat 07

Kupac adatszerkezet. A[i] bal fia A[2i] A[i] jobb fia A[2i + 1]

ARCHIMEDES MATEMATIKA VERSENY

MATEMATIKA ÉRETTSÉGI TÍPUSFELADATOK MEGOLDÁSAI KÖZÉP SZINT Függvények

Brósch Zoltán (Debreceni Egyetem Kossuth Lajos Gyakorló Gimnáziuma) Megoldások

Brósch Zoltán (Debreceni Egyetem Kossuth Lajos Gyakorló Gimnáziuma) Megoldások

Követelmény a 6. évfolyamon félévkor matematikából

BBTE Matek-Infó verseny mintatételsor Informatika írásbeli vizsga

Matematika A1a Analízis

Algoritmusok bonyolultsága

Felvételi tematika INFORMATIKA

7 7, ,22 13,22 13, ,28

2. ELŐADÁS. Transzformációk Egyszerű alakzatok

Koordinátageometria. , azaz ( ) a B halmazt pontosan azok a pontok alkotják, amelynek koordinátáira:

MATEMATIKA ÉRETTSÉGI TÍPUSFELADATOK KÖZÉP SZINT Függvények

Halmazelméleti alapfogalmak

Programozás alapjai 9. előadás. Wagner György Általános Informatikai Tanszék

Minimum követelmények matematika tantárgyból 11. évfolyamon

Brósch Zoltán (Debreceni Egyetem Kossuth Lajos Gyakorló Gimnáziuma) Megoldások

Gelle Kitti Algoritmusok és adatszerkezetek gyakorlat - 07 Hasítótáblák

Síkbeli egyenesek Egy egyenes az x = 1 4t, y = 2 + t parméteres egyenletekkel adott. Határozzuk meg

Tuesday, March 6, 12. Hasító táblázatok

Összeállította: dr. Leitold Adrien egyetemi docens

Hierarchikus adatszerkezetek

MATEMATIKA ÉRETTSÉGI TÍPUSFELADATOK MEGOLDÁSAI KÖZÉPSZINT Függvények

Algoritmuselmélet 2. előadás

Algoritmusok Tervezése. 6. Előadás Algoritmusok 101 Dr. Bécsi Tamás

Koordináta-geometria II.

I. VEKTOROK, MÁTRIXOK

A Fermat-Torricelli pont

A MAXIMUM-KUPACOL eljárás helyreállítja az A[i] elemre a kupactulajdonságot. Az elemet süllyeszti cserékkel mindaddig, amíg a tulajdonság sérül.

Vektorok és koordinátageometria

Átírás:

Algoritmusok és adatszerkezetek II. Horváth Gyula Szegedi Tudományegyetem Természettudományi és Informatikai Kar horvath@inf.u-szeged.hu

9. Geometriai algoritmusok Számos olyan gyakorlati számítási probléma van, amely megoldható olyan geometriai modellben, amelyben csak egyszerű objektumok, pontok, egyenesek, szakaszok, szögek, szögtartományok, poligonok szerepelnek. Ilyen alapvető feladatokat vizsgálunk. 9.1. Alapfogalmak Pont: (x,y) R R Szakasz Legyen p 1, p 2 pont. A p 1 és p 2 pont által meghatározott szakasz: p 1 p 2 = {p = (x,y) : x = α p 1.x + (1 α)p 2.x, y = α p 1.y + (1 α) p 2.y), α R, 0 α 1 Ha p 1 és p 2 sorrendje számít, akkor irányított szakaszról beszélünk, jele: p 1 p 2. Egyenes Egyenes megadása: 1. y = m x + b egyenlettel: azon (x, y) pontok halmaza, amelyekre teljesül az egyenlet. 2. ax + by + c = 0 egyenlettel. 3. Egyenes megadása két pontjával: e(p 1, p 2 )

9.2. Feladat: Pontok összekötése zárt, nem-metsző poligonná. Adott a síkon n darab pont, amelyek nem esnek egy egyenesre. A pontok (x, y) koordinátáikkal adottak, amelyek egész számok. A pontokat a 1,...,n számokkal azonosítjuk. Kössünk össze pontpárokat egyenes szakaszokkal úgy, hogy olyan zárt poligont kapjunk, amelyben nincs metsző szakaszpár. Egy ilyen zárt, nem-metsző poligon megadható a pontok azonosítóinak egy felsorolásával: a felsorolásban egymást követő pontokat kötjük össze egyenes szakaszokkal, továbbá, az utolsót az elsővel is összekötjük. Bemeneti specifikáció A poligon.be szöveges állomány első sora a pontok n(3 < n < 100000) számát tartalmazza. A további n sor mindegyike két egész számot tartalmaz, egy pont x és y koordinátáit, ( 20000 x,y 20000). A pontok nem esnek egy egyenesre. Kimeneti specifikáció A poligon.ki szöveges állományba a bemenetre kiszámított zárt, nem-metsző poligont leíró sorozatot kell kiírni.

Példa bemenet és kimenet poligon.be 6 2 0 1 4 0 2 3 2 2 4 2 6 poligon.ki 3 1 4 5 6 2

Megoldás Válasszuk ki a legkisebb x-koordinátájú pontot, ha több ilyen van, akkor ezek közül válasszuk a legkisebb y-koordinátájút. Ezt nevezzük (bal-alsó) sarokpontnak és jelöljük Q-val. Húzzunk (fél) egyenest a Q sarokpontból minden ponthoz. Rendezzük az egyeneseket a Q ponton áthaladó, x-tengellyel párhuzamos egyenessel bezárt (előjeles) szög alapján. p i φ(q, p i ) Q Q φ(q, p i ) p i 1. ábra. A p i ponthoz tartozó előjeles szög: φ(q, p i ).

Rendezzük a pontokat úgy, hogy a Q sarokpont legyen az első, és p i előbb legyen mint p j akkor és csak akkor, ha A φ(q, p i ) < φ(q, p j ), vagy φ(q, p i ) = φ(q, p j ) és p i közelebb van Q-hoz, azaz p i.x < p j.x, vagy φ(q, p i ) = φ(q, p j ) és p i.x = p j.x és p i.y < p j.y. Ha ebben a sorrendben kötjük össze a pontokat, kivéve, hogy az utolsó egyenesen lévő pontokat fordított sorrendben vesszük, akkor egy zárt, nem metsző poligont kapunk.

Q

6 5 4 3 Q 2 1

6 5 4 3 Q 2 1

6 5 4 3 Q 2 1

6 5 4 3 Q 2 1

6 5 4 3 Q 2 1

6 5 4 3 Q 2 1

6 5 4 3 Q 2 1

6 5 4 3 Q 2 1

6 5 4 3 Q 2 1

6 5 4 3 Q 2 1

6 5 4 3 Q 2 1

6 5 4 3 Q 2 1

Hogyan dönthető el, hogy φ(q, p i ) < φ(q, p j )? Minden i > 1-re π 2 < φ(q, p i) π 2 és ebben a tartományban a tangens függvény szigorúan p j p i p j.y Q.y p i.y Q.y Q p j.x Q.x p i.x Q.x 2. ábra. A φ(q, p i ) és φ(q, p j ) szögek viszonya. monoton növekvő, tehát φ(q, p i ) < φ(q, p j ) akkor és csak akkor, ha tan(φ(q, p i )) = p i.y Q.y p i.x Q.x < p j.y Q.y p j.x Q.x = tan(φ(q, p j)) Mivel Q sarokpont, így p i.x Q.x 0 és p j.x Q.x 0, tehát φ(q, p i ) < φ(q, p j )

akkor és csak akkor, ha (p i.y q.y)(p j.x Q.x) < (p j.y Q.y)(p i.x Q.x) Tehát a pontok rendezése: p i megelőzi p j -t akkor és csak akkor, ha (p i.y Q.y)(p j.x Q.x) < (p j.y Q.y)(p i.x Q.x) (1) (p i.y Q.y)(p j.x Q.x) = (p j.y Q.y)(p i.x Q.x) p i.x < p j.x (2) (p i.y Q.y)(p j.x Q.x) = (p j.y Q.y)(p i.x Q.x) p i.x = p j.x p i.y < p j.y (3) A sík pontjainak ábrázolására a PONT osztályt használjuk. public class Pont{ double x, y;//a pont x- és y-koordinátája int az; //a pont azonosítója Pont(double x, double y, int az){ this.x=x; this.y=y; this.az=az; Pont(double x, double y){ this.x=x; this.y=y; Pont(){

Tegyük fel, hogy van olyan SAROKRENDEZ eljárásunk, amely a P ponthalmazt rendezi a balalsó sarokpontjára vonatkozó polárszög szerint. Ekkor a feladat megoldása a következőképpen adható meg.

public class Poligon{ public static int[] Osszekot(Pont[] P){ int n=p.length; int[] S=new int[n]; //bal-alsó sarokpont szerinti polár-szög rendezés Geom.SarokRendez(P); for (int i=0; i<n; i++) S[i]=P[i].az; int i=n-2; while ( (P[n-1].y-P[0].y)*(P[i].x-P[0].x)== (P[i].y-P[0].y)*(P[n-1].x-P[0].x) ) i--; //egy helyes sorrend: int j=n-1; i++; while (i<j){ int x=s[i]; S[i++]=S[j]; S[j--]=x; S[0..i],S[n-1]..S[i+1] return S;

A SAROKRENDEZ eljárás a kupacrendezést használva rendezi a ponthalmazt. A REN- DEZ.KUPACREND1 eljárásnak paraméterként adjuk meg az r rendezési relációt, ami az (1-3) képletet valósítja meg. public static void SarokRendez(Pont[] P){ int mi=0; int n=p.length; for (int i=1; i<n; i++) //bal-also sarokpont meghatározása if (P[i].x<P[mi].x P[i].x==P[mi].x && P[i].y<P[mi].y) mi=i; Pont x=p[0]; //a sarokpont kicserélése P[0]=P[mi]; P[mi]=x; //P[0]-al SarokRend r=new SarokRend(P[0]); //a rendezési reláció létesítése Rendez.KupacRend1(P, r); //P[1..n-1] rendezése kupacrendezéssel

Tehát a teljes feladat megoldása: public class Polifelad{ public static void main (String[] args)throws IOException{ Pont[] P=BeOlvas(); int[] S=Poligon.Osszekot(P); KiIr(S); public static Pont[] BeOlvas()throws IOException{ Scanner bef = new Scanner(new File("poligon.be")); int n=bef.nextint(); bef.nextline(); Pont[] P=new Pont[n]; for (int i=0; i<n; i++){ int x=bef.nextint(); int y=bef.nextint(); bef.nextline(); P[i]=new Pont(x,y,i+1); bef.close(); return P;

static void KiIr(int[] S)throws IOException{ PrintWriter kif=new PrintWriter( new BufferedWriter( new FileWriter("poligon.ki") ) ); for (int x:s) kif.print(x+" "); kif.println(); kif.close();

Gyakran előfordul, hogy a síkon adott p 1 és p 2 pontra el kell dönteni, hogy a p 1 ponthoz képest a p 2 pont milyen forgásirányba esik. Tekintsük a 3. ábrán látható p 1 és p 2 vektorokat. A p 1 p 2 keresztszorzat a (0,0), p 1, p 2 és a p 1 + p 2 = (p 1.x + p 2.x, p 1.y + p 2.y) pontok által alkotott paralelogramma előjeles területeként értelmezhető. x 2 x 1 p 1 + p 2 y 1 p 2 y 2 y 2 p1 y 1 (0,0) x 1 x 2 3. ábra. A paralelogramma előjeles területe: T = (x 1 + x 2 )(y 1 + y 2 ) x 1 y 1 x 2 y 2 x 2 y 1 x 2 y 1 = x 1 y 1 + x 1 y 2 + x 2 y 1 + x 2 y 2 x 1 y 1 x 2 y 2 x 2 y 1 x 2 y 1 = x 1 y 2 x 2 y 1

y p 1 + p 2 y p 2 p (0,0) x p 1 (0,0) (a) x (b) 4. ábra. (a) A p 1 és p 2 vektorok keresztszorzata a paralelogramma előjeles területe. (b) A világos tartomány azokat a pontokat tartalmazza, amelyek a p-től órajárással egyező irányba esnek, a sötétebb pedig azokat, amelyek órajárással ellentétes irányba esnek p-től. p 1 p 2 = ( x1 x det 2 y 1 y 2 = x 1 y 2 x 2 y 1 = p 2 p 1. ) p 1 p 2 > 0 p 2 az órajárással ellentétes irányban van p 1 -hez képest. p 1 p 2 = 0 a (0,0), p 1 és p 2 pontok egy egyenesre esnek (kollineárisak). p 1 p 2 < 0 p 2 az órajárás irányban van p 1 -hez képest.

p2 p2 p1 p1 Még általánosabban, adott két csatlakozó irányított szakasz, p 0 p 1 és p 1 p 2, milyen irányba fordul p 1 p 2 a p 0 p 1 -hez viszonyítva? A válasz (p 1 p 0 ) (p 2 p 0 ) = (p 1.x p 0.x)(p 2.y p 0.y) (p 2.x p 0.x)(p 1.y p 0.y) keresztp0 p0 5. ábra. Csatlakozó szakaszok forgásiránya. szorzat előjele alapján megadható. (p 1 p 0 ) (p 2 p 0 ) > 0 : p 1 p 2 balra fordul, (p 1 p 0 ) (p 2 p 0 ) = 0 : p 0 p 1 és p 1 p 2 kollineárisak, (p 1 p 0 ) (p 2 p 0 ) < 0 : p 1 p 2 jobbra fordul.

public static int ForgasIrany(Pont p0, Pont p1, Pont p2){ /** Kimenet: +1 ha p0->p1->p2 balra fordul, * 0 ha p0,p1 és p2 kollineárisak, * -1 ha p0->p1->p2 jobbra fordul. */ double p1xp2=(p1.x-p0.x)*(p2.y-p0.y)-(p2.x-p0.x)*(p1.y-p0.y); return (int)math.signum(p1xp2); Annak eldöntése, hogy a kollineáris p 0, p 1, p 2 pontok esetén p 1 közelebb van-e p 0 -hoz, mint p 2 : public static boolean Kozel(Pont p0, Pont p1, Pont p2){ /** *Feltétel: (p0,p1,p2) kollineáris *Kimenet: p1 közelebb van p0-hoz, mint p2 */ return Math.abs(p1.x-p0.x)<Math.abs(p2.x-p0.x) Math.abs(p1.y-p0.y)<Math.abs(p2.y-p0.y) ;

max(p1.y,p2.y) q.y q p1 min(p1.y,p2.y) p2 min(p1.x,p2.x) q.x max(p1.x,p2.x) 6. ábra. A q pont a p 1 p 2 szakaszra esik, ha p 1, p 2 és q kollineárisak és min(p 1.x, p 2.x) q.x max(p 1.x, p 2.x) és min(p 1.y, p 2.y) q.y max(p 1.y, p 2.y). public static boolean Kozte(Pont p1, Pont p2, Pont q){ return Math.abs(p1.x-q.x)<=Math.abs(p2.x-p1.x) && Math.abs(p2.x-q.x)<=Math.abs(p2.x-p1.x) && Math.abs(p1.y-q.y)<=Math.abs(p2.y-p1.y) && Math.abs(p2.y-q.y)<=Math.abs(p2.y-p1.y) ;

A FORGASIRANY és a KOZEL felhasználásával megadhatjuk a bal-alsó sarokponthoz viszonyított polárszög szerinti rendezés rendezési relációját. /** *A this.sarok bal-alsó sarokponthoz viszonyított pollárszög szerinti rendez *rendezési relációja */ public class SarokRend implements Comparator<Pont>{ Pont sarok; //a ponthalmaz bal-alsó sarokpontja public int compare(pont p1, Pont p2){ if (p1.x==p2.x && p1.y==p2.y) return 0; int forg=geom.forgasirany(sarok,p1,p2); return (forg>0 forg==0 && Geom.Kozel(sarok,p1,p2))? -1:1; SarokRend(Pont q){ sarok=new Pont(q.x,q.y); SarokRend(){ sarok=new Pont();

Hasonlóképpen, tetszőleges q pontra vonatkozó polárszög szerinti rendezés rendezési relációja is megadható a FORGASIRANY és a KOZTE felhasználásával. 14 13 11 12 2 3 1 q 9 10 7 4 5 6 8 7. ábra. A q pontra vett polárszög szerinti rendezés. A pont mellé írt szám a pontnak a rendezésbeli sorszáma.

/** A this.polar ponthoz viszonyított pollárszög szerinti rendezés * rendezési relációja */ public class PolarRend implements Comparator<Pont>{ private Pont polar; public int compare(pont p1, Pont p2){ if (p1.x==p2.x && p1.y==p2.y) return 0; int forg=geom.forgasirany(polar,p1,p2); switch (forg){ case -1: return (p1.y<=polar.y && p2.y>polar.y)? -1:1; case 0 : return Geom.Kozte(polar,p2,p1) Geom.Kozte(p1,p2,polar) && (p1.y<polar.y p1.y==polar.y && p1.x<polar.x)? -1:1; case 1 : return (p1.y<=polar.y p2.y>polar.y)? -1:1; default : return 0; 9.3. Feladat: Pont helyzetének megállapítása. Adott a síkon egy zárt, nem-metsző poligon a csúcsainak p 1,..., p n órajárással ellentétes felsorolásával és adott egy q pont. Eldöntendő a q pontnak a poligonhoz képesti helyzete, azaz, hogy a belsejéhez tartozik-e, az oldalán van-e, avagy külső pont?

Megoldás Válasszunk egy olyan q 0 pontot, amely biztosan nem tartozik a poligon belsejéhez és a poligon egyetlen csúcsa sem esik a q 0 q szakaszra, legfeljebb ha q megegyezik valamelyik csúccsal. (Van ilyen pont.) Ha a q 0 q szakasz a poligon páratlan számú oldalát metszi, akkor q belső pont, egyébként külső. q q0 8. ábra. A q 0 q szakasz a poligon páratlan sok oldalát metszi, tehát belső pont.

q q0 9. ábra. A poligonnak több csúcsa is a q 0 q szakaszra esik.

A q 0 külső pont választása. Legyen q 0.y = max{p i.y p i.y < q.y,i = 1,...n és q 0.x = min{p i.x i = 1,...n 1. Ha a poligonnak nincs olyan csúcspontja, amelynek y-koordinátája kisebb, mint q.y, akkor q biztosan külső pont. A q0 pont ilyen választása esetén legfeljebb a q pont esik a poligon valamelyik q q0 10. ábra. A q 0 pont választása:q 0.y = max{p i.y p i.y < q.y,i = 1,...n és q 0.x = min{p i.x i = 1,...n 1. oldalára, amikor is q nem belső pont lesz. Ezt az esetet külön ellenőrizzük. Egyébként, a poligon bármely p i p i+1 oldalának akkor és csak akkor van közös pontja a q 0 q szakasszal, ha p i és p i+1 az e(q 0,q) egyenes különböző oldalára esik és a q 0 és q pont az e(p i, p i+1 ) egyenes különböző oldalára esik. Ez a feltétel a FORGÁSIRANY eljárás felhasználásával egyszerűen kiszámítható.

max(p1.y,p2.y) q.y q p1 min(p1.y,p2.y) p2 min(p1.x,p2.x) q.x max(p1.x,p2.x) 11. ábra. A q pont a p 1 p 2 szakaszra esik, ha p 1, p 2 és q kollineárisak és q.x p 1.x p2.x p1.x és q.x p 2.x p2.x p1.x /** a p1-p2 szakaszon van-e a q pont? */ public static boolean Szakaszon(Pont p1, Pont p2, Pont q){ double fir=(p1.x-q.x)*(p2.y-q.y)-(p2.x-q.x)*(p1.y-q.y); return fir==0.0 && Math.abs(q.x-p1.x)<=Math.abs(p2.x-p1.x) && Math.abs(q.x-p2.x)<=Math.abs(p2.x-p1.x) && Math.abs(q.y-p2.y)<=Math.abs(p2.y-p1.y) && Math.abs(q.y-p2.y)<=Math.abs(p2.y-p1.y) ;

/** Kimenet: -1 ha a q pont a poligon belsejében van, * 0 az oldalán van, * +1 ha kivül van */ public static int PontHelyzete(Pont[] P, Pont q){ int n=p.length; double y0=q.y; double x0=p[0].x; for (int i=1; i<n; i++){ if (P[i].y<q.y && (P[i].y>y0 y0==q.y) ) y0=p[i].y; if (P[i].x<x0) x0=p[i].x; Pont q0=new Pont(x0-1,y0); int metsz=0; for (int i=0; i<n; i++){ int ii=(i<n-1)? i+1: 0; if (Szakaszon(P[i], P[ii], q) ) return 0; if (ForgasIrany(P[i],P[ii],q0)*ForgasIrany(P[i],P[ii],q)<0 && ForgasIrany(q0, q, P[i])*ForgasIrany(q0, q, P[ii]) <0 ) metsz++; return (metsz % 2==1)? -1:1;

A algoritmus futási ideje legrosszabb esetben is a poligon csúcsainak n számával arányos, tehát O(n). 9.4. Metsző szakaszpárok Eldöntendő, hogy metszi-e egymást adott p 1 p 2 és q 1 q 2 szakasz? q2 p2 p2 p2 q1 q1 q2 p1 p1 q2 p1 q1 p2 p1 q2 q2 p1 q1 p2 q1 12. ábra. Szakaszpárok metszésének öt lehetséges esete.

public class Szakasz{ Pont bal, jobb; //a szakasz bal- és jobb-végpontja int az; //a szakasz azonisítója Szakasz(Pont b, Pont j, int a){ bal=b; jobb=j; az=a; Szakasz(Pont b, Pont j){ bal=b; jobb=j; Szakasz(){ public static boolean SzakaszParMetsz(Szakasz s1, Szakasz s2){ int fpq1=forgasirany(s1.bal,s1.jobb,s2.bal); int fpq2=forgasirany(s1.bal,s1.jobb,s2.jobb); int fqp1=forgasirany(s2.bal,s2.jobb,s1.bal); int fqp2=forgasirany(s2.bal,s2.jobb,s1.jobb); return (fpq1*fpq2<0) && (fqp1*fqp2<0) fpq1==0 && Kozte(s1.bal,s1.jobb,s2.bal) fpq2==0 && Kozte(s1.bal,s1.jobb,s2.jobb) fqp1==0 && Kozte(s2.bal,s2.jobb,s1.bal) fqp2==0 && Kozte(s2.bal,s2.jobb,s1.jobb);

9.5. Ponthalmaz konvex burka Definíció. Egy egyszerű (nem metsző) poligon konvex, ha bármely két belső pontját összekötő szakasz minden pontja a poligon belsejében, vagy határán van. Definíció. Egy P = {p 1,..., p n ponthalmaz konvex burka az a legszűkebb Q konvex poligon, amely a ponthalmaz minden pontját tartalmazza. Megoldás Graham-féle pásztázással Első lépésként rendezzük a ponthalmazt polárszög szerint, majd minden egyenesen csak a sarokponttól legtávolabbi pontot hagyjuk meg, a többit töröljük. Az így törölt pontok biztosan nem lehetnek csúcspontjai a konvex buroknak. Legyen q 1,...,q m az így kapott pontsorozat polárszög szerinti rendezésben. Mindaddig, amíg van három olyan cirkulárisan egymást követő q i, q i+1 q i+2 pont, hogy q i+1 q i+2 jobbra fordul q i q i+1 -hez képest, hagyjuk el a q i+1 pontot. Az algoritmus futási ideje O(n lg n), ha a polárszög szerinti rendezést olyan algoritmussal valósítjuk meg amelynek futási ideje O(n lgn).

13. ábra. Ponthalmaz konvex burka.

14. ábra. A pontok halmazának rendezése polárszög szerint.

15. ábra. Minden egyenesen csak a legtávolabbi pont marad meg.

/** *Konvex burok Graham-féle páztázó algoritmusa *Bemenet: Pont[] P ponthalmaz *Kimenet: m: a konvex burok pontjainak száma * P[0..m-1] tartalmazza a konvex burok pontjait */ public static int GrahamKB(Pont[]P){ int n=p.length; Pont x; SarokRendez(P); int m=1; for (int i=2; i<n; i++){ while (m>0 && ForgasIrany(P[m-1],P[m], P[i])<=0) m--; m++; x=p[m]; P[m]=P[i]; P[i]=x; return m;

9.6. Érintő egyenes keresése lineáris időben 9.1. definíció. Legyen P ponthalmaz, a P és q egy pont. Azt mondjuk, hogy az e(q, a) a P ponthalmaz jobboldali érintő (támasztó) egyenese, ha P minden pontja qa-tól nem jobbra van. Hasonlóan, az e(q,a) a P ponthalmaz baloldali érintő (támasztó) egyenese, ha P minden pontja qa-tól nem balra van. b q a 16. ábra. e(q, a) a P ponthalmaz jobboldali, e(q, b) pedig a baloldali érintő egyenese.

Nyilvánvaló, hogy akkor és csak akkor létezik adott q ponton átmenő érintő egyenes, ha q a P ponthalmaz konvex burkán kivül, vagy az oldalán van. Feladat: érintő egyenes meghatározása. Bemenet: P ponthalmaz, q pont Kimenet: 1. (a,0,0), ha P minden pontja az e(q,a) egyenesre esik 2. (a,b,0), ha q a P konvex burkán kivül van, és ekkor e(q,a) jobboldali, e(q, b) pedig baloldali érintő egyenes 3. (a,b,c), ha q a P konvex burkán belül van, és ekkor a, b és c olyan három pontja P-nek, hogy q az (a, b, c) háromszög belsejébe, vagy oldalára esik, de P egyetlen más pontja sem esik a háromszögbe sem oldalára.

b 4 a 3 q 2 1

b 4 a 3 q 2 1 P[i]

4 b a 3 q 2 P[i] 1

4 b 3 q 2 a= P[i] 1

4 b 3 q 2 a= P[i] 1

4 b =P[i] 3 q 2 a 1

c q a b 17. ábra.

c q a b

c q a b

c q a b

public static int[] Erinto(Pont[] P, Pont q){ /* Bemenet: P pon Kimenet: (i,0,0) ha P minden pontja az e(q,p[i+1]) egyenesre esik (a,b,0) ha q a P konvex burkán kívül van, és ekkor az e(q,a) és e(q,b) a két érintő egyenes (a,b,c) ha q a P konvex burkán belül van, és ekkor (a,b,c) olyan háromszög, hogy q a háromszögben van, és a,b és c kivételével P egyetlen pontja sem esik a háromszögbe, sem oldalára. */ int n=p.length; int[] abc={0,0,0; Pont a=p[0]; Pont b=null; Pont c=null; int firqa,firqb, firqc; int i=0; for (i=1; i<n&&geom.forgasirany(q,a,p[i])==0; i++) if (i==n){//p pontjai egy egyenesre esnek return abc;

b=p[i]; if (Geom.ForgasIrany(q,a,b)<0){//q-a-tól b balra essen a=b; b=p[0]; for (int j=1; j<n; j++){ firqa=geom.forgasirany(q,a,p[j]); firqb=geom.forgasirany(q,b,p[j]); if (firqa<0 && firqb>=0 firqa<=0 && firqb>0){//1.eset c=p[j]; break; else if (firqa<0 && firqb<0){//2.eset a=p[j]; else if (firqa>0 && firqb>0){//3.eset b=p[j]; //else nincs mit tenni, sem a, sem b nem vátozik //ha c==null, akkor q kivül van, és ekkor e(q,a) és e(q,b) érin if (c==null){ abc[0]=a.az; abc[1]=b.az; abc[2]=0; return abc;

//Az (a,b,c) háromszög tartalmazza a q pontot, finomítás: for (int i=0; i<n; i++) if (P[i].az!=a.az && P[i].az!=b.az && P[i].az!=c.az && Geom.ForgasIrany(a,b,P[i])>=0 && Geom.ForgasIrany(b,c,P[i])>=0 && Geom.ForgasIrany(c,a,P[i])>=0){ firqa=geom.forgasirany(q,a,p[i]); firqb=geom.forgasirany(q,b,p[i]); firqc=geom.forgasirany(q,c,p[i]); if (firqb<=0 && firqc>=0){ a=p[i]; else if (firqa>=0 && firqc<=0){ b=p[i]; else { c=p[i]; abc[0]=a.az; abc[1]=b.az; abc[2]=c.az; return abc; //Erinto

9.7. Feladat: Ponthalmaz legtávolabbi pontpárja. Adott a síkon egy P = {p 1,..., p n ponthalmaz. Határozzuk meg a ponthalmaz egy legtávolabbi pontpárját! Megoldás. A naiv algoritmus, amely minden pontpárra kiszámítja azok távolságát, futási ideje O( i=1 n 1 n(n 1) i) = 2 = O(n 2 ). Konvex burok alkalmazásával O(n lg n) idejű algoritmust adhatunk. 9.2. lemma. A legtávolabbi pontpár P konvex burkának két pontja lesz. Definíció A P ponthalmaz átellenes pontpárja olyan p i és p j pontpár, hogy ha van olyan p i -n és p j -n átmenő egyenes, amelyek párhuzamosak és a P ponthalmaz minden pontja a két egyenes közé esik. Konvex poligon összes átellenes pontpárjának meghatározása görgetéssel. Legyen P = p 1,..., p m a konvex poligon csúcspontjainak órajárással ellentétes felsorolása. Legyen p i a konvex poligon legkisebb y-koordinátájú pontja, ha kettő ilyen van, akkor ezek közöl válasszuk a legnagyobb x-koordinátájút. Legyen továbbá p j pedig a legnagyobb y-koordinátájú pontja, ha kettő ilyen van, akkor ezek közül

válasszuk a legkisebb x-koordinátájút. p i és p j nyilvánvalóan átellenes pontjai a poligonnak. Az összes átellenes pontpár lineáris időben meghatározható görgetéssel.

p j p j+1 p i+1 p i 18. ábra. Görgetés Ha az e(p i, p i+1 ) egyenes hajlásszöge kisebb, mint az e(p j, p j+1 ) egyenes hajlásszöge, akkor a p i+1 és p j is átellenes pontpár lesz, egyébként a p i p j+1 lesz átellenes pontpár. (a +1 modulo m értendő). Forgassuk el balra a 14.ábrán látható p i és p j pontokon átmenő párhuzamos egyeneseket amíg valamelyik a p i p i+1 vagy a p j p j+1 oldalra nem ér. Ha előbb érjük el a p i p i+1 oldalt, akkor i := i + 1, egyébként j := j + 1. Folytassuk ezt mindaddig, amíg vissza nem érünk a kezdetben választott két átellenes ponthoz. A szögek viszonya eldönthető a következő kifejezéssel:

FORGASIRANY(p j+1, p i+1 p i + p j+1, p j ) > 0 Következmény n elemű ponthalmaz egy legtávolabbi pontpárja O(n lg n) idejű algoritmussal kiszámítható. Következmény n elemű ponthalmaz vastagsága O(n lg n) idejű algoritmussal kiszámítható.

public class LTavolPontpar{ private static Pont Eltol(Pont q1, Pont q2, Pont q3){ return new Pont(q3.x-q2.x+q1.x, q3.y-q2.y+q1.y,0); /**@return A P ponthalmat legtavolabbi pontpárja */ public static PontPar ParKeres(Pont[] P){ int n=p.length; int m=geom.grahamkb(p); int i0=0; int j0=0; int i,j,ii,jj; double irany; /* A konvex burok két átellenes pontjának meghatározása */ for (int k=1; k<m; k++){ if (P[k].y<P[i0].y (P[k].y==P[i0].y&&P[k].x>P[i0].x))i0=k; if (P[k].y>P[j0].y (P[k].y==P[j0].y&&P[k].x<P[j0].x))j0=k;

double maxtav=(p[i0].x-p[j0].x)*(p[i0].x-p[j0].x)+ (P[i0].y-P[j0].y)*(P[i0].y-P[j0].y); PontPar Ptavol=new PontPar(P[i0], P[j0], maxtav); double ujtav; i=i0; j=j0; do{ //görgetés ii=(i+1)%m; jj=(j+1)%m; irany=geom.forgasirany(p[jj],eltol(p[jj],p[i],p[ii]),p[j]) if (irany>0){ i=ii; ii=(i+1)%m; else { //irany>=0 j=jj; jj=(j+1)%m; ujtav=(p[i].x-p[j].x)*(p[i].x-p[j].x)+ (P[i].y-P[j].y)*(P[i].y-P[j].y); if (ujtav>maxtav){ Ptavol.a=P[i]; Ptavol.b=P[j]; while(i!=i0 j!=j0); maxtav=ujtav;

Ptavol.abtav=Math.sqrt(maxtav); return Ptavol;

9.8. Metsző szakaszpárok létezésének vizsgálata Bemenet: S = {s 1 = p 1 q 1,...s n = p n q n Kimenet: i, j : 1 i < j n, a p i q i és p j q j szakasz metsző, 0,0 ha nincs ilyen i, j pár. Seprő egyenes Seprés során egy képzeletbeli seprő egyenest mozgatunk a geometriai elemek halmazán. Azt a dimenziót, amelyben a seprő egyenes halad, idődimenziónak hívjuk. Jelen esetben a seprő egyenes az y-tengellyel párhuzamos egyenes, az idődimenzió az x-koordináta lesz. Egyszerűsítő feltételek: 1. Egyik bemeneti szakasz sem függőleges. 2. Nincs három olyan szakasz, amelyek egy pontban metszenék egymást. s = pq szakasz esetén : s.bal = p és s. jobb = q jelölést használjuk. A pontok koordinátáira pedig p.x és p.y

9.9. Szakaszok rendezése Legyen s 1 és s 2 szakasz és x R Azt mondjuk, hogy s 1 összehasonlítható s 2 -vel x-nél, ha s 1.bal.x x s 1. jobb.x s 2.bal.x x s 2. jobb.x 9.3. definíció. Az s 1 szakasz felette van az s 2 szakasznak, jelben s 1 > x s 2, ha s 1 összehasonlítható s 2 -vel x-nél és az x seperő egyenesnek s 1 -el vett metszete magasabban van, mint s 2 -el vett metszete. 9.4. Állítás. A > x reláció lineáris rendezési reláció 9.5. Állítás. Ha x 1 < x 2 -re s 1 > x1 s 2 és s 2 > x2 s 1, akkor az s 1 és s 2 szakasz metszi egymást x 1 és x 2 között. Továbbá, ha x 1 és x 2 a seprő egyenes két egymást követő megállási helye, akkor x 1 -ben a két szakasz egymást követő lesz a rendezésben. Bizonyítás. Az ábráról látható. Tehát elegendő ellenőrizni minden szakasz berakásakor, hogy a rendezésben őt megelőző, és követő szakasz metszi-e a berakottat, és kivételkor ellenőrizni, hogy a kivett szakaszt megelőző és követő szakaszok metszik-e egymást.

x1 x2 x1 x2 19. ábra. 9.10. A seprő egyenes mozgatása 1. Esetpontok jegyzéke: azon időpontok (rendezett) sorozata, amely időpontokban a seprő egyenes megáll. 2. A seprő egyenes állapotleírása: az egyenes által metszett elemek rendezett halmaza. Esetpontok jegyzéke: = {s.bal.x : s S {s. jobb.x : s S Pontosabban: tegyük fel, hogy a szakaszok az S[1],...,S[n] felsorolással adottak. Feltételezzük, hogy S[i].bal.x < S[i]. jobb.x

20. ábra. Az esetpontok jegyzéke azon x értékek halmaza, ahol a seprő egyenes megáll. x

VegP = { S[i].bal.x,true,i : i = 1,...,n { S[i]. jobb.x, f alse,i : i = 1,...,n Rendezzük a VegP halmaz elemeit a seprő egyenes haladásának megfelelően, azaz a x1,b1,i1 hármas akkor és csak akkor előzze meg az x2,b2,i2 hármast, ha x1 < x2 vagy x1 = x2 és b1 = true és b2 = f alse vagy x1 = x2 és b1 = true és b2 = true és S[i1].bal.y < S[i2].bal.y vagy x1 = x2 és b1 = f alse és b2 = f alse és S[i1]. jobb.y < S[i2]. jobb.y Állapotleírás adott x-re legyen F az x-ben összehasonlítható szakaszok > x - szerint rendezett halmaza. A seprő egyenes mozgatásakor, azaz a VegP szakaszvégpontok fenti rendezése szerint haladva: Ha a x,b,i hármas az aktuális elem, akkor Ha b = true, azaz x az i. szakasz bal-végpontja, akkor szúrjuk be az s i szakaszt F-be. Ha b = f alse, azaz x az i. szakasz jobb-végpontja, akkor töröljük az s i szakaszt F-ből.

si. jobb si.bal s j s j. jobb si s j s j.bal s j. jobb s j.bal si si. jobb si.bal x x 21. ábra. s j.bal s i.bal s j s i s i. jobb s i.bal s j si s i. jobb s j. jobb s j.bal s j. jobb x x 22. ábra.

Beszúrást közvetlenül követően határozzuk meg a beszúrt s i szakasz követőjét F-ben. Ha ez metszi s i -t, akkor készen vagyunk. Hasonlóan, a beszúrást közvetlenül követően határozzuk meg a beszúrt s i szakasz megelőzőjét F-ben. Ha ez metszi s i -t, akkor készen vagyunk. Törlés esetén a törlést megelőzően határozzuk meg a törlendő s i szakaszt F- ben megelőző s j1 és követő s j2 szakaszokat. Ha mindkettő létezik és metszik egymást, akkor készen vagyunk. Tehát az alábbi műveletekre van szükség: BOVIT(F,I) TOROL(F,I) ELOZ(F,I) KOVET(F,I) Az RHALMAZ adattípus mindezen műveleteket biztosítja.

Megvalósítás. Ezek a műveletek hatékonyan megvalósíthatók kiegyensúlyozott keresővával, pl. AVL-fával, vagy piros-fekete fával. Ekkor minden művelet futási ideje legrosszabb esetben O(lg n). Ekkor az algoritmus futási ideje legrosszabb esetben O(n lg n) lesz, mivel a VegP halmaz rendezhető O(n lg n) időben, továbbá az, hogy két szakasz metszie egymást O(1) időben megállapítható. A kiegyensúlyozott bináris keresőfában nem kulcs szerinti a rendezés. Az adatmező tartalmazza a szakasz sorszámát, S a szakaszok tömbje legyen globális az eljárásokra nézve. A keresőfában a < összehasonlítás legyen a < x reláció:

public class SzakaszMetszKereso{ private static class SeproE implements Comparable<SeproE>{ /** A seprő egyenes megállási pontjainak típusa */ double x,y; int az; boolean bal; SeproE(double xx, double yy, boolean b, int a){ x=xx; y=yy; bal=b; az=a; public int compareto(seproe e){ if (this.x==e.x&&this.bal==e.bal&&this.az==e.az) return 0; if (this.x<e.x this.x==e.x && this.bal &&!e.bal this.x==e.x && this.bal==e.bal && this.y<e.y ){ return -1; else return 1;

private static class FElem implements Comparable<FElem>{ /** A Felett rendezési reláció megvalósítása */ public Szakasz[] S; int ind; public int compareto(felem e){ int fir; if (this.ind==e.ind) return 0; if (S[ind].bal.x<=e.S[e.ind].bal.x){ fir=geom.forgasirany( S[ind].bal, S[ind].jobb, e.s[e.ind].bal); else{ fir=-geom.forgasirany( e.s[e.ind].bal,e.s[e.ind].jobb,s[ind].bal); return (fir<0 fir==0&&ind<e.ind)?-1:1; FElem(Szakasz[] q, int az){ S=q; ind=az; FElem(){

public static Szakasz[] Keres(Szakasz[] S){ Szakasz[] MetszoPar=new Szakasz[2]; //az két metsző szakasz int n=s.length; SeproE[] VegP=new SeproE[2*n];//a seprő egyenes megállási po for (int i=0; i<n; i++){ VegP[i]=new SeproE(S[i].bal.x, S[i].bal.y,true,S[i].az); VegP[n+i]=new SeproE(S[i].jobb.x,S[i].jobb.y,false,S[i].az Rendez.KupacRend(VegP); RHalmaz<FElem> F=new RHalmazFa<FElem>("PF"); FElem p, q; FElem t=new FElem();

for (int ii=0; ii<2*n; ii++){ int i=vegp[ii].az; if (VegP[ii].bal){ FElem e=new FElem(S,i); F.Bovit(e); p=f.elozo(e); if (p!=null && Geom.SzakaszParMetsz(S[i],S[p.ind]) ){ MetszoPar[0]=S[i]; MetszoPar[1]=S[p.ind]; break; p=f.koveto(e); if (p!=null && Geom.SzakaszParMetsz(S[i],S[p.ind]) ){ MetszoPar[0]=S[i]; MetszoPar[1]=S[p.ind]; break; else{ t.s=s; t.ind=i; p=f.elozo(t); q=f.koveto(t); if (p!=null&&q!=null&& Geom.SzakaszParMetsz(S[p.ind],S[q.ind])){ MetszoPar[0]=S[p.ind]; MetszoPar[1]=S[q.ind]; break;

F.Torol(t); return MetszoPar;

9.11. Legközelebbi pontpár megkeresése Legyen p és q a síkon két pont. A két pont távolsága az Euklideszi távolság, azaz tav(p,q) = (p.x q.x) 2 + (p.y q.y) 2. Bemenet: P = {p 1,... p n ponthalmaz Kimenet: i, j : 1 i < j n, a tav(p i, p j ) minimális. Oszd-meg-és-uralkodj elvű algoritmus. Legyen S a pontok (azonosítóinak) halmaza, X a pontok (azonosítóinak) x- koordináta szerint rendezett sorozata, Y pedig pontok (azonosítóinak) y-koordináta szerint rendezett sorozata.

Elvi algoritmus: Bemenet: S, X,Y Kimenet: d min. távolság, a, b két legközelebbi pont; tav(a, b) = d TAVKERES(S,X,Y, D, A,B) begin {TavKeres if S 3 then Begin minden pontpárra ellenőrizzük a távolságot és vegyük a legkisebbet; Exit; end; S L := S-nek S /2 számú eleme x-koordináta szerint; S R := S-nek S /2 számú eleme x-koordináta szerint; x 0 := a felosztó (felező) x-kootdináta érték; X L := S L elemeinek x-koordináta szerint rendezett sorozata; X R := S R elemeinek x-koordináta szerint rendezett sorozata; TAVKERES(S L,X L,Y L,d L,a L,b L ); TAVKERES(S R,X R,Y R,d R,a R,b R ); d := min(d L,d R ); Y d := azon S-beli pontok halmaza, amelyek x-koordinátájára x 0 x d; Y d legyen y-koordináta szerint rendezett;

Ha van Y d-ben d-nél közelebbi pár, akkor azt adjuk vissza, egyébként d-t; end {TavKeres

Állítás. Y d-ben elég minden p pontra csak p-t követő 7 pontra nézni a távolságot, hogy találjuk d-nél közelebbi pontpárt, ha létezik ilyen. Futási idő legrosszabb esetben. T (n) = 2T (n/2) + O(n) Tehát T (n) = (n lgn) Megvalósítás

p L p R δ δ S L l S R 23. ábra. A sik (tartomány) két részre osztása az l egyenessel.

δ Itt két pont is lehet, egy S L -ben, egys R -ben δ δ S L l S R 24. ábra. A δ átmérőjű sávban adott p ponthoz legfeljebb 7 olyan pont lehet, amelynek p-től vett távolsága legfeljebb δ. Ezek a pontok a y-koordináta szerinti rendezésben egymást követők.

public class LKozelPontpar{ private static class XKoord implements Comparator<Pont>{ public int compare(pont p1, Pont p2 ){ return (p1.x<p2.x p1.x==p2.x && p1.az<p2.az)? -1:1 private static class YKoord implements Comparator<Pont>{ public int compare(pont p1, Pont p2 ){ return (p1.y<p2.y p1.y==p2.y && p1.az<p2.az)? -1:1

public static PontPar ParKeres( Pont[] X, Pont[] Y, Pont[] Z, int bal, int jobb){ if (jobb-bal == 1) // csak két pont van return new PontPar(X[bal],X[jobb],Geom.Tav(X[bal],X[jobb if (jobb-bal == 2){ // 3 pont van, minden párra kiszámoljuk a táv-ot double t1 = Geom.Tav(X[bal], X[bal+1]); double t2 = Geom.Tav(X[bal+1], X[jobb]); double t3 = Geom.Tav(X[bal], X[jobb]); if (t1 <= t2 && t1 <= t3) return new PontPar(X[bal], X[bal+1], t1); if (t2 <= t3) return new PontPar(X[bal+1], X[jobb], t2); else return new PontPar(X[bal], X[jobb], t3);

int kozep=(bal+jobb) >>1; int zbal = bal, // kurzor Z[bal:kozep]-hez zjobb = kozep+1; // kurzor Z[kozep+1:jobb]-hez for (int i = bal; i <= jobb; i++) if (Y[i].az <= kozep) Z[zbal++] = Y[i]; else Z[zjobb++] = Y[i]; // uralkodj PontPar balkozel = ParKeres(X, Z, Y, bal, kozep); PontPar jobbkozel = ParKeres(X, Z, Y, kozep+1, jobb); PontPar kozel; kozel= (balkozel.abtav<jobbkozel.abtav)? balkozel : jobbkoz

// Y rekonstruálása: Z[bal:kozep], Z[bal+1,jobb]->Y[bal:jobb] int k=bal; {int i=bal; int j=kozep+1; while (i<=kozep && j<=jobb) //összefésülés if (Z[i].y<Z[j].y Z[i].y==Z[j].y && Z[i].az<Z[j].az) Y[k++]=Z[i++]; else Y[k++]=Z[j++]; while (i<=kozep) Y[k++]=Z[i++];//a maradékok átmásolása while (j<=jobb) Y[k++]=Z[j++]; k=bal;

for (int i = bal; i <= jobb; i++) if (Math.abs(X[kozep].x - Y[i].x) < kozel.abtav) Z[k++] = Y[i]; for (int i = bal; i < k-1; i++) for (int j=i+1; j<k && Z[j].y-Z[i].y<kozel.abtav; j++){ double ujtav = Geom.Tav(Z[i], Z[j]); if (ujtav < kozel.abtav){ // kozelebbi párt találtunk kozel.a=z[i]; kozel.b=z[j]; kozel.abtav=ujtav; return kozel;

public static PontPar ParKeres(Pont[] P){ int n=p.length; int [] Az=new int[n]; //eredeti pont-azonosítok mentésére Pont[] X=new Pont[n]; //x-szerint rendezett ponthalmaz Pont[] Y=new Pont[n]; //y-szerint rendezett ponthalmaz Pont[] Z=new Pont[n]; //segéd for (int i=0; i<n; i++) X[i]=P[i];

XKoord Xrend=new XKoord();//x-szerinti rendezés relációja Rendez.KupacRend2(X,Xrend);//előrendezés x-koord szerint for (int i=0; i<n; i++){ Az[i]=X[i].az; X[i].az=i; Y[i]=X[i]; //eredeti pont-azonosítók mentése YKoord Yrend=new YKoord();//y-szerinti rendezés relációja Rendez.KupacRend2(Y,Yrend); PontPar Pkozel=ParKeres(X, Y, Z, 0, n-1); //az eredei pont-azonosítók helyreállítása for (int i=0; i<n; i++) X[i].az=Az[i]; return Pkozel;