tsükliliste arvutuste programmeerimine...– negatiivsed arvud võidakse lugeda ka positiivsetest...
TRANSCRIPT
-
1
Tsükliliste arvutusteprogrammeerimine
1 Rekursioon 2
Rekursioon
-
1 Rekursioon 3
Rekursioon
Rekursiivne on definitsioon (või definitsioonide rühm), mis määratlebdefineeritava objekti (või objektide rühma) tema enda (või tsükliliseltrühma liikmete endi) kaudu.
– Mh definitsiooni paremas pooles võib esineda sama muutuja misvasakus.
Vastavat nähtust nimetatakse rekursiooniks.
1 Rekursioon 4
Liigid
• Otsene rekursioon.Definitsioon on otseselt rekursiivne, kui ta kasutab paremas poolestema enda poolt defineeritud objekti.
• Kaudne rekursioon.Definitsioon on kaudselt rekursiivne, kui ta on üks liige järjendistx0, . . . , xl−1, kus l > 1 ja iga xi korral xi+1 definitsioon kasutab pa-remas pooles xi-d (loeme xl = x0).
• Vastastikrekursioon.Kui kaudses rekursioonis definitsioonide arv on 2, siis öeldakse, etneed definitsioonid on vastastikku rekursiivsed.
-
1 Rekursioon 5
Rekursiivne kutse
Rekursiivseks kutseks nimetatakse
– arvutussammu, kus muutuja asendatakse samast definitsioonist,mille kaudu selle sammuni on jõutud;
– ka muutuja esinemist oma otseselt rekursiivse definitsiooni pare-mas pooles.
1 Rekursioon1.1 Funktsiooni määratlemine rekursiivselt
6
Funktsiooni määratlemine rekursiivselt
-
1 Rekursioon1.1 Funktsiooni määratlemine rekursiivselt
7
Põhimõte
Funktsiooni defineerimisel rekursiivselt tuleb kirjeldada:
– funktsiooni väärtuse leidmine suurematel argumentidel samafunktsiooni väärtuste kaudu väiksematel argumentidel;
– funktsiooni väärtus vähimatel argumentidel ilma rekursiivsete kut-seteta.
∗ Viimased on nn baasjuhud.
1 Rekursioon1.1 Funktsiooni määratlemine rekursiivselt
8
Arvutus
Kui funktsioon on defineeritud vastavalt sellele põhimõttele, siis arvu-tuse käigus
– igal rekursiivsel kutsel argumendi väärtus väheneb,
– kuni saab triviaalselt väikseks ja käiku lähevad baasjuhud.
-
1 Rekursioon1.1 Funktsiooni määratlemine rekursiivselt
9
Tavalised argumenditüübid
• Rekursioon täisarvudel.Järjestus on standardne (vähemalt mittenegatiivsetel täisarvudel).
– Negatiivsed arvud võidakse lugeda ka positiivsetest suuremaks,kui funktsiooni väärtus negatiivsel argumendil määratleda väärtu-se kaudu nt vastandarvul.
• Struktuurne rekursioon (andmestruktuuridel).Järjestus on alamstruktuurijärjestus.
– Näiteks listist väiksemad listid on tema saba, saba saba jne.
1 Rekursioon1.1 Funktsiooni määratlemine rekursiivselt
10
Standardne rekursioon
Kõige standardsemal juhul kirjeldatakse funktsiooni väärtus mittetri-viaalsel argumendil funktsiooni väärtuse kaudu talle järjestuses vahetulteelneval andmel.
– Funktsiooni väärtus positiivsel täisarvulisel argumendil n kirjelda-takse funktsiooni väärtuse kaudu argumendil n− 1.
– Funktsiooni väärtus mittetühjal listil x : l kirjeldatakse funktsiooniväärtuse kaudu listil l.
-
1 Rekursioon1.2 Protseduuri määratlemine rekursiivselt
11
Protseduuri määratlemine rekursiivselt
1 Rekursioon1.2 Protseduuri määratlemine rekursiivselt
12
Definitsioon funktsiooni kaudu
Kui protseduur sõltub mingist parameetrist, siis formaalselt on tegufunktsiooniga, mille väärtusteks on protseduurid.
-
1 Rekursioon1.2 Protseduuri määratlemine rekursiivselt
13
Otsene defineerimine
Pole põhimõttelisi takistusi protseduure määratleda puhtalt protseduuri-tasemel (mitte läbi funktsioonide).
– Kuna puudub parameeter, mis võiks rekursiivsel kutsel väheneda,siis lõpetamine sõltub muudest asjaoludest (keskkonnast loetud in-fost).
1 Rekursioon1.3 Listi määratlemine rekursiivselt
14
Listi määratlemine rekursiivselt
-
1 Rekursioon1.3 Listi määratlemine rekursiivselt
15
Listid on tsüklilised
Listid on olemuselt tsüklilised struktuurid: mittetühja listi saba on oma-korda list.
Seetõttu tuleb pikemate listide defineerimisel kasutada rekursiooni.
– Võimalik defineerida funktsiooni kaudu
– ja ka otse.
1 Rekursioon1.3 Listi määratlemine rekursiivselt
16
Otsene defineerimine
Listi määratlemisel tuleb
– kirjeldada listi algus (vähemalt üks element) ilma rekursiivsetekutseteta (n-ö baasjuht)
– ja kirjeldada ülejäänud osa rekursiivselt sama listi kaudu nii, et igaelemendi arvutamisel läheks vaja ainult eespool seisvaid elemente.
-
1 Rekursioon1.3 Listi määratlemine rekursiivselt
17
Erinevused funktsioonirekursioonist
• Jaotus baasiks ja sammuks toimub väärtuse, mitte argumendi järgi.
• Iga rekursiivset kutset rekursiivselt defineeritava listi poole kasutatak-se ülimalt üks kord.
– Ühekordsest sidumisest piisab, kuna puuduvad parameetrid, muu-tuv keskkond vms, mis võiks arvutuse käiku muuta.
1 Rekursioon1.3 Listi määratlemine rekursiivselt
18
Lõpmatud ja lõplikud listid
Otsese rekursiooniga on võimalik defineerida nii lõplikke kui ka lõpma-tuid liste.
– Lõpmatute listide defineerimine on lihtsam, sest puuduvad lõpeta-mistingimused.
-
1 Rekursioon1.4 Muud näited rekursioonist
19
Muud näited rekursioonist
1 Rekursioon1.4 Muud näited rekursioonist
20
Rekursioon suvalisel andmestruktuuril
Rekursiivselt on võimalik defineerida mida iganes.
– Nt puud.
– Ka staatilised andmestruktuurid nagu paarid.
– . . . .
-
1 Rekursioon1.4 Muud näited rekursioonist
21
Paradoksaalne rekursioon
Abistruktuure rekursiivselt defineerides on võimalik programmeerida ar-vutus, mis
– läbib listi vaid ühe korra, kuid
– loeb kõiki listi elemente mitu korda.
2 Programmeerimisvõtted 22
Programmeerimisvõtted
-
2 Programmeerimisvõtted2.1 Arvutamine rekursiivse funktsiooni argumentidel
23
Arvutamine rekursiivse funktsiooniargumentidel
2 Programmeerimisvõtted2.1 Arvutamine rekursiivse funktsiooni argumentidel
24
Imperatiivset programmeerimist jäljendav stiil
Imperatiivse programmeerimise jäljendamiseks võib defineerida rekur-siivselt abifunktsiooni, mille parameetrid vastavad imperatiivse prog-rammi vahetulemusi hoidvatele muutujatele.
– Rekursiivsel kutsel antakse edasi muudetud väärtused, esimeselväljakutsel algväärtused.
-
2 Programmeerimisvõtted2.1 Arvutamine rekursiivse funktsiooni argumentidel
25
Akumulaatorid
Akumulaator on rekursiivselt defineeritud operaatori parameeter, misarvutuse käigus kogub ja akumuleerib infot.
– Igal rekursiivsel kutsel lisatakse sinna midagi juurde.
2 Programmeerimisvõtted2.1 Arvutamine rekursiivse funktsiooni argumentidel
26
Akumulaatorite liigid
• Loendurid.
• Ehitajad.
• Arvutajad.
• . . . .
-
2 Programmeerimisvõtted2.1 Arvutamine rekursiivse funktsiooni argumentidel
27
Järjehoidjad
Järjehoidja on muutuja (tavaliselt akumulaator), mille väärtus näitabtööjärge.
– Tsükliindeksid.
– Läbivaadatud elementide nimekirjad.
– . . .
2 Programmeerimisvõtted2.2 Sabarekursioon
28
Sabarekursioon
-
2 Programmeerimisvõtted2.2 Sabarekursioon
29
Sabarekursioon
Funktsiooni rekursiivset definitsiooni nimetatakse sabarekursiivseks,kui tema järgi arvutades läheb rekursiivse kutse tulemus alati kogu arvu-tuse tulemuseks (ilma vaheteisendusteta).
– Rekursiivne kutse (kui see vaadeldavas harus esineb) on konkreet-se rekursioonitaseme viimasena lõpetav tegevus.
2 Programmeerimisvõtted2.2 Sabarekursioon
30
Sabarekursiooni ja akumulaatoritehnika seos
Üleminekul akumulaatoristiilile tekib tüüpiliselt sabarekursiivne definit-sioon.
– Kui kõik arvutus viia argumentidesse, ei jäägi midagi rekursioonisttagasipöördumise järel teha.
Kasutust leiab ka segastiil, kus arvutust jätkub nii akumulaatoritesse kuika rekursiivse kutse järele.
– Lõpmatuid liste akumulaatoris arvutada ei saa.
-
2 Programmeerimisvõtted2.2 Sabarekursioon
31
Sabarekursiooni tähtsus
Sabarekursiivset definitsiooni saab kompileerimisel optimeerida.
– Rekursiivsel kutsel võib uue rekursioonitaseme lokaalsete muutu-jate väärtused kirjutada endiste asemele.
– Tekib tavaline tsükkel.
2 Programmeerimisvõtted2.3 Jooksev väärtustamine
32
Jooksev väärtustamine
-
2 Programmeerimisvõtted2.3 Jooksev väärtustamine
33
Mälukasutuse optimeerimine
Mittesabarekursiivne definitsioon üldiselt ei võimalda arvutuse käigusvahetulemusi välja arvutada, tekib pikk väärtustamata avaldis.
– Arvutuse teostamiseks on tarvis rekursiivse kutse tulemust, temaväljaarvutamiseks omakorda tema rekursiivse kutse tulemust jne.
Reaalne arvutamine algab alles baasjuhuni jõudmisel.
Sabarekursioon laseb vahetulemused jooksvalt väärtustada, sest arvu-tused toimuvad argumentidel, rekursiivse kutse tulemust pole vaja.
2 Programmeerimisvõtted2.3 Jooksev väärtustamine
34
Probleem laisa väärtustamisega
Haskellis on vaikimisi laisk väärtustamine.
– Ka akumulaatoreid ei väärtustata!
-
2 Programmeerimisvõtted2.3 Jooksev väärtustamine
35
Väärtustusjärjekorra ohje
Haskellis on spetsiaalne agara väärtustamise operaator $!.
Sellega saavutame akumulaatoritega tõepoolest võidu mälutarbes.
– Väärtustatakse siiski ainult seni, kuni selgub, kas tegu on normaal-se väärtusega.
2 Programmeerimisvõtted2.4 “Jaga ja valitse”
36
“Jaga ja valitse”
-
2 Programmeerimisvõtted2.4 “Jaga ja valitse”
37
“Jaga ja valitse”
“Jaga ja valitse” on programmeerimise strateegia, milles
– mittetriviaalne ülesanne
∗ jagatakse kaheks või enamaks mingis mõttes ühesuurusekssama tüüpi alamülesandeks,
∗ lahendatakse need samal viisil ning∗ kombineeritakse tulemused kokku terve ülesande lahen-
duseks,
– triviaalne ülesanne lahendatakse otse.
2 Programmeerimisvõtted2.4 “Jaga ja valitse”
38
“Jaga ja valitse” stiili tuntud näited
• Kasvava funktsiooni väärtuse järgi argumendi otsimine (nn lõigu poo-litamise meetod e kahendotsing).
• Listis suurusjärjestuses etteantud kohal oleva elemendi leidmine (nnvaliku kiirmeetod).
• Listi järjestamine (kiirmeetod, põimemeetod).
• Hanoi tornide ülesanne.
• . . . .
-
2 Programmeerimisvõtted2.4 “Jaga ja valitse”
39
Realiseerimise viisid
• Otsene realisatsioon:
– jagatakse vahetuteks alamülesanneteks, mis lahendatakse üldjuhulrekursiivselt pöördudes, erijuhul otse.
• Realisatsioon alamülesannete listiga:
– jagatakse kohe triviaalseteks ülesanneteks,– koostatakse nende lahendustest list,– kombineeritakse lahendused puukujuliselt kokku.
2 Programmeerimisvõtted2.4 “Jaga ja valitse”
40
Dünaamiline programmeerimine
“Jaga ja valitse” strateegia korral võib sama alamülesannet tekkida kor-duvalt.
Dünaamiline programmeerimine on “jaga ja valitse” stiilis lahen-duse realiseerimine nii, et alamülesanded lahendatakse ühekordselt.
– Lahendus salvestatakse ja vajadusel korduvkasutatakse.
-
2 Programmeerimisvõtted2.4 “Jaga ja valitse”
41
Dünaamilise programmeerimise tuntud näited
• Fibonacci arvude leidmine.
• Kiire astendamine.
• Pikima ühise osasõne leidmine.
• . . . .
2 Programmeerimisvõtted2.4 “Jaga ja valitse”
42
Nõutust rohkem kirjeldamine
Laisk väärtustamine lubab koodis kirjeldada nõutust rohkem.
– Kui funktsiooni väärtus vajab väljaarvutamiseks paljusid eelne-vaid, siis defineerida lõpmatu list, milles nad kõik kirjas on.
– . . . .
Kirjeldades nõutust rohkem, saab koodi loetavamalt struktureerida.
– Kasutatakse dünaamilise programmeerimise abivõttena (kõigi ala-mülesannete lahenduste struktuuri, nt listi loomine).