Кіріспе

Нүктелер жиынтығында дөңгелек қабықшаны есептеу алгоритмі

Грэхамның сканерлеу әдісі – жазықтықтағы нүктелер жиынтығының дөңгелек қабықшасын табу әдісі, уақыт күрделілігі O(n log n) шамасында. Бұл әдіс 1972 жылы алғашқы алгоритмін жариялаған Рональд Грэмнің есімімен аталады. Алгоритм дөңгелек қабықшаның шекарасы бойынша реттелген барлық төбелерін анықтайды. Шекарадағы ойыстарды тиімді анықтау және жою үшін ол стек пайдаланады.

Алгоритм

Алғашқы қадам – y-координатының ең төмен нүктесін табу. Егер жиынның бірден көп нүктесінде ең төменгі y координатасы болса, онда үміткерлердің ішінен ең төменгі x координатасы бар нүкте таңдалуы керек. Бұл нүктеге P деп атаңыз. Бұл қадам O(n) уақыт алады, мұнда n – нүктелердің саны. Келесі қадамда нүктелер жиыны олардың және P нүктесінің x оське қатысты бұрышы бойынша өсу тәртібімен сұрыпталуы керек. Бұл үшін кез келген жалпы мақсаттағы сұрыптау алгоритмін қолдануға болады, мысалы, heapsort (O(n log n)). Бұрыш бойынша сұрыптау үшін бұрышты есептеудің қажеті жоқ. Косинус нүктелік көбейтіндісі арқылы оңай есептеледі немесе түзудің еңістігін қолдануға болады. Егер сандық дәлдік маңызды болса, сұрыптау алгоритмінде салыстыру функциясы салыстырмалы бұрыштарды анықтау үшін векторлық көбейтіндінің таңбасын пайдалана алады. Егер бірнеше нүктелер бірдей бұрышқа ие болса, қашықтық бойынша түйіндіктерді шешіңіз (оңай есептеу үшін Евклидтік қашықтықтың орнына Манхэттен немесе Чебышев қашықтығын қолдануға болады, себебі нүктелер бір түзу бойында жатыр) немесе ең алыс нүктеден басқа барлық нүктелерді жойыңыз. Алгоритм реттелген массивтегі әр нүктені бірінен кейін бірі қарастыру арқылы жүзеге асырылады. Әр нүкте үшін, осы нүктеден бірден бұрынғы екі нүктеден қозғалыс солға немесе оңға бұрылуды білдіретінін анықтау керек. Егер оңға бұрылса, екінші соңғы нүкте дөңгелек қабықшаның бөлігі емес, оның ішінде жатыр. Содан кейін, соңғы нүкте мен қабықшаның ішінде деп табылған нүктеден бұрынғы екі нүкте үшін де осы тексеру жасалады және «солға бұрылу» жиынтығы кездескенше қайталанады. Осы кезде алгоритм реттелген массивтегі келесі нүктеге көшеді, ал қабықшаның ішінде деп табылған нүктелерді ескермейді; оларды қайта қарастырудың қажеті жоқ. (Егер үш нүкте бір түзу бойында болса, оларды жоюды немесе туралы хабарлауды таңдауға болады, себебі кейбір қолданбаларда дөңгелек қабықшаның шекарасындағы барлық нүктелерді табу қажет.) Тағы да, үш нүкте «солға бұрылу» немесе «оңға бұрылу» құрайтынын анықтау үшін екі түзу кесіндісі арасындағы нақты бұрышты есептеудің қажеті жоқ, оны қарапайым арифметикалық амалдармен анықтауға болады. Үш нүкте үшін A, B және C, екі вектордың векторлық көбейтіндісінің z координатын есептеңіз: (B - A) x (C - A). Егер нәтиже 0 болса, нүктелер бір түзу бойында жатыр; егер оң болса, үш нүкте «солға бұрылу» немесе сағат тіліне қарсы бағытта, әйтпесе «оңға бұрылу» немесе сағат тілімен бағытта (сағат тіліне қарсы нөмірленген нүктелер үшін). Бұл процесс бастапқы нүктеге қайта оралады, осы кезде алгоритм аяқталады және стек дөңгелек қабықшадағы нүктелерді сағат тіліне қарсы тәртіппен қамтиды.

Сандық беріктігі

Сандық беріктік – шекті дәлдігі бар қозғалмалы нүктелі компьютерлік арифметиканы қолданатын алгоритмдерде туындайтын мәселе. 2004 жылғы мақалада қарапайым инкременттік стратегия талданды, оны, атап айтқанда, Грэм сканерін іске асыру үшін пайдалануға болады. Кейін Д. Цзян және Н. Ф. Стюарт осы мәселені терең зерттеп, кері қателік талдауын қолданып, екі маңызды қорытынды жасады. Біріншісі – дөңес қабықша жақсы жағдайланған мәселе, сондықтан нәтиже ақылға қонымды қателік шегінде болатын алгоритмдерді күтуге болады. Екіншісі, олар Грэм сканерінің өзгертілген нұсқасын, оны Грэм Фортуна деп атады (Стивен Фортунаның сандық тұрақтылыққа қатысты идеяларын енгізе отырып), шекті дәлдік пен нақты емес деректердің тудыратын қиындықтарды "мүмкін болатын шекте" шеше алады.