Ispis od 1 do n
Napiši rekurzivnu funkciju koja ispisuje brojeve od 1 do n (u jednom redu, razdvojene razmakom). Petlje nisu dozvoljene.
Primer
Ulaz
5Izlaz
1 2 3 4 5Rekurzija je način rešavanja problema u kome funkcija poziva samu sebe, ali za manji problem. U ovoj lekciji vidimo kako se piše rekurzivna funkcija, šta je bazni slučaj i kako računar „pamti“ nedovršene pozive.
Zamisli red ljudi i pitanje „koji si po redu?“. Osoba ne broji ceo red, nego pita osobu ispred sebe i svom odgovoru doda 1. Prva osoba u redu ne pita nikoga – ona zna da je prva. Tako radi i rekurzivna funkcija:
Bez baznog slučaja funkcija bi se pozivala beskonačno – program se prekida greškom (prekoračenje steka).
Funkcija ispisuje broj n, a zatim „ostatak posla“ prepušta pozivu za n - 1:
#include <iostream>
using namespace std;
void odbrojavanje(int n) {
if (n == 0) { // bazni slučaj
cout << "Start!" << endl;
return;
}
cout << n << " ";
odbrojavanje(n - 1); // rekurzivni korak: isti posao za manji broj
}
int main() {
odbrojavanje(5);
return 0;
}
Izlaz: 5 4 3 2 1 Start!. Svaki poziv radi samo mali deo posla – ispisuje jedan broj.
Funkcija koja vraća vrednost čeka rezultat poziva za manji problem, pa tek onda završava svoj račun. Pogledajmo zbir prvih n prirodnih brojeva: zbir(n) = n + zbir(n - 1), a zbir(0) = 0.
#include <iostream>
using namespace std;
int zbir(int n) {
if (n == 0) return 0; // bazni slučaj
return n + zbir(n - 1); // čeka rezultat za n - 1
}
int main() {
int n;
cin >> n;
cout << zbir(n) << endl;
return 0;
}
| Korak | Poziv | Šta se dešava |
|---|---|---|
| 1 | zbir(4) | treba mu zbir(3) – čeka |
| 2 | zbir(3) | treba mu zbir(2) – čeka |
| 3 | zbir(2) | treba mu zbir(1) – čeka |
| 4 | zbir(1) | treba mu zbir(0) – čeka |
| 5 | zbir(0) | bazni slučaj, vraća 0 |
| 6 | zbir(1) | vraća 1 + 0 = 1 |
| 7 | zbir(2) | vraća 2 + 1 = 3 |
| 8 | zbir(3) | vraća 3 + 3 = 6 |
| 9 | zbir(4) | vraća 4 + 6 = 10 |
Nedovršeni pozivi čuvaju se na steku poziva: poslednji započet poziv prvi se završava. Zato je dubina rekurzije ograničena – za nekoliko stotina hiljada ugnježdenih poziva memorija za stek može da se potroši.
Redosled naredbi u odnosu na rekurzivni poziv menja rezultat. Funkcija ispod ispisuje cifre broja s leva na desno, iako se cifre izdvajaju s desna (n % 10): ispis je posle poziva, pa se izvršava tek kada se vrate svi kraći pozivi.
#include <iostream>
using namespace std;
void cifre(int n) {
if (n < 10) { // jednocifren broj: bazni slučaj
cout << n << " ";
return;
}
cifre(n / 10); // prvo sve cifre osim poslednje
cout << n % 10 << " "; // pa poslednja cifra
}
int main() {
int n;
cin >> n;
cifre(n);
cout << endl;
return 0;
}
Ako se ispis premesti pre poziva (cout << n % 10; cifre(n / 10);), cifre se ispisuju obrnutim redom.
| Petlja | Rekurzija | |
|---|---|---|
| Ponavljanje | telo petlje | novi poziv funkcije |
| Kraj | uslov petlje postane netačan | bazni slučaj |
| Memorija | stalna | raste sa dubinom (stek poziva) |
| Kada je bolja | jednostavno ponavljanje (zbir, brojanje) | problem se prirodno deli na manje iste probleme: stabla, grafovi, bektreking, „podeli pa vladaj“ |
Svaka rekurzija može da se zameni petljom (ponekad uz sopstveni stek), ali je rekurzivno rešenje često mnogo kraće i jasnije – videćemo to kod Hanojskih kula i bektrekinga.
Za svaki zadatak postoji primer, uputstvo i rešenje. Rešenja su provereno tačna na primerima iz teksta.
Napiši rekurzivnu funkciju koja ispisuje brojeve od 1 do n (u jednom redu, razdvojene razmakom). Petlje nisu dozvoljene.
51 2 3 4 5Napiši rekurzivnu funkciju int zbirCifara(int n) i ispiši zbir cifara unetog prirodnog broja.
407213Učitaj prirodan broj n i cifru c. Rekurzivno izbroj koliko puta se cifra c pojavljuje u zapisu broja n.
1231271 13Napiši rekurzivnu funkciju bool palindrom(const string &s, int i, int j) koja proverava da li je deo reči od pozicije i do j palindrom. Ispiši DA ili NE za učitanu reč.
anavolimilovanaDArekurzijaNEn - 1, n / 10), inače rekurzija ne staje.string i vector prenosi kao const & – inače se pri svakom pozivu pravi kopija.1. Šta je bazni slučaj rekurzije?
2. Šta ispisuje f(3) ako je void f(int n){ if(n==0) return; f(n-1); cout<<n; }?
3. Šta se dešava kada rekurzivna funkcija nema bazni slučaj?