From: Doni Pracner Date: Sat, 30 May 2015 11:01:49 +0000 (+0200) Subject: Simulacija rekurzije, dodatni kompleksniji primeri radjeni na casu X-Git-Url: https://svarog.pmf.uns.ac.rs/gitweb/?a=commitdiff_plain;h=97f70a20a007f00cc96c4c2beaac709cf5b79d87;p=spa1-materijali.git Simulacija rekurzije, dodatni kompleksniji primeri radjeni na casu --- diff --git a/kodovi/simulacija-rekurzije/Rek1.java b/kodovi/simulacija-rekurzije/Rek1.java new file mode 100644 index 0000000..2cc562a --- /dev/null +++ b/kodovi/simulacija-rekurzije/Rek1.java @@ -0,0 +1,106 @@ +/** + * Kompleksniji primer sa sukcesivnim pozivima. + * + * Sama funkcija nalazi maksimum niza polovljenjem intervala, medjutim + * nije neophodno razumeti funkciju da bi se ona simulirala. + * + * Funkcija je simulirana detaljno u skladu sa datim algoritmom, a naznacene + * su neke komande koje nisu bile neophodne da se navode posto nemaju efekta, + * no nije greska navesti ih. + * + * Pazljivom analizom funkcionisanja originalne funkcije mozemo videti + * da polje m2 nema svrhe pamtiti na steku, posto se vrednost postavlja + * tek nakon poslednjeg poziva. Medjutim ni ovo nije greska da se navede + * u simuliranoj verziji jer ne utice na ispravnost programa. + */ +public class Rek1 { + + static int[] niz; + + static int max(int d, int g) { + System.out.println(String.format("%d %d",d,g)); + if (d > g) { + return Integer.MIN_VALUE; + } + if (d == g) { + return niz[d]; + } + int m1 = max(d, (d + g) / 2); + int m2 = max((d + g) / 2 + 1, g); + if (m1 > m2) { + return m1; + } else { + return m2; + } + } + + private static class InfoTip { + int d, g, m1, m2, adr; + } + + static int maxS(int d, int g) { + int rez; + int m1,m2; + InfoTip el; + Stek s = new Stek(); + + do { + // rekurzivni spust + while (d < g) { + el = new InfoTip(); + el.d = d; + el.g = g; + el.m1 = 0;//nije postavljeno jos + el.m2 = 0;//nije postavljeno jos + el.adr = 1; + s.stavi(el); + g = (d + g) / 2; + } + + // trivijalni slucaj + if (d > g) { + rez = Integer.MIN_VALUE; + } else { // d == g + rez = niz[d]; + } + + // povratak iz rekurzije + boolean nemaPoziva = true; + while (!s.jePrazan() && nemaPoziva) { + el = s.skiniVrh(); + d = el.d; + g = el.g; + m1 = el.m1; + m2 = el.m2; + if (el.adr == 1) { + m1 = rez; + el.m1 = m1; + el.adr = 2; + el.m2 = 0;//nije potrebno zapravo + el.d = d;//nije potrebno zapravo + el.g = g;//nije potrebno zapravo + s.stavi(el); + d = (d + g) / 2 + 1; + nemaPoziva = false; + } else { // adr je 2 + m2 = rez; + if (m1 > m2) { + rez = m1; + } else { + rez = m2; + } + } + } + } while (!s.jePrazan()); + + return rez; + } + + public static void main(String[] args) { + niz = new int[] { 300, 2, 5, -7, 20, 66, 128 }; + + System.out.print(max(0, niz.length - 1)); + System.out.print(" = "); + System.out.println(maxS(0, niz.length - 1)); + } +} diff --git a/kodovi/simulacija-rekurzije/Rek2.java b/kodovi/simulacija-rekurzije/Rek2.java new file mode 100644 index 0000000..7091719 --- /dev/null +++ b/kodovi/simulacija-rekurzije/Rek2.java @@ -0,0 +1,106 @@ +/** + * Kompleksniji primer u kome simuliramo funkciju cije funkcionisanje + * i rezultat nisu nuzno jasni. + * + * U funkciji postoje ugnjezdjeni pozivi na koje treba obratiti paznju. + * + * Ova verzija resenja takodje sadrzi i ispise parametara na 'ulazu' u + * funkciju, i iste takve kod simulirane verzije da se jasno vidi da se + * svi pozivi desavaju u istom redosledu, pri cemu su dodatno naznacene + * adrese poziva u simuliranoj verziji. Ovakav dodatak nije potreban inace + * za resavanje, ali moze pomoci u razumevanju i proveri da li je + * sve ispravno uradjeno. + */ +public class Rek2 { + + static int g(int x, int y, int n) { + System.out.printf("0 %d %d %d\n",x,y,n); + if (n < 3) { + return x + y; + } + + if (n % 2 == 1) { + return g(g(x + 1, y, n - 2), y, n - 3); + } else { + return g(x, g(x, y + 1, n - 2), n - 3); + } + } + + private static class InfoTip { + int x, y, n, adr; + } + + static int gS(int x, int y, int n) { + int rez; + InfoTip el; + Stek s = new Stek(); + System.out.printf("%d %d %d %d\n",0,x,y,n); + + do { + // rekurzivni spust + while (n >= 3) { + if (n % 2 == 1) { + el = new InfoTip(); + el.x = x; + el.y = y; + el.n = n; + el.adr = 1; + s.stavi(el); + x = x + 1; + n = n - 2; + System.out.printf("%d %d %d %d\n",el.adr,x,y,n); + } else { + el = new InfoTip(); + el.x = x; + el.y = y; + el.n = n; + el.adr = 3; + s.stavi(el); + y = y + 1; + n = n - 2; + System.out.printf("%d %d %d %d\n",el.adr,x,y,n); + } + } + + // trivijalni slucaj + rez = x + y; + + // povratak iz rekurzije + boolean nemaPoziva = true; + while (!s.jePrazan() && nemaPoziva) { + el = s.skiniVrh(); + x = el.x; + y = el.y; + n = el.n; + if (el.adr == 1) { + el.x = x; // nije potrebno zapravo + el.y = y; // nije potrebno zapravo + el.n = n; // nije potrebno zapravo + el.adr = 2; + s.stavi(el); + x = rez; + n = n - 3; + System.out.printf("%d %d %d %d\n",el.adr,x,y,n); + nemaPoziva = false; + } else if (el.adr == 3) { + el.x = x; // nije potrebno zapravo + el.y = y; // nije potrebno zapravo + el.n = n; // nije potrebno zapravo + el.adr = 4; + s.stavi(el); + y = rez; + n = n - 3; + System.out.printf("%d %d %d %d\n",el.adr,x,y,n); + nemaPoziva = false; + } // adr 2 i 4 + // rez = rez; nema smisla pisati + } + } while (!s.jePrazan()); + return rez; + } + + public static void main(String[] args) { + System.out.println(g(2, 3, 11)); + System.out.println(gS(2, 3, 11)); + } +}