Rekursif
Pada akhir pertemuan ini, diharapkan mahasiswa akan mampu:
Menjelaskan defnisi rekursif
Menerapkan rekursif dalam pembuatan
program
Membedakan rekursif dan iteratif
Defnisi rekursif Deklarasi rekursif
Penggunaan rekursif
Analisa rekursif dan iterasi
Method yang memanggil dirinya sendiri Berguna untuk teknik pemrograman
Lebih memudahkan pemecahan masalah
tertentu
Contoh:
Faktorial 0! = 1;
n! = n x (n – 1)!; n > 0
Memerlukan kondisi penghentian (stopping
condition atau base case)
Contoh deklarasi rekursif:
public static long factorial(int n) {
if(n==0) // stopping condition / base case
return 1;
else
return n * factorial(n-1); // recursive call
}
Pemanggilan factorial (diri sendiri) rekursif Dipanggil sampai mencapai kondisi n == 0
(stopping condition atau base case)
Penggunaan Rekursif
return 1 return 1 *
factorial(0) return 2 *
factorial(1) return 3 *
factorial(2) return 4 * factorial(3)
factorial(4)
Step 0: executes factorial(4)
Step 1: executes factorial(3)
Step 2: executes factorial(2)
Step 3: executes factorial(1)
Step 4: executes factorial(0)
Step 5: return 1
Step 6: return 1
Step 7: return 2
Step 8: return 6
Faktorial lebih baik menggunakan loop
int hasil = 1;
if(bil>1) {
for(int i=2; i<=bil; i++) hasil *= i;
}
Faktorial baik dalam merepresentasikan
rekursif
Penggunaan Rekursif
Fibonacci:
Dimulai dari 0 dan 1
Bilangan berikutnya penjumlahan dari 2
bilangan sebelumnya
fb(0) = 0
fb(1) = 1
fb(index) = fb(index – 2) x fb(index – 1);
index > =2
Inde
x
0 1 2 3 4 5 6 7 8 9 1
0
1
1
Seri 0 1 1 2 3 5 8 1
Palindrom: kata, frasa, bilangan, atau
kalimat yang dibaca sama dari 2 arah pembacaan
Contoh: ◦ Civic
◦ Level
◦ Rotator
◦ Was it a rat I saw
◦ 58285
◦ 20-02-2002
Method isPalindrome pertama mengecek
apakah string tersebut palindrom
Method isPalindrome kedua mengecek
apakah substring tersebut palindrom
Teknik mendeklarasikan method bantuan
untuk rekursif recursive helper method
Berguna untuk string dan array
Rekursif:
◦ Bentuk alternatif kontrol program
◦ Repetisi tanpa loop
◦ Memanggil methodnya sendiri
◦ Memerlukan pernyataan seleksi (if) untuk base case/stopping condition ◦ Memerlukan memori lebih banyak
◦ Waktu eksekusi lebih lambat
◦ Terkadang lebih jelas, sederhana dibandingkan iteratif
Iteratif:
◦ Merupakan struktur kontrol (fundamental dari bahasa pemrograman)
◦ Spesifkasi loop body
◦ Dikontrol oleh loop-control-structure
◦ Memori lebih sedikit dan waktu proses lebih cepat
Permasalahan yang dapat diselesaikan oleh
rekursif pasti bisa diselesaikan oleh iteratif
Infnite recursion (rekursif tak terhingga)
terjadi jika tidak ada stopping condition atau
base case
Contoh pada Faktorial
public static long factorial(int n) {
return n * factorial(n-1); // recursive call
}
Menyebabkan StackOverfowError Solusi
if(n==0) // stopping condition / base case
return 1;
Tower of Hanoi: contoh rekursif klasik
Mudah diselesaikan dengan rekursif
Terdapat 3 menara (tower) dan beberapa
cakram (disk) dengan ukuran berbeda
Disk atas harus lebih besar daripada disk
bawah
Semua disk berawal dari tower pertama
Hanya 1 disk yang boleh dipindahkan dalam
sekali waktu
Semua disk harus dipindahkan ke tower akhir
Fungsi Rekursif
(Berulang)
Defnisi
Recursive = Berulang Recursive function =
fungsi rekirsif =
fungsi yang berulang
di dalam fungsi
tersebut dia
Fungsi rekursif:
Di dalamnya terdapat pernyataan yang memanggil dirinya sendiri.
Berguna untuk memecahkan masalah yang dapat
didefnisikan secara rekursif pula.
n faktorial atau n! = n * n-1 * n-2 * …. * 3 * 2 * 1,
dan didefniskan bahwa 0! = 1
Contoh:
3! = 3 * 2 * 1
4! = 4 * 3 * 2 * 1 4! = 4 * 3!
n! = n * (n-1)!
25
Faktorial (n) atau n! didefnisikan sebagai berikut :
jika n = 0, n! = 1
jika n > 0, n! = n * (n-1)!
4! = 4 * 3! 3! = 3 * 2! 2! = 2 * 1! 1! = 1* 0! 0! = 1
4! = 4*3! = 4*3*2! = 4*3*2*1! = 4*3*2*1 = 24
// iteratif dekremental
long faktorialIteratifDec(long n) mulai
long i, faktorial = 1; for(i=n; i>=1; i--) faktorial *= i; return faktorial; selesai
tutup
4! = 1*2*3*4 = 24
// iteratif inkremental
long faktorialIteratifInc(long n){ mulai
long i, faktorial = 1; for(i=1; i<=n; i++) faktorial *= i; return faktorial; selesai
tutup
27
Contoh perhitungan 5 faktorial
28
5!
(5 * 4!)
(5 * (4 *3!))
(5 * (4 * (3 * 2!)))
(5 * (4 * (3 * (2 * 1!))))
(5 * (4 * (3 * (2 * (1 * 0!))))) (5 * (4 * (3 * (2 * (1 * 1))))) (5 * (4 * (3 * (2 * 1))))
(5 * (4 * (3 * 2))) (5 * (4 * 6 ))
(5 * 24) 120
Fungsi rekursif mempunyai dua komponen
yaitu:
◦ Base case:
Mengembalikan nilai tanpa melakukan pemanggilan rekursi berikutnya.
Rekursi berakhir jika base case dijumpai/dipenuhi
◦ Recursion call / Reduction step:
Memanggil fungsi rekursif di dalam fungsi rekursif di atas Menghubungkan sebuah fungsi rekursif dengan fungsi rekursif di dalamnya
Biasanya memiliki keyword return untuk
mengembalikan nilai ke fungsi yang memanggilnya
29
Fungsi faktorial ◦ Base case: n = 0
◦ Reduction step: f(n) = n * f(n-1)
// rekursif
long faktorialRekursif(long n) mulai
if(n==0)
return (1); else
return(n * faktorialRekursif(n-1)); selesai
tutup
30
Contoh:
31
• Faktorial - Rekursif
long faktorial(long n) mulai if(n==0) return (1); else return(n*faktorial(n-1)); selesai tutup
• Faktorial - Rekursif
long faktorial(long n) mulai if(n==0) return (1); else return(n*faktorial(n-1)); selesai tutup
• Faktorial - Iteratif // dekremental
long faktorial(long n) mulai
long i, faktorial = 1; for(i=n; i>=1; i--) faktorial *= i; return faktorial; selesai
tutup
• Faktorial - Iteratif
// dekremental
long faktorial(long n) mulai
long i, faktorial = 1; for(i=n; i>=1; i--) faktorial *= i; return faktorial; selesai
tutup
32
Rekursif
Pengulangan dengan struktur seleksi (if-else) dan
pemanggilan fungsi (dirinya sendiri) -> rekursi
Pengulangan berhenti saat base case dijumpai/dipenuhi
(konvergen terhadap base case)
Pengulangan tanpa henti jika
base case tidak pernah
dijumpai/dipenuhi (tidak konvergen terhadap base case)
Biaya proses lebih tinggi dengan pemanggilan banyak fungsi (butuh memori lebih besar & kerja prosesor lebih tinggi) Terbaca lebih jelas, model lebih
dekat dengan masalah
(contoh: faktorial, fbonacci)
Rekursif
Pengulangan dengan struktur seleksi (if-else) dan
pemanggilan fungsi (dirinya sendiri) -> rekursi
Pengulangan berhenti saat base case dijumpai/dipenuhi
(konvergen terhadap base case)
Pengulangan tanpa henti jika
base case tidak pernah
dijumpai/dipenuhi (tidak konvergen terhadap base case)
Biaya proses lebih tinggi dengan pemanggilan banyak fungsi (butuh memori lebih besar & kerja prosesor lebih tinggi) Terbaca lebih jelas, model lebih
dekat dengan masalah
(contoh: faktorial, fbonacci)
Iteratif
Pengulangan dengan struktur repetisi (for/while)
Pengulangan berhenti saat
kondisi pengulangan bernilai salah (false)
Pengulangan tanpa henti jika kondisi pengulangan selalu benar
Biaya proses lebih rendah
(kebutuhan memori lebih kecil & kerja prosesor lebih rendah) karena proses pengulangan berada dalam satu fungsi Terbaca kurang jelas, model
kurang dekat dengan masalah (contoh: faktorial, fbonacci)
Iteratif
Pengulangan dengan struktur repetisi (for/while)
Pengulangan berhenti saat
kondisi pengulangan bernilai salah (false)
Pengulangan tanpa henti jika kondisi pengulangan selalu benar
Biaya proses lebih rendah
(kebutuhan memori lebih kecil & kerja prosesor lebih rendah) karena proses pengulangan berada dalam satu fungsi Terbaca kurang jelas, model
kurang dekat dengan masalah (contoh: faktorial, fbonacci)
Meskipun penulisan program dengan cara
rekursif bisa lebih jelas dan pendek, namun fungsi rekursif memerlukan :
◦ Memori yang lebih banyak untuk mengaktifkan
stack (memori yang digunakan untuk
pemanggilan fungsi).
◦ Waktu lebih lama untuk menjejaki setiap rekursi melalui stack.
33
Apakah stack ?
Secara umum, hanya jika :
◦ Penyelesaian sulit dilaksanakan secara iteratif
◦ Efsiensi dengan cara rekursif masih memadai
◦ Efsiensi bukan masalah dibandingkan dengan kejelasan logika program
◦ Tidak mempertimbangkan faktor penghematan memori dan kecepatan eksekusi program
Kecepatan kerja dan penghematan memori (iteratif)
VS
Perancangan logika yang baik (rekursif)
34
Urutan bilangan 0, 1, 1, 2, 3, 5, 8, 13 …
disebut bilangan Fibonacci.
Hubungan antara satu angka dengan angka
berikutnya didefnisikan secara rekursif sebagai berikut :
◦ Fib(n) = n, jika n = 0 atau 1
◦ Fib(n) = Fib(n-2) x Fib(n-1) , jika n >= 2
35
Misalkan jika ditanya berapa suku ke-4 dari
barisan fbonachi?
n = 4
fbo(4) =
= fbo(3) x fbo(2)
= (fbo(2) x fbo(1)) x (fbo(1) x fbo(0))
= ((fbo(1) x fbo(0)) x 1) x (1 x 0)
= ((1 x 0) x 1) x 1
= (1 x 1) x 1
= 2 x 1
37 int Fib(int n)
mulai int f; if(n==0)
f = 0;
else if(n==1) f = 1;
else
f = Fib(n-2) + Fib(n-1); return f;
selesai tutup
int Fib(int n) mulai
int f; if(n==0)
f = 0;
else if(n==1) f = 1;
else
f = Fib(n-2) + Fib(n-1); return f;
selesai tutup
Fungsi fb() di atas ditulis secara rekursif dan disebut sebagai slow_Fib()
Tulislah fast_Fib() jika menggunakan iterasi.
Fungsi fb() di atas ditulis secara rekursif dan disebut sebagai slow_Fib()
Tulislah fast_Fib() jika menggunakan iterasi.
Contoh : Skema fbonacci jika N=4
38
FIB (4)
FIB (3) FIB (2)
FIB (2) FIB (1) FIB (1) FIB (0)
FIB (1) FIB (0)
Bilangan Fibonacci
+
+
+
Latihan
Implementasikan algoritma rekursi untuk
#include <iostream>
using namespace std;
long rekursifaktorial(int f)
{
if (f == 0)
return 1;
else
return f * rekursifaktorial(f - 1);
}
int main()
{
int x;
int n = 4;
cout << n << "! = "<< rekursifaktorial(n) << endl;
Recursif faktorial C++
n = 9;
cout << n << "! = “ << rekursifaktorial(n) << endl; cout<<"Masukan Angka yang akan difaktorialkan : "; cin>>x;
cout << x <<"! = " << rekursifaktorial(x) <<endl;
Introduction to Java Programming. 7ed. Liang. 2009. ch 20
Java Software Solutions. 5ed. Lewis & Loftus. 2007. ch 11
Fibonacci.
http://en.literateprograms.org/Fibonacci_numbers _(Java)
Palindrome.
http://en.wikipedia.org/wiki/Palindrome Towers of Hanoi.
◦ http://www.codeproject.com/KB/graphics/Towers_of_Hanoi/Towers_of_Ha noi.jpg
◦ http://www.codeproject.com/KB/graphics/Towers_of_Hanoi.aspx
◦ http://www.java2s.com/Tutorial/Java/0100__Class-Defnition/TheTowersof Hanoi.htm
◦ http://pirate.shu.edu/~wachsmut/Java/Hanoi/index.html
Ada kalanya kita mengalami kesulitan
untuk mendefnisikan suatu obyek secara
eksplisit
.
Mungkin lebih mudah untuk
mendefnisikan obyek tersebut dengan
menggunakan dirinya sendiri. Ini
dinamakan sebagai
proses rekursif
.
Kita dapat mendefnikan
barisan
,
fungsi
Contoh:
Barisan bilangan pangkat dari 2
an = 2n untuk n = 0, 1, 2, … .
Barisan ini dapat didefnisikan secara rekursif: a0 = 1
anx1 = 2an untuk n = 0, 1, 2, …
Langkah-langkah untuk mendefnisikan barisan secara rekursif:
1. Langkah basis: Spesifkasi anggota awal.
2. Langkah rekursif: Berikan aturan untuk membangun
anggota baru dari anggota yang telah ada.
Berikan defnisi rekursif dari an=rn, dengan rN, r≠0 dan n bilangan bulat positif.
Solusi:
Defnisikan a0=r0=1 dan anx1=r . a
n untuk n = 0, 1, 2, …
Contoh barisan yang
didefnisikan
Langkah-langkah untuk mendefnisikan
fungsi dengan domain
bilangan cacah
:
1.
Langkah basis
: Defnisikan nilai fungsi
pada saat nol.
2.
Langkah rekursif
: Berikan aturan untuk
mencari nilai fungsi untuk setiap bilangan
bulat berdasarkan nilai fungsi pada
bilangan bulat yang lebih kecil.
Defnisi seperti itu disebut
rekursif
atau
defnisi induktif
.
f(0) = 3
f(n x 1) = 2f(n) x 3 Maka
f(0) = 3
f(1) = 2f(0) x 3 = 23 x 3 = 9 f(2) = 2f(1) x 3 = 29 x 3 = 21 f(3) = 2f(2) x 3 = 221 x 3 = 45 f(4) = 2f(3) x 3 = 245 x 3 = 93
Contoh fungsi yang
didefnisikan
Bagaimana kita dapat mendefnisikan
fungsi faktorial f(n) = n! secara rekursif?
f(0) = 1
Karena (nx1)! = n! (nx1) maka
f(n x 1) = (n x 1)f(n)
f(0) = 1
f(1) = 1 f(0) = 1
1 = 1
f(2) = 2 f(1) = 2
1 = 2
f(3) = 3 f(2) = 3
2 = 6
f(4) = 4 f(3) = 4
6 = 24
Contoh fungsi yang
didefnisikan
Contoh fungsi yang
didefnisikan
secara rekursif (3)
f
0= 0, f
1= 1
f
n= f
n-1x f
n-2, n=2,3,4,…
Contoh terkenal: Bilangan
Fibonacci
f0= 0 f1= 1
f2= f1x f0= 1 x 0 = 1 f3= f2x f1= 1 x 1 = 2 f4= f3x f2= 2 x 1 = 3 f5= f4x f3= 3 x 2 = 5 f6= f5x f4= 5 x 3 = 8
Tunjukkan bahwa untuk n
3,
Langkah-langkah dalam mendefnisikan suatu himpunan secara rekursif:
1. Langkah basis:
Spesifkasi koleksi awal dari anggota
2. Langkah rekursif:
Mendefnisikan aturan konstruksi anggota baru dari anggota yang telah diketahui
Himpunan yang
Misalkan S didefnisikan secara rekursif oleh: 3 S
(xxy) S jika x S dan y S
Maka S adalah himpunan bilangan bulat positif yang habis dibagi 3.
Bukti:
Misalkan A himpunan yang beranggotakan semua bilangan bulat positif yang habis dibagi 3.
Untuk membuktikan bahwa A = S, harus ditunjukkan A S and S A.
Bagian I: Akan dibuktikan A S, yaitu menunjukkan bahwa setiap bilangan bulat positif yang habis dibagi 3 ada di S (dengan menggunakan induksi matematika).
Contoh himpunan yang
Misalkan P(n): proposisi “3n anggota S”.
1. Langkah basis: P(1) benar, karena 3 S. 2. Langkah induktif:
Asumsikan P(k) benar, yaitu 3k S.
Akan ditunjukkan P(kx1) juga benar, yaitu
3(kx1) S
Karena 3k S dan 3 S, berdasarkan
defnisi rekursif dari S, 3kx3 = 3(kx1) juga ada di S.
3. Konklusi:
Jadi, setiap bilangan bulat positif yang habis dibagi 3 ada di S.
Kesimpulan dari bagian I adalah A S.
Contoh himpunan yang
Bagian II: Akan ditunjukkan S A dengan menggunakan defnisi rekursif dari S.
Langkah basis:
Akan ditunjukkan setiap anggota awal S ada di A. Karena 3 habis dibagi 3 maka 3 A.
Langkah rekursif:
Akan ditunjukkan bahwa setiap bilangan bulat yang dibangun dengan mengunakan langkah rekursif juga merupakan
anggota A, yaitu
(xxy) A jika x,y S (yang diasumsikan A).
Jika x dan y keduanya di A, maka 3 | x dan 3 | y. Akibatnya, 3 | (x x y).
Kesimpulan dari bagian II adalah S A. Jadi, secara keseluruhan, berlaku A = S.
Contoh himpunan yang
Dalam membuktikan hasil-hasil yang berkaitan dengan himpunan yang didefnisikan secara rekursif, akan lebih mudah apabila digunakan suatu bentuk induksi matematika yang disebut
induksi struktural.
Langkah-langkah dalam induksi struktural:
1. Langkah basis:
Menunjukkan bahwa hasil yang akan dibuktikan berlaku untuk semua anggota awal.
2. Langkah rekursif:
Menunjukkan bahwa jika hasil yang akan
dibuktikan berlaku untuk anggota-anggota yang digunakan untuk membangun anggota baru,
maka hasil tersebut juga berlaku untuk anggota yang baru dibangun.
Himpunan string * atas alfabet dapat didefnisikan secara
rekursif oleh:
1. Langkah basis:
* ( adalah string kosong yang tidak memuat simbol)
2. Langkah rekursif:
Jika w * dan x , maka wx *
Himpunan string atas
alfabet
Contoh:
Jika = {0,1} maka string yang merupakan anggota *
adalah:
• yang didefinisikan sebagai anggota * dalam langkah basis,
• 0 dan 1 yang dibentuk dalam langkah rekursif pertama,
• 00, 01, 10, dan 11 yang dibentuk dalam langkah rekursif
kedua,
Konkatenasi
Sebagai operasi kombinasi dari dua string,
konkatenasi didefnisikan secara rekursif sebagai:
1. Langkah basis:
Jika w *, maka w. = w, dengan string
kosong
2. Langkah rekursif:
Jika w1 * dan w2 * dan x , maka
w1 . (w2 x) = (w1 . w2) x
Himpunan string atas alfabet
(2)
w1 . w2seringkali ditulis sebagaiw1 w2
Contoh:
Konkatenasi dari w1 = meng dan w2 = apa adalah
Panjang string
Panjang dari string
w
, l (
w
) dapat
didefnisikan secara rekursif oleh:
l () = 0,
l (w x) = l (w) x 1 jika w * dan x .
Himpunan string atas alfabet
(3)
Gunakan induksi struktural untuk
membuktikan bahwa
Induksi matematika dapat diperluas untuk
membuktikan hasil-hasil mengenai himpunan yang memiliki sifat terurut dengan baik.
Contoh: himpunan N x N
Contoh perluasan induksi
Misalkan didefnisikan secara rekursif untuk (m,n) N x N oleh
dan
Tunjukkan bahwa
untuk setiap
(m,n)
N x N.
n m
a
,0
0 , 0
a
0
jika
,
0
dan
0
jika
,
1
1 , , 1,
a
n
n
m
n
a
a
n m n m n m2
/
)
1
(
,
m
n
n
Proses yang memanggil dirinya sendiri. Merupakan suatu fungsi atau prosedur Terdapat suatu kondisi untuk berhenti.
Faktorial
Konsep Faktorial
n! = n(n-1)(n-2)…1
Dapat diselesaikan
dengan
Int Faktorial(int n) {
if (n<0) return -1 ; else if (n>1)
{
S = 1 ;
for(i=2 ;i<=n;ixx) S = S * n ; return S ;
}
else return 1 ; }
Int Faktorial(int n) {
if (n<0) return -1
else if (n>1) Return (n*Faktorial(n-1))
Else Return 1 ;
}
Leonardo Fibonacci berasal dari Italia
1170-1250
Deret Fibonacci f
1, f
2,… didefinisikan secara
rekursif sebagai berikut :
f
1= 1
f
2= 2
f
n= f
n-1+ f
n-2for n > 3
Deret: 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233,
377, 610, 987, 1597,…
procedure
fab
(n)
if n=1 then
return 1
if n=2 then
return 2
return (
fab
(n-1) x
fab
(n-2))
end
Jika pernyataan terakhir yang akan
dieksekusi berada dalam tubuh fungsi
Hasil yang kembali pada fungsi tsb
bukanlah bagian dari fungsi tersebut.
Tidak memiliki aktivitas selama fase balik.
Rekursif Tail : Faktorial()
F(4,1) = F(3,4) Fase awal F(3,4) = F(2,12)
F(2,12) = F(1,24)
F(1,24) = 24 Kondisi Terminal
Algoritma BinRec(n)
◦ //input : Bilangan desimal integer positif n
◦ //output : Jumlah digit biner yang dinyatakan dengan n
If (n=1) return 1
Else return BinRec( n/2 ) x 1