A Graham -algoritmus egy konvex hajótest felépítésére szolgáló algoritmus kétdimenziós térben. Ebben az algoritmusban a konvex hajótest problémáját a jelölt pontokból képzett verem segítségével oldjuk meg. A bemeneti halmaz összes pontja a verembe kerül, majd végül eltávolítják belőle azokat a pontokat, amelyek nem a konvex hajótest csúcsai. Az algoritmus végén csak a shell csúcsai maradnak a veremben abban a sorrendben, ahogy az óramutató járásával ellentétes irányban haladnak.
A Graham-eljárás bemeneti adatai a Q pontok halmaza, ahol . Meghívja a Top(S) függvényt, amely visszaadja az S verem tetején lévő pontot anélkül, hogy annak tartalmát megváltoztatná. Ezenkívül a NextToTop(S) függvény is használatos, amely az S veremben található pontot adja vissza, egy pozícióval a felső pont alatt; verem S nem változik.
Graham (Q) 1) Legyen egy pont a Q halmazból minimális y koordinátájú, vagy az ilyen pontok közül a bal szélső egyezések jelenlétében 2) Legyen a Q halmaz fennmaradó pontjai a polárszög növekvő sorrendjében, a ponthoz képest az óramutató járásával ellentétes irányban mérve (ha több pont poláris szöge azonos, akkor a pont távolságával ) 3) Nyomja meg ( ,S) 4) Push( ,S) 5) i = 2 -től m -ig 6) míg a NextToTop (S),Top(S) és , pontok által alkotott szög nem balra fordult (a pontok által alkotott szaggatott vonal mentén haladva egyenesen vagy jobbra haladunk) 7) Pop (S) 8) Push( ,S) 9) küldje vissza SAnnak meghatározásához, hogy három pont képez -e , és egy balra fordulást, használhatja a vektorszorzat általánosítását egy kétdimenziós térre, nevezetesen a balra fordulás feltétele így fog kinézni: , ahol
Ha a Graham eljárás egy Q ponthalmazt dolgoz fel, ahol , akkor ennek az eljárásnak a végén az S verem (alulról felfelé) csak a CH(Q) héj csúcsait fogja tartalmazni az óramutató járásával ellentétes sorrendben.
A 2. sor végrehajtása után egy pontsorozat áll rendelkezésünkre . Határozzuk meg az i = 2,3,…,m pontok részhalmazát . A Q pontok halmaza azokat a pontokat alkotja, amelyeket azért távolítottak el, mert a p0 ponthoz viszonyított polárszögük egybeesik a halmaz valamely pontjának polárszögével . Ezek a pontok nem tartoznak a CH(Q) konvex burokhoz, így CH( ) = CH(Q). Így elég megmutatni, hogy a Graham-eljárás végén az S verem a CH( ) héj csúcsaiból áll az óramutató járásával ellentétes sorrendben, ha ezeket a pontokat alulról felfelé nézzük a veremben. Vegyük észre, hogy ahogy a , , pontok a CH(Q) shell csúcsai, a , , pontok a CH( ) shell csúcsai.
A bizonyítás az alábbiakban megfogalmazott ciklusinvariánst használja. A for ciklus minden iterációjának elején a 6-9. sorban az S verem (alulról felfelé) csak a CH( ) héj csúcsaiból áll az óramutató járásával ellentétes sorrendben.
Inicializálás . A 6. idősor első végrehajtása, az invariáns megmarad, mert ezen a ponton az S verem csak = csúcsokból áll , és ez a három csúcsból álló halmaz alkotja saját konvex burkot. Ezenkívül, ha a pontokat alulról felfelé nézi, akkor azok az óramutató járásával ellentétes sorrendben helyezkednek el.
Tartósítás . A for ciklus új iterációjának megadásakor a verem tetején az S pont található , amely az előző iteráció végén (vagy az első iteráció előtt, amikor i = 3) kerül oda. Legyen az S verem legfelső pontja a while ciklus 7-8. sorainak végrehajtása után, de mielőtt a pont a verembe kerül a 9. sorban . Legyen az S veremben közvetlenül a pont alatt található pont is . Abban a pillanatban, amikor a pont az S verem tetején van, és a pontot még nem adták hozzá, a verem ugyanazokat a pontokat tartalmazza, mint a for ciklus j-edik iterációja után. Ezért a ciklusinvariáns szerint ezen a ponton az S veremben csak a CH( ) található az óramutató járásával ellentétes bejárási sorrendben, alulról felfelé nézve. A pontnak a ponthoz viszonyított poláris szöge nagyobb, mint a pont poláris szöge , és mivel a szög balra gördül (különben a pont kikerülne a veremből), miután hozzáadta a pontot az S veremhez (mielőtt csak CH( ) csúcsok voltak, a CH( ) csúcsokat fogja tartalmazni . Ugyanakkor alulról felfelé nézve az óramutató járásával ellentétes sorrendben lesznek elrendezve.
Mutassuk meg, hogy a CH( ) csúcshalmaz egybeesik a CH( ) ponthalmazsal. Tekintsünk egy tetszőleges pontot a veremből a for ciklus i-edik iterációja során, és legyen az a pont, amely az S veremben található közvetlenül a veremből való utolsó kiugrás előtti pont alatt (ez a pr pont lehet a pont ). A szög nem gördül balra, és a pont poláris szöge a ponthoz képest nagyobb, mint a pont poláris szöge . Mivel a pont a halmaz három másik pontja által alkotott háromszögön belül van , nem lehet CH( ) csúcsa. Mivel ez nem a CH( ) csúcsa , akkor CH( - { }) = CH( ). Legyen a for ciklus i-edik iterációjának végrehajtása során a veremből vett pontok halmaza. A CH( - ) = CH( ) egyenlőség igaz. Azonban — = { }, tehát arra a következtetésre jutunk, hogy CH( { }) = CH( — ) = CH( ).
Közvetlenül a pont S veremből való kiszorítása után csak a CH( ) csúcsokat tartalmazza az óramutató járásával ellentétes irányban való bejárásuk sorrendjében, ha alulról felfelé nézzük őket a veremben. Az i értékének ezt követő növelése a ciklusinvariáns megőrzéséhez vezet a következő iterációban.
Befejezés . A ciklus végén teljesül az i = m + 1 egyenlőség, így a ciklusinvariánsból következik, hogy az S verem csak a CH( ), vagyis a CH(Q) csúcsaiból áll. Ezek a csúcsok az óramutató járásával ellentétes bejárási sorrendben vannak, ha alulról felfelé nézzük a veremben.
A Graham eljárás futási ideje , ahol . Amint könnyen látható, a while ciklus O( ) időt vesz igénybe. Míg a poláris szögek rendezése időt vesz igénybe , ebből adódik a Graham-eljárás általános aszimptotikus viselkedése.