You are on page 1of 33

REKURZIJA

1
PROGRAMIRANJE II 2010/11.
REKURZIJA

2
PROGRAMIRANJE II 2010/11.
Primjer rekurzivnog postupka
Recimo, da idemo u trgovinu.
Možemo postupiti ovako:
Uzastopno koračamo u smjeru trgovine,
dok ne dođemo do nje.

Drugi način:

Ako smo u trgovini, "obavili smo radnju".


Inače, napravimo korak u smjeru trgovine
i zatim (od toga mjesta) idemo u trgovinu.

3
PROGRAMIRANJE II 2010/11.
Funkcija za postupak: idemoUTrgovinu()

void idemoUTrgovinu() {
if (u trgovini) obavljeno;
else {
napravi jedan korak prema trgovini;
idemoUTrgovinu()
}
}

rekurzivni poziv
4
PROGRAMIRANJE II 2010/11.
Rekurzija kao matematički pojam

 Rekurzija - definiranje pojma pomoću samog


sebe s obzirom na varijablu rekurzije

 Varijabla rekurzije ima prebrojivo mnogo


vrijednosti uređenih po veličini i jednoznačnu
minimalnu vrijednost.

 Rekurzivna definicija je sastavljena iz dva dijela:


- rubni uvjet
- definicija pojma za neku vrijednost varijable rekurzije s
uporabom poznatih pojmova i sa uporabom samog
pojma pri manjim vrijednostima varijable rekurzije
5
PROGRAMIRANJE II 2010/11.
Osnovni princip rekurzije

Načelo "podijeli i savladaj":


korak podjele problema
korak savladavanja
kombiniranje dobivenih rješenja
potproblema u rješenje izvornog problema

6
PROGRAMIRANJE II 2010/11.
Rekurzivna funkcija
Rekurzivna funkcija – funkcija koja poziva
samu sebe

Do rekurzije dolazi, ako funkcija poziva


samu sebe, direktno ili indirektno preko
lanca poziva drugih funkcija.

Rekurzija:
 eksplicitna, direktna
 implicitna, indirektna rekurzija
7
PROGRAMIRANJE II 2010/11.
Rekurzivna funkcija

Svaki problem koji se može riješiti rekurzivno


može se riješiti i iterativno (uz pomoć petlje).
Rekurzivno rješenje je jednostavnije napisati od
iterativnog rješenja, kada je problem po svojoj
prirodi rekurzivan.
Ipak, rekurzivno rješenje ne mora biti jednako
učinkovito kao iterativno rješenje istog problema.
Slijedi problem koji je po svojoj prirodi iterativan,
a pogledati ćemo oba pristupa rješavanja.

8
PROGRAMIRANJE II 2010/11.
Primjer 1: Problem izračunavanja
faktorijele pozitivnog cijelog broja n

Iterativna definicija:
n! = 1 x 2 x 3 x ... x n, za n>=1

Funkcija ima vrijednosti:


faktorijela(1) = 1
faktorijela(2) = 1*2 = 2
faktorijela(3) = 1*2*3 = 6
faktorijela(4) = 1*2*3*4 = 24 itd.

9
PROGRAMIRANJE II 2010/11.
#include<iostream.h>
unsigned long FAKT(int n);
void main(){
int n;
cout<<"Unesi prirodni broj: ";
cin>>n;
cout<<"\n"<<n<<"! = "<<FAKT(n)<<endl;
}
unsigned long FAKT(int n){
unsigned long fjel=1;
for(int i =2; i<=n; i++)
fjel*=i;
return fjel;
}
10
PROGRAMIRANJE II 2010/11.
Rekurzivno rješenje se temelji na
rekurzivnoj definiciji funkcije za
izračunavanje faktorijele:

0! = 1
n! = n x (n-1)!, za n=1,2,3,4,...

11
PROGRAMIRANJE II 2010/11.
#include<iostream.h>
unsigned long faktorijela(int n);
void main(){
int n;
unsigned long F;
cout<<"Unesi prirodni broj: ";
cin>>n;
F=faktorijela(n);
cout<<"\n"<<n<<"! = "<<F<<endl;
}
unsigned long faktorijela(int n){
long int f; // Ako riješavamo bez lokalne varijable
if (n==0 || n==1)f=1; // tada pišemo return 1
else // ovu liniju možemo izostaviti
f=n*faktorijela(n-1); // pišemo return n*faktorijela(n-1)
return f; // ovu liniju možemo isto izostaviti
} 12
PROGRAMIRANJE II 2010/11.
Rekurzivna izvedba računanja faktorijele [Šribar]
13
PROGRAMIRANJE II 2010/11.
UPORABA STOGA PRI POZIVU
POTPROGRAMA

xx

cc cc cc

bb bb bb

aa aa aa

trenutno stanje push xx pop xx


14
PROGRAMIRANJE II 2010/11.
područje podataka za poziv faktorijela(1)

područje podataka za poziv faktorijela(2)

područje podataka za poziv faktorijela(3)

područje podataka glavnog programa

Uporaba stoga u rekurzivnoj izvedbi računanja


faktorijele prirodnog broja

15
PROGRAMIRANJE II 2010/11.
Primjer: Euklidov algoritam (izračunavanje
najvećeg zajedničkog djelitelja za dva cijela broja)

nzd(x,y) se izračunava prema definiciji:


za y=0 nzd(x,y)=x
inače nzd(x,y)=nzd(y, x mod y)

Rekurzivna funkcija:
int nzd(int x,int y)
{
if(y==0)return x;
return nzd(y,x%y);
}

16
PROGRAMIRANJE II 2010/11.
Prednosti i nedostaci rekurzije u
odnosu na iteraciju
Prednosti rekurzije:
Rekurzivno riješenje je često prirodnije (npr. izvedba
postupaka na rekurzivnim strukturama podataka).
Izvori nedostataka rekurzije:
Prostor koji rekurzija koristi na stogu proporcionalan je
dubini rekurzije (najveći stupanj gnježđenja funkcija u
rekurziji).
Rekurzija je i vremenski zahtjevna - iterativna rješenja
su obično učinkovitija.
Za rekurziju se odlučujemo kada je problem po
svojoj prirodi rekurzivan, a odgovarajuće
iterativno rješenje nije puno učinkovitije.
17
PROGRAMIRANJE II 2010/11.
Primjer neočekivanog rasta
zahtjevnosti problema
Prema legendi je pravila za šah izmislio indijski
mudrac Seta. Vladar Šeram mu je obećao za
nagradu pokloniti što god poželi.
Seta je za nagradu izabrao zrna pšenice, toliko
koliko je polja na šahovnici: na prvo polje 1 zrno,
na drugo 2 zrna, na treće 4 i na svako slijedeće
dva puta više nego na prethodno (za zadnje
polje 264 zrna).
•Vladar
18 446 744je 073
bio709
razočaran
551 615 zrna što Seta omalovažava
•njegovu velikodušnost,
1 200 000 000 000 m3 (u 1m3 idealipribližno
se neugodno iznenadio
15 milijuna zrna)
•kada
Ako je su njegovi
širina mudraci
silosa 10m, izračunali količinu zrnja,
a visina 4m:
koju duguje
silos ima duljinuSeti:
30 000 000 km
= 80x udaljenosti do Mjeseca ili petina udaljenosti od Zemlje do18
Sunca PROGRAMIRANJE II 2010/11.
Primjer: Problem hanojskih kula

Ovaj problem je po svojoj prirodi rekurzivan.


Imamo tri stupa i N obruča različitih veličina, koji
se nalaze u početnoj poziciji svi na prvom stupu i
to tako da je najveći na dnu, a najmanji na vrhu.
Cilj je obruče premjestiti na treći stup u istom
poretku i pri tome se smije koristiti drugi stup
kao pomoćni. U svakom trenutku se smije
pomicati samo jedan obruč.
Prema legendi svećenici u jednom hramu su
dobili zadatak sa 64 obruča. pokazuje se da bi im
za izvršenje trebalo 348 stoljeća, kad bi u svakoj
sekundi napravili jedan ispravan potez. 19
PROGRAMIRANJE II 2010/11.
Primjer: Problem hanojskih kula (disc.exe)
Zadatak:
Premjesti_kulu(n,1,3,2)

Program:
#include <iostream.h>
void premjesti_kulu(int n,int sa,int
na,int pom);
void main(){
int n;
cout<<"\n Unesi broj diskova: ";
cin>>n;
premjesti_kulu(n,1,3,2);
cout<<endl;
}
void premjesti_kulu(int n,int sa,int na,int
pom){
if (n>0){
premjesti_kulu(n-1,sa,pom,na);
cout<<endl<<sa<<"-->"<<na;
premjesti_kulu(n-1,pom,na,sa);
} 20
PROGRAMIRANJE II 2010/11.
}
n=3
1  3, 1  2, 3  2, 1  3, 2  1, 2  3, 1  3

http://home.comcast.net/~asunnet/hanoi/
http://www.softschools.com/games/logic_games/tower_of_hanoi/

21
PROGRAMIRANJE II 2010/11.
Primjer 1: Inverzni ispis unesenog niza
znakova koji završava zvjezdicom (inverz.cpp)

#include <iostream.h> void inverz(){


void inverz(); char x;
cin>>x;
void main(){ if (x!='*')inverz();
inverz(); cout<<x;
}
cout<<endl;
}

22
PROGRAMIRANJE II 2010/11.
Primjer 2: Program s rekurzivnom funkcijom za
izračunavanje sume prirodnih brojeva od 1 do k

#include <iostream.h>
int suma(int n);
void main(){
int k;
cin>>k;
cout<<"\nSuma= "<<suma(k)<<endl;
}

int suma(int n){


if(n==0) return 0;
return n+suma(n-1);
}
23
PROGRAMIRANJE II 2010/11.
Primjer 3: Izračunavanje potencije xy

Kako napisati pot(int x, int y) rekurzivno?

int pot(int x, int y){


if(y==0)
return 1;
return x * pot(x, y-1);
}

24
PROGRAMIRANJE II 2010/11.
Primjer 4:
Napiši rekurzivnu funkciju koja na ulazu ima polje
sa elementima tipa double i veličinu polja, te
vraća zbroj elemenata polja.

double azbroj(int a[], int size){


if(size==0)
return 0;
return azbroj(a, size-1)+a[size-1];
}

25
PROGRAMIRANJE II 2010/11.
Primjer 5
Napiši rekurzivnu funkciju koja broji koliko ima
nula u nenegativnom broju.
brojiNule(10200) vraća 3

int brojiNule(int n){


if(n==0)
return 1;
if(n < 10)
return 0;
if(n%10 == 0)
return 1 + broji Nule(n/10);
else
return brojiNule(n/10);
}
26
PROGRAMIRANJE II 2010/11.
Primjer sa kviza: Što se ispisuje prilikom
izvršavanja programa?
#include <iostream.h>
void xxx(int n);
Ispis:
321123
void main(){
xxx(3);
cout<<endl;
}

void xxx(int n){


cout<<n;
if (n>1)xxx(n-1);
cout<<n; 27
PROGRAMIRANJE II 2010/11.
Primjer sa kviza:
Što vraća poziv f(3,4)? Što računa funkcija?
int f(int a, int b){
if(b == 0)
return 1;
return a * f(a, b-1);
}

Funkcija računa ab, a vraća 81.


28
PROGRAMIRANJE II 2010/11.
Primjer sa kviza:
Što vraća poziv f(5)? Što računa funkcija?

int f(int a){


if(a == 0)
return 1;
return (f(a-1) * a);
}

Funkcija računa n! i vraća 120.

29
PROGRAMIRANJE II 2010/11.
Primjer sa kviza:
Što vraća poziv f(72,54)? Što računa funkcija?

int f(int a, int b){


if(a==b)
return a;
if(a > b)
return f(a-b, b);
else
return f(a, b-a);
}

Funkcija računa nzd(a,b) i vraća 18.


30
PROGRAMIRANJE II 2010/11.
Primjer sa kviza:
Nadopuni rekurzivnu funkciju koja računa
zbroj prirodnih brojeva od 1 do n. Poziv
f(5) treba vratiti 15.

int f(int n){

31
PROGRAMIRANJE II 2010/11.
Napiši rekurzivnu funkciju koja računa
umnožak prirodnih brojeva od a do b (za
b>a).

32
PROGRAMIRANJE II 2010/11.
Preporuka za čitanje:
rekurzija.doc (prema Sedgewick, pogl.5)

33
PROGRAMIRANJE II 2010/11.

You might also like