Navigacija
Lista poslednjih: 16, 32, 64, 128 poruka.

Rekurzija - princip

[es] :: C/C++ programiranje :: C/C++ za početnike :: Rekurzija - princip

[ Pregleda: 3500 | Odgovora: 15 ] > FB > Twit

Postavi temu Odgovori

Autor

Pretraga teme: Traži
Markiranje Štampanje RSS

grabber
Gorazde

Član broj: 213110
Poruke: 172
*.pppoe03-744.bih.net.ba.



Profil

icon Rekurzija - princip04.04.2010. u 13:21 - pre 171 meseci
Pozdrav, iz Algoritama radim trenutno rekurziju, i nikako da shvatim princip, evo recimo na primjeru faktorijela kojeg sam ispod napisao, kako god propratim program, cini mi se da ce funkcija vratit rezultat 1 :S Evo primjera:

Code:
long fakt(int n)

     long nfakt;
     if (n<=1)
          nfakt=1;
     else
          nfakt=n*fakt(n-1);
     return nfakt;
}


vidim da su svi zadaci otprilike na istom principu, i samo malo mi treba ja mislim da shvatim :) u konkretno primjeru iznad, zar funkcija nece kad odradi recimo ako je u početku n=5, zar ona neće smanjivati svakog puta, i kada dođe do 1 nfakt će postati 1, i return nfakt će ustvari biti return 1?
 
Odgovor na temu

maksvel

Član broj: 107376
Poruke: 2417

Jabber: maksvel
Sajt: maksvel.in.rs


+161 Profil

icon Re: Rekurzija - princip04.04.2010. u 13:47 - pre 171 meseci
Ova funkcija "zna" da je faktorijel od 1 (ili manjeg broja) 1 i da je faktorijel nekog broja proizvod tog broja i "prethodnog faktorijela".
Ako tražiš faktorijel od 5, funkcija "zadržava" konačno množenje, sve dok ne stigne do izračinavanja faktorijela jedinice.
Prvo je 5!=5*4! (zadržava, tj. zove ponovo f-ju - ta petica "visi", dok ne stignu ostali rezultati poziva), pa ima 4!=4*3! itd, dok ne stigne do 2=2*1! (a 1! ume da izračuna neposredno). Onda se izmnoži sve "unazad" i funkcija se završi.
(Nije baš 100% korektno objašnjenje, ali je poenta tu, bar se nadam. )


[Ovu poruku je menjao maksvel dana 04.04.2010. u 15:32 GMT+1]
 
Odgovor na temu

X Files
Vladimir Stefanovic
Pozarevac

SuperModerator
Član broj: 15100
Poruke: 4902
212.200.65.*

Jabber: xfiles@elitesecurity.org


+638 Profil

icon Re: Rekurzija - princip04.04.2010. u 16:11 - pre 171 meseci
Jedan mali dodatak maksvel-ovom objasnjenju.

Rekurzivna funkcija poziva samu sebe, uvek sa nekom drugom vrednoscu argumenta i podesena je da u jednom trenutku izadje i pozivaocu vrati resenje.

Druga vrednost argumenta se postize sa n-1 a izlazi se kada se ispuni (n<=1).
 
Odgovor na temu

Wajda.W
Vladimir Vajda
Zrenjanin

Član broj: 127039
Poruke: 323
*.dynamic.isp.telekom.rs.



+101 Profil

icon Re: Rekurzija - princip04.04.2010. u 16:32 - pre 171 meseci
Recursion:
If you don't get it, see Recursion.
 
Odgovor na temu

grabber
Gorazde

Član broj: 213110
Poruke: 172
*.pppoe03-744.bih.net.ba.



Profil

icon Re: Rekurzija - princip04.04.2010. u 17:07 - pre 171 meseci
sve je to ok, ali jos uvijek ne kontam zasto nece ispisat uvijek rezultat 1, jer nebitno koji broj proslijedim kao argument funkciji, on će doći na kraju do n<=1, tj do n=1 i onda bi nfakt postao 1.
 
Odgovor na temu

proka_92
proka_92
Smederevo

Član broj: 153372
Poruke: 69
109.93.0.*



+4 Profil

icon Re: Rekurzija - princip04.04.2010. u 17:58 - pre 171 meseci
Pazi... Gledaj na sledeci poziv kao na izvrsenje nove funkcije, znaci kad se prvi put pozove sa parametrom npr. 5, ta petica ceka da se vrate sve ostale vrednosti i da se izmnozi sa njima... nfakt ti postaje 1 u poslednjem pozivanju i ta vrednost se vraca funkciji koja je pozvana pre toga... Nadam se da ti je malo jasnije, ja sam to na taj nacin skapirao, mozda ce neko umeti malo bolje da ti objasni :)
 
Odgovor na temu

Mihajlo Cvetanović
Beograd

Moderator
Član broj: 37636
Poruke: 1249



+96 Profil

icon Re: Rekurzija - princip04.04.2010. u 18:50 - pre 171 meseci
Lokalne promenljive unutar funkcije (kao i parametri funkcije) su jedinstveni za taj poziv funkcije. Ako funkcija poziva samu sebe pet puta onda se negde u memoriji (na takozvanom steku) nalazi pet promenljivih nfakt, svaka unutar sopstvene funkcije. Tih pet promenljiva ne dele istu vrednost, nego svaka ima svoju.
 
Odgovor na temu

Wajda.W
Vladimir Vajda
Zrenjanin

Član broj: 127039
Poruke: 323
*.dynamic.isp.telekom.rs.



+101 Profil

icon Re: Rekurzija - princip05.04.2010. u 12:56 - pre 171 meseci
Ajde da se i ja oprobam u objasnjavanju. :)
Ovako recimo da pozivas f-ju sa parametrom 4 (uzeo sam ovu vrednost da objasnjavanje ne bi potrajalo).
Znaci negde u kodu imas promenljivu kojoj dodeljujes rezultat f-je fakt
Code:

long broj;
broj = fakt(4);


ovo se desava u memoriji, manje vise:

Code:

long fakt(4)   // n je 4

     long nfakt;
     if (4<=1)
          nfakt=1;
     else
          nfakt=4*fakt(3);
     return nfakt;
}


e sad, posto je 4 vece od 1 prolazi se u else deo, a tu opet imamo poziv ove iste f-je samo sa parametrom 3

Code:

long fakt(3)   // n je 3

     long nfakt;
     if (3<=1)
          nfakt=1;
     else
          nfakt=3*fakt(2);
     return nfakt;
}


sad opet uslov nije zadovoljen i opet se prelazi u else deo, i opet tu imas poziv f-je, ali sada sa parametrom 2

Code:

long fakt(2)   // n je 2

     long nfakt;
     if (2<=1)
          nfakt=1;
     else
          nfakt=2*fakt(1);
     return nfakt;
}


opet ista prica i opet poziv f-je samo sa parametrom 1

Code:

long fakt(1)   // n je 1

     long nfakt;
     if (1<=1)
          nfakt=1;
     else
          nfakt=1*fakt(0);
     return nfakt;
}


e sad, ova je jako bitna, ovde else deo nece biti odradjen, jer je 1 <= od 1, i nfakt ce dobiti vrednost 1 i vratiti 1 kao rezultat.
ALI NE U U GLAVNI PROGRAM, NEGO U F-JU KOJA JE TU F-JU POZVALA. U ovom slucaju f-ju fakt sa parametrom 2.
Pa ce f-ja sa parametrom 2 izgledati ovako ustvari:
Code:

long fakt(2)   // n je 2

     long nfakt;
     if (2<=1)
          nfakt=1;
     else       nfakt=2*1;  // ovo je bitno, sada cemo tu imati 1 umesto f-je fakt(1) jer je tu vrednost ta f-ja vratila
     return nfakt;
}

ova f-ja ce vratiti rezultat 2*1 sto je 2 i proslediti taj rez f-ji koja je nju pozvala, tj f-ji sa parametrom 3, koja ce posle vracanej vrednosti da izgleda ovako
Code:

long fakt(3)   // n je 3

     long nfakt;
     if (3<=1)
          nfakt=1;
     else
          nfakt=3*2;  // jer je rezultat f-je fakt(2) 2 kao sto smo gore videli
     return nfakt;
}


to znaci da ce f-ja fakt(3) vratiti 2*3 sto je 6 f-ji koja je nju pozvala, tj f-ji fakt(4)

Code:

long fakt(4)   // n je 4

     long nfakt;
     if (4<=1)
          nfakt=1;
     else
          nfakt=4*6;
     return nfakt;
}

a ova f-ja vraca 4*6 sto je 24 tamo gde je ona pozvana, tju glavni program, a to je i vrednost faktorijela broja 4.
Jos jedna bitna osobina: F-JA SE NECE ZAVRSITI DOK SE NJOJ NE VRATI VREDNOST F-JE KOJU JE ONA POZVALA, znaci fakt(4) ce cekati dok fakt(3) ne vrati njemu vrednost, a fakt(3) ce cekati dok fakt(2) ne vreti vrednost, i tako redom... Tek kad se f-ja koja nema poziva zavrsi onda se krece unazad.
 
Odgovor na temu

sasaz2008

Član broj: 200415
Poruke: 204
*.adsl.eunet.rs.



+4 Profil

icon Re: Rekurzija - princip05.04.2010. u 20:59 - pre 171 meseci
grabber, rekurzija je vrlo jednostavna i moćna tehika, ali ujedno i veliki potrošač resursa... Glavno je da treba zapamtiti da kada funkcija/procedura poziva samu sebe, pre poziva snimi na steku sve promenljive koje se u njoj koriste i tačku sa koje poziva samu sebe, pa kad jednom stigne do uslova kojim regularno izadje (return), vraća se na predhodno zapamćenu tačku prekida i tako nastavlja dalje dok stek ne bude prazan (uslovno rečeno)...

Najjednostavniji primer je rekurzivno izračunavanje faktorijela koje je i ovde navedeno. Dakle, faktorijel od n (n!) je definisan samo za pozitivne cele brojeve sa izuzetkom 0, gde je 0! =1, za negativne vrednosti treba vratiti grešku. To je osnovna postavka zadatka.

Uzmimo na primer 5!, to je x=n*(n-1)!, gde n ide od 5 do 1.

Za fakt(5), odnosno n=5 proveri da li je n=0, ako nije, snimi sve promenljive, zapamti gde si stao i pozovi sam sebe sa nfakt = 5* fakt(4), nfakt je nedefinisano.

fakt(4), isto kao i predhodno samo 4* fakt(3) itd.

Kada dodje do poziva sa nfakt = 1 * fakt(0), pri put će nam za n biti poznata vrednost nfakt, a to je 1.

Sada funkcija vraća vrednost 1 i sa steka skida vrednost promenjive n (koja je 1), nfakt (nedefinisan) i pozicije odakle je pozvala samu sebe. Kako je nfakt=n*fakt(n-1), odnosno nfakt=1*fakt(1-1), a vrednost fakt(0) smo upravo dobili (1), možemo da izračunamo nfakt=1*1=1.

Dalje n=2, vraća se 1, a to je vrednost za fakt(1), pa je sada nfakt:= 2 * fakt(1)= 2 * 1 = 2
Dalje n=3, vraća se 2, a to je vrednost za fakt(2), pa je sada nfakt:= 3 * fakt(2)= 3 * 2 = 6
Dalje n=4, vraća se 6, a to je vrednost za fakt(3), pa je sada nfakt:= 4 * fakt(3)= 4 * 6 = 24
Dalje n=5, vraća se 24, a to je vrednost za fakt(4), pa je sada nfakt:= 5 * fakt(4)= 5 * 24 = 120

Tu se proces obustavlja, jer je stek prazan i vraća se 120.

Faktorijel je možda jednostavan primer, ali nije baš zgodan pošto se može jednostavno rešiti jednom for petljom, tako da to može da zbunjuje zašto se uopšte koristi rekurzuja. Mnogo bolji primer je QSort ili rešenje Hanojskih kula. Oba algoritma su malo složenija i pokazuju šta se tačno dešava sa promenljivama i tačkama prekida. Još drugi jedan dobar primer kojeg se mogu setiti za primenu rekurzije je brisanje binarnog stabla.

[Ovu poruku je menjao sasaz2008 dana 05.04.2010. u 22:11 GMT+1]
 
Odgovor na temu

Sini82

Član broj: 234605
Poruke: 479
91.191.9.*

Jabber: Sini82@elitesecurity.org


+33 Profil

icon Re: Rekurzija - princip06.04.2010. u 10:27 - pre 171 meseci
Citat:
grabber

long fakt(int n)
{
long nfakt;
if (n<=1)
nfakt=1;
else
nfakt=n*fakt(n-1);
return nfakt;
}


Pogledajmo šta se dešava kada funkcija ima argument 1: u trećem redu tijela funkcije nfakt uzima vrijednost 1, zatim se izvrsava šesti red, tj. funkcija vraća vrijednost 1 a ne vrijednost koju je imala kada je prethodni put izvršena pomnozenu sa 1.
Inače, rekurzivna funkcija je funkcija koja poziva samu sebe.

Ispravka:

#include <iostream>
using namespace std;

long fakt(int n)
{
long nfakt;
if (n==1)
return 1;
else return n*fakt(n-1);
}


main()
{
int m;
cout<<"Unesi cijeli broj: ";
cin>>m;
if (m>=1)
cout<<m<<"!="<<fakt(m);
else cout<<"Faktorijel negativnog broja nije definisan!";
return 0;
}
 
Odgovor na temu

grabber
Gorazde

Član broj: 213110
Poruke: 172
92.36.130.*



Profil

icon Re: Rekurzija - princip06.04.2010. u 16:05 - pre 171 meseci
Hvala puno ljudi, mislim da sam napokon shvatio! I sad, zasto i gdje koristiti rekurziju, kada je gotovo nemoguce odraditi posao sa malo vecim brojevima u nekom realnom vremenskom periodu?
 
Odgovor na temu

Wajda.W
Vladimir Vajda
Zrenjanin

Član broj: 127039
Poruke: 323
*.dynamic.isp.telekom.rs.



+101 Profil

icon Re: Rekurzija - princip06.04.2010. u 17:00 - pre 171 meseci
Rekurziju gledaj da koristis samo za resavanje rekurzivnih problema, tj problema koji nemaju iterativno resenje, svaki problem koji mozes i iteretivno i rekurzivno uvek radi iterativno.
Neki od tih problema su pretraga binarnog stabla, brisanje binarnog stabla (skoro sve u vezi sa stablima) i ima jos nekih.
Faktorijel je interesantno problem koji se resava iterativno, a u svakoj knjizi u kojoj ima objasnjenje rekurzije se nalazi bas resavanje faktorijela. :)
Sto se naravno ne radi rekurzijom.
Znaci samo ako ne mozes nesto da resis iterativno onda rekurzijom (to je tako u 99% slucajeva), ima i problema koje je bilje resiti rekurzivno, npr sortiranje niza (quicksort), ali ih je mnogo manje.
 
Odgovor na temu

sasaz2008

Član broj: 200415
Poruke: 204
*.adsl.eunet.rs.



+4 Profil

icon Re: Rekurzija - princip06.04.2010. u 17:10 - pre 171 meseci
grabber,

Kao prvo, svaki rekurzivni algoritam se može prevesti u nerekurzivni (sam simuliraš stek), ali je onda kod malo nečitljiviji.

Drugo, stek je u mnogim programskim jezicima ograničen na veoma male vrednosti, koje se mere KB. To se može i promeniti, ali za to treba dobro poznavati kompajler.

Treće, rekurzija se najčešće koristi tamo gde je potrebna provera raznih kombinacija, kao recimo u šahu, traženje izlaza iz lavirinta, pronalaženje najkraćeg puta od mesta A do mesta Z i sl. Koliko će vremena biti potrebno, zavisi od broja kombinacija koje se ispituju i složenosti algoritma koji svaku kombinaciju obradjuje. Obično brzina za izvršavanje nekih realnih problema (kao što je nalaženje najkraćeg puta) danas nije nikakvo ograničenje, ali jeste ograničenje koje nameće stek. U teoriji postoji način da se izračuna vreme potrebno za izvršavanje, ali to moraš da izračunaš za konkretan algoritam. Generalan način kako se to radi možeš da nadješ u svakoj knjizi za učenje osnova algoritama ili potraži na internetu.
 
Odgovor na temu

Dekisa
Dejan Jankovic
Loznica,Srbija

Član broj: 289036
Poruke: 2
*.teol.net.



Profil

icon Re: Rekurzija - princip12.08.2011. u 18:57 - pre 154 meseci
Wajda,procitah tvoj komentar,a upravo se prilicno mucim sa quick sortom...pa da li bi bio problem da mi pojasnis nekako?
Takodje, radim rekurziju u stablima,i veoma se mucim,ali vasi komentari pomazu!
 
Odgovor na temu

Dekisa
Dejan Jankovic
Loznica,Srbija

Član broj: 289036
Poruke: 2
*.teol.net.



Profil

icon Re: Rekurzija - princip12.08.2011. u 21:12 - pre 154 meseci
****jedan problem u stablima****
Potrebno je da nadjem visinu prvog cvora u stablu koji nema jedno dete barem

public int visinaCvoraBezDeteta(CvorStabla koren){
if(k==null) return 0;
if(k.levo==null || k.desno==null) return 1;
return 1+Math.min(visinaCvoraBezDeteta(k.levo),visinaCvoraBezDeteta(k.desno));
}

// e sad mene buni ovaj kec u posledjem returnu
//moje je misljenje da treba bez njega,jer ovako dobijamo visinu za 1 vecu od stvarne

Jesam li u pravu?
 
Odgovor na temu

Mihajlo Cvetanović
Beograd

Moderator
Član broj: 37636
Poruke: 1249



+96 Profil

icon Re: Rekurzija - princip15.08.2011. u 09:49 - pre 154 meseci
Funkcija ne vraća visinu nego nivo čvora. Koren stabla je na prvom nivou i ako je koren rezultat onda funkcija vraća 1. Ako bi pozvao funkciju sa null onda bi vratila 0. Meni se to čini kao dobra organizacija, ali ako ti ne odgovara onda napravi novu funkciju koja hendluje parametar null kako već misliš da treba, a inače vraća vrednost visinaCvoraBezDeteta(x) - 1 kao rezultat.
 
Odgovor na temu

[es] :: C/C++ programiranje :: C/C++ za početnike :: Rekurzija - princip

[ Pregleda: 3500 | Odgovora: 15 ] > FB > Twit

Postavi temu Odgovori

Navigacija
Lista poslednjih: 16, 32, 64, 128 poruka.