“Rekursiv algoritmlar. Rekursiya ta’rifi. Bevosita (oddiy) va bilvosita (murakkab) rekursiya sxemalari. Rekursiv algoritmlarga misollar
Mavzu: “Rekursiv algoritmlar. Rekursiya ta’rifi. Bevosita (oddiy) va bilvosita (murakkab) rekursiya sxemalari. Rekursiv algoritmlarga misollar” Reja: 1. Kirish 2. Asosiy qism A) Rekursiv algoritmlar haqida B) Rekursiya ta’rifi C) Bevosita va bilvosita rekursiya sxemalari D) Rekursiv algoritmlarga misollar 3. Xulosa 4. Amaliy ish 5. Foydalangan Adobiyotlar
Kirish Rekursiv algoritmlar Rekursiyaning mohiyati Hisoblash jarayonida ba’zi bir algoritmlarning o‘ziga qayta murojaat qilishga to‘g‘ri keladi. O‘ziga–o‘zi murojaat qiladigan algoritmlarga rekkurent algoritmlar yoki rekursiya deb ataladi. Biron bir masalani yechishda, agar uni bir xil kichik yoki sodda masalaraga bo‘lib bajarish mumkin bo‘lsa, bunday hollarda rekursiv algoritm qo‘llash mumkin.Hayotda uchrovchi ba’zi masalalarni hal etish rekursiv algoritmlarni qo‘llash orqali oson va intutitiv tarzda kechadi. Misol sifatida Fibonachi sonlari ketma-ketligi, factorial hisoblash. Protsedura yoki funksiya boshqa protsedura yoki funksiyalarga qo‘ng'iroqlarni o‘z ichiga olishi mumkin. Jumladan, protsedura o‘zini chaqirishi mumkin. Bu erda hech qanday paradoks yo‘q - kompyuter faqat dasturda duch kelgan buyruqlarni ketma-ket bajaradi va agar protsedura chaqiruviga duch kelsa, u shunchaki ushbu protsedurani bajarishni boshlaydi. Buni amalga oshirish uchun qanday buyruq berilganligi muhim emas. Rekursiv protseduraga misol: Procedure Rec(a: integer); a> bo‘lsa boshlang Keling, asosiy dasturga, masalan, Rec(3) ko‘rinishdagi qo‘ng'iroqni qo‘ysak nima bo‘lishini ko‘rib chiqamiz. Quyida bayonotlar bajarilish ketma-ketligini ko‘rsatadigan oqim diagrammasi keltirilgan. Guruch. 1. Rekursiv protseduraning blok diagrammasi. Rec protsedurasi a = 3 parametri bilan chaqiriladi. Unda a = 2 parametrli Rec protsedurasiga qo‘ng'iroq mavjud. Oldingi qo‘ng'iroq hali tugallanmagan, shuning uchun siz boshqa protsedura yaratilayotganini tasavvur qilishingiz mumkin va birinchisi amalga oshiriladi. ishi tugaguniga qadar ishini tugatmaslik. Qo‘ng'iroq jarayoni parametr a = 0 bo‘lganda tugaydi. Hozirgi vaqtda protseduraning 4 ta nusxasi bir vaqtning o‘zida bajarilmoqda. Bir vaqtning o‘zida bajariladigan protseduralar soni chaqiriladi rekursiya chuqurligi. (Rec(0)) deb nomlangan to‘rtinchi protsedura 0 raqamini chop etadi va chiqadi. Shundan so‘ng, boshqaruv uni chaqirgan protseduraga qaytadi (Rec(1)) va 1 raqami chop etiladi va barcha protseduralar tugaguncha davom etadi. Dastlabki qo‘ng'iroqning natijasi to‘rtta raqamni chop etadi: 0, 1, 2, 3. Nima sodir bo‘layotganining yana bir vizual tasviri rasmda ko‘rsatilgan. 2. Guruch. 2. 3-parametr bilan Rec protsedurasini bajarish 2-parametr bilan Rec protsedurasini bajarish va 3-raqamni chop etishdan iborat. hokazo. O‘z-o‘zidan mashq sifatida, Rec(4) ga qo‘ng'iroq qilganingizda
nima sodir bo‘lishini ko‘rib chiqing. Quyida tasvirlangan Rec2(4) protsedurasini chaqirganingizda nima sodir bo‘lishini ham ko‘rib chiqing, bu erda operatorlar teskari. Protsedura Rec2(a: butun son); yozishni boshlash (a); agar a>0 bo‘lsa, Rec2(a-1); oxiri; E'tibor bering, yuqoridagi misollarda rekursiv qo‘ng'iroq shartli bayonot ichida joylashgan. bu zarur shart rekursiya abadiy tugashi uchun. Shuni ham yodda tutingki, protsedura o‘zini chaqirilganidan boshqa parametr bilan chaqiradi. Agar protsedura global o‘zgaruvchilardan foydalanmasa, bu rekursiya cheksiz davom etmasligi uchun ham kerak. Biroz murakkabroq sxema bo‘lishi mumkin: A funktsiyasi B funktsiyasini chaqiradi, bu esa o‘z navbatida A ni chaqiradi. Bu deyiladi murakkab rekursiya. Ma'lum bo‘lishicha, birinchi bo‘lib tasvirlangan protsedura hali tasvirlanmaganini chaqirishi kerak. Buning mumkin bo‘lishi uchun siz dan foydalanishingiz kerak. Protsedura A(n: butun son); (Birinchi protseduraning oldinga tavsifi (sarlavhasi)) B protsedurasi (n: butun son); (Ikkinchi protseduraning oldinga tavsifi) protsedura A(n: butun son); (To‘liq protsedura tavsifi A) begin writeln(n); B(n-1); oxiri; B protsedurasi (n: butun son); (B protsedurasining to‘liq tavsifi) begin writeln(n); ifn B protsedurasining oldinga e'lon qilinishi uni A protsedurasidan chaqirish imkonini beradi. A protsedurasining oldinga e'lon qilinishi bu misolda talab qilinmaydi va estetik sabablarga ko‘ra qo‘shilgan. Agar oddiy rekursiyani uroborosga qiyoslash mumkin bo‘lsa (3-rasm), unda “Bo‘rilar qo‘rqib bir-birini yeb qo‘ygan” nomli mashhur bolalar she’ridan murakkab rekursiya tasvirini olish mumkin. Ikki bo‘ri bir-birini yeyayotganini tasavvur qiling va siz murakkab rekursiyani tushunasiz. Guruch. 3. Ouroboros - o‘z dumini yutib yuboradigan ilon. Teodor Pelekanosning "Sinoziy" alkimyoviy risolasidan olingan rasm (1478). Guruch. 4. Murakkab rekursiya. 3. Rekursiya yordamida sikl ishini simulyatsiya qiling Agar protsedura o‘zini o‘zi chaqirsa, unda, aslida, bu uning tarkibidagi ko‘rsatmalarning takroriy bajarilishiga olib keladi, bu tsiklning ishlashiga o‘xshaydi. Ba'zi dasturlash tillarida aylanma konstruktsiyalar umuman mavjud emas, bu esa dasturchilarni rekursiyadan foydalangan holda takrorlashni tashkil qilishni qoldiradi (masalan, Prolog, bu erda rekursiya asosiy dasturlash texnikasi). Masalan, for siklining ishini simulyatsiya qilaylik. Buning uchun bizga, masalan, protsedura parametri sifatida amalga oshirilishi mumkin bo‘lgan qadam hisoblagichi o‘zgaruvchisi kerak. 1-misol Protsedura
LoopImitation(i, n: integer); (Birinchi parametr - qadamlar soni, ikkinchi parametr - qadamlarning umumiy soni) begin writeln("Salom N ", i); //Bu erda i bo‘lsa takrorlanadigan har qanday gaplar LoopImitation(1, 10) kabi qo‘ng'iroq natijasi hisoblagichni 1 dan 10 gacha o‘zgartirish bilan ko‘rsatmalarning o‘n marta bajarilishi bo‘ladi. Bu holda u chop etadi: Salom N1 Salom N2 … Salom N 10 Umuman olganda, protsedura parametrlari hisoblagich qiymatlarining o‘zgarishi chegaralari ekanligini ko‘rish qiyin emas. Quyidagi misolda bo‘lgani kabi takrorlanadigan qo‘ng'iroq va ko‘rsatmalarni almashtirishingiz mumkin. 2-misol Protsedura LoopImitation2(i, n: integer); agar men boshlasam Bunday holda, ko‘rsatmalar bajarilishidan oldin protsedura rekursiv chaqiriladi. Protseduraning yangi nusxasi, shuningdek, birinchi navbatda, hisoblagichning maksimal qiymatiga erishgunimizcha, boshqa misolni chaqiradi va hokazo. Shundan keyingina oxirgi chaqirilgan protseduralar o‘z ko‘rsatmalarini bajaradi, so‘ngra oxirgisi o‘z ko‘rsatmalarini bajaradi va hokazo. LoopImitation2(1, 10) ni chaqirish natijasi salomlashishni teskari tartibda chop etishdir: Salom N 10 … Salom N1 Agar biz rekursiv deb ataladigan protseduralar zanjirini tasavvur qilsak, u holda 1- misolda biz undan oldingi protseduralardan keyingilariga o‘tamiz. 2-misolda, aksincha, keyinroqdan oldingiga. Nihoyat, rekursiv qo‘ng'iroqni ikkita ko‘rsatmalar bloki orasiga qo‘yish mumkin. Masalan: Protsedura LoopImitation3(i, n: integer); begin writeln("Salom N", i); (Bu bayonotlarning birinchi bloki bo‘lishi mumkin) agar i Bu yerda, birinchi navbatda, birinchi blokdagi ko‘rsatmalar ketma-ket bajariladi, keyin ikkinchi blokning ko‘rsatmalari teskari tartibda bajariladi. LoopImitation3(1, 10) ga qo‘ng'iroq qilganda biz quyidagilarni olamiz: Salom N1 … Salom N 10 Salom N 10 … Salom N1 Rekursiyasiz xuddi shunday qilish uchun bir vaqtning o‘zida ikkita tsikl kerak bo‘ladi. Xuddi shu protsedura qismlarini bajarish vaqt oralig'ida joylashganligidan foydalanishingiz mumkin. Masalan: 3-misol: Sonni ikkilik sistemaga aylantirish. Ikkilik sonning raqamlarini olish, ma'lumki, sanoq sistemasining asosiga qoldiqga bo‘lish yo‘li bilan sodir bo‘ladi 2. Agar raqam bo‘lsa, uning ikkilik ko‘rinishidagi oxirgi raqami teng bo‘ladi. 2 ga bo‘lishning butun qismini olish: biz bir xil ikkilik ko‘rinishga ega bo‘lgan, ammo oxirgi raqamsiz raqamni olamiz. Shunday qilib, keyingi bo‘linish maydonida 0 ga teng butun son bo‘lguncha yuqoridagi ikkita amalni takrorlash kifoya. Rekursiyasiz u
quyidagicha ko‘rinadi: x>0 esa c:=x mod 2 boshlanadi; x:=x div 2; yozish (c); oxiri; Bu erda muammo shundaki, ikkilik vakillikning raqamlari teskari tartibda hisoblanadi (oxirgi birinchi). Raqamni oddiy shaklda chop etish uchun siz massiv elementlaridagi barcha raqamlarni eslab qolishingiz va ularni alohida tsiklda chiqarishingiz kerak bo‘ladi. Rekursiya bilan massiv va ikkinchi siklsiz kerakli tartibda chiqishni olish oson. Aynan: Protsedura BinaryRepresentation(x: integer); var c, x: integer; start (Birinchi blok. Protsedura chaqiruvi tartibida bajariladi) c:= x mod 2; x:=x div 2; (Rekursiv chaqiruv) agar x>0 bo‘lsa, BinaryRepresation(x); (Ikkinchi blok. Teskari tartibda ishlaydi) yozish(c); oxiri; Umuman olganda, biz hech qanday yutuq olmadik. Ikkilik tasvirning raqamlari mahalliy o‘zgaruvchilarda saqlanadi, ular rekursiv protseduraning har bir ishlayotgan misoli uchun farq qiladi. Ya'ni xotirani saqlab bo‘lmadi. Aksincha, biz ko‘p mahalliy o‘zgaruvchilarni saqlash uchun qo‘shimcha xotira sarflaymiz x. Shunga qaramay, bunday yechim menga chiroyli ko‘rinadi. 4. Takroriy munosabatlar. Rekursiya va iteratsiya Aytishlaricha, vektorlar ketma-ketligi, agar boshlang'ich vektor va keyingi vektorning oldingisiga funktsional bog'liqligi berilsa, takrorlanish munosabati bilan beriladi. Qaytalanish munosabatlari yordamida hisoblangan miqdorning oddiy misoli faktorialdir Keyingi faktorialni avvalgisidan quyidagicha hisoblash mumkin: Belgini kiritish orqali biz quyidagi munosabatni olamiz: Formula (1) vektorlari o‘zgaruvchan qiymatlar to‘plami sifatida talqin qilinishi mumkin. Keyin ketma-ketlikning kerakli elementini hisoblash ularning qiymatlarini qayta-qayta yangilashdan iborat bo‘ladi. Xususan, faktorial uchun: X:= 1; i:= 2 uchun n do x:= x * i; writeln(x); Har bir bunday yangilanish (x:= x * i) chaqiriladi iteratsiya, va takroriy takrorlash jarayoni iteratsiya. Biroq, e'tibor bering, (1) munosabat ketma-ketlikning sof rekursiv ta'rifi va n-elementni hisoblash aslida f funktsiyasini o‘zidan takroriy olishdir: Xususan, faktorial uchun quyidagilarni yozish mumkin: Function Factorial(n: integer): integer; start agar n > 1 bo‘lsa, unda Faktorial:= n * Faktorial(n-1) else Faktorial:= 1; oxiri; Shuni tushunish kerakki, funktsiya chaqiruvlari qo‘shimcha xarajatlarni talab qiladi, shuning uchun faktorialni hisoblashning birinchi varianti biroz tezroq bo‘ladi. Umuman olganda, iterativ echimlar rekursivlarga qaraganda tezroq ishlaydi. Rekursiya foydali bo‘lgan holatlarga o‘tishdan oldin, uni ishlatmaslik kerak bo‘lgan yana bir misolni ko‘rib chiqaylik. Ketma-