Pertemuan 10
Pemrograman Terstruktur
Pemrograman Terstruktur
Fungsi Rekursi
Fungsi Rekursi adalah fungsi yang memanggil dirinya
sendiri
R k
i d
t di
k
b
i lt
tif d i
Rekursi dapat digunakan sebagai alternatif dari
Algoritma Rekursi
Algoritma rekursif secara umum dapat dituliskan terdiri
dari
if
statement sebagai berikut:
if this is a
simple case
p
solve it
else
redefine the problem using recursion
redefine the problem using recursion
(
recursive step
)
Simple case & recursive step
Simple case (base case)
adalah kondisi untuk
menghentikan rekursi
R
i
t
d l h k
di i
t k
l k k
k
i
Contoh1: Rekursi untuk Perkalian 2
Bilangan
Bilangan
int multiply(int m, int n)
{
{
int ans;
if (n
==
1)
/*
i
l
*/
ans = m;
/* simple case */
else
ans = m + multiply (m, n - 1);
/* recursive step */
return (ans);
(
)
}
Contoh2: Menghitung jumlah Karakter
dalam suatu String
g
int count (char ch, const char *str)
{
int ans;
int ans;
if (str[0] == ‘\0’)
/* simple case */
ans = 0;
else
/* redefine problem using recursion */
if (ch == str[0])
/* first character must be counted */
ans = 1 + count (ch, &str[1]);
else
/* first character is not counted */
else
/ first character is not counted /
ans = count(ch, &str[1]);
return (ans);
Penelusuran (tracing) pada Fungsi
Rekursi
Penelusuran fungsi rekusi yang
mengembalikan suatu nilai
mengembalikan suatu nilai
Fungsi Rekursi untuk Perkalian 2
buah bilangan
i t lti l (i t i t ) int multiply(int m, int n) {
int ans; if (n == 1)
ans = m; /* simple case */
else ans = m + multiply (m, n - 1); /* recursive step */ return (ans); return (ans); }
Penelusuran fungsi void yang
rekursi
parameter and local Variable Stacks
stack adalah Struktur data dimana data yang terkhir
masuk adalah data yang akan diproses terlebih dahulu.
Stack biasanya dimplementasikan dengan
Stack biasanya dimplementasikan dengan
menggunakan sebuah array.
dalam stack kita bisa menambah data dengan perintah
operasi push
operasi push
dan menghapus data dengan menggunakan perintah
Fungsi Rekursi pada Matematika
Banyak fungsi matematika yang dapat didefinisikan dengan
rekursi.
Contoh: fungsi faktorial dari n (n!), dapat didefinisikan
g
( ),
p
secara iteratif :
0! Adalah 1
n! Adalah n x (n-1)!, untuk n>0
Fungsi rekursi untuk faktorial
Program :
//menghitung n! Menggunakan definisi rekursi
//pre : n>=0
Int factorial (int n)
{
int ans;
int ans;
if (n == 0)
ans = 1;
/*simple case*/
else
else
ans = n * factorial (n-1);
/*recursive step*/
return(ans);
}}
Penulusuran dari fact=
factorial(3);
factorial(3);
Fact=factorial(3);
return(ans) n = 3 ans=3 * factorial (2)6
return(ans) n = 2 ans=2 * factorial (1)2
return(ans) ( ) n = 1 ans 1 * factorial (0)1
n = 0 return(ans) ans=1 * factorial (0)1
return(ans) n 0 ans=1Iteratif untuk faktorial
Program :
//menghitung n! Menggunakan iteratif
//pre : n>=0
Int factorial (int n)
{
int i; /*variabel lokal */
Product =1;
//menghitung perkalian n x (n-1) x (n-2) x ... X 2 x 1
For (i=n; i>1; --i) { Product=product * i; }}
//Mengembalikan kembalian fungsi Return(product);
Persamaan dan perbedaan iteratif
& rekursi adalah
& rekursi adalah
Persamaan
Perbedaan
Persamaan
Sama-sama
merupakan bentuk
Perbedaan
Pada rekursi, dikenal
adanya istilah
perulangan
Dilakukan
pengecekan kondisi
recursive step
Sedangkan pada
iteratif ada
decrement
pengecekan kondisi
terlebih dahulu
sebelum mengulang
Kelebihan dan kelemahan rekursi :
Kelemahan
Kelebihan
solusi sangatlah
Kelemahan
sulit dipahami
perlu stack besar
efisien
dapat memecahkan
masalah yang sulit
p
(stack overrun)
masalah yang sulit
dengan tahapan
yang mudah dan
i
k t
10.4 Fungsi Rekursi dengan Parameter
Array dan String
10.5 Pemecahan Masalah dengan Rekursi
10.6 Studi Kasus Klasik dengan Rekursi:
Tower of Hanoi
Tower of Hanoi
Fungsi Rekursi dengan Parameter Array dan
String
g
Study Kasus: Menemukan Huruf Kapital dalam string
Analisa
input : String (str)
H
f k
i l (
)
output : Huruf kapital (caps)
penyelesaian:
if (str[0] == '\0') caps[0] = '\0'; else{ if (isupper(str[0])) sprintf(caps, "%c%s", str[0],find_caps(restcaps, &str[1])); elsefind caps(caps, &str[1]);}_ p ( p , [ ]);} return (caps);
Desain
1.
Jika string kosong, maka string kosong tersebut akan disimpan
dalam caps.
2.
Jika huruf pertama dari string adalah huruf kapital, simpan huruf
g
kapital dalam
caps
dan sisanya dalam
str
kembali.
Implementasi
Implementasi
#include<stdio.h> #include<ctype.h> #define STRSIZ 50
char *find_caps(char *caps, //output-string of all caps found in str
const char*str); //input-string of from which to caps extract caps void main()
{{
char caps[STRSIZ];
printf("Capital letters in JoJo are %s\n",find_caps(caps, "JoJo")); }
char *find_caps(char *caps, const char*str) {
char restcaps[STRSIZ]; //caps from reststr if (str[0] == '\0')
caps[0] = '\0'; //no lettrers in str => no caps in str caps[0] \0 ; //no lettrers in str > no caps in str else{
if (isupper(str[0]))
sprintf(caps, "%c%s", str[0],find_caps(restcaps, &str[1])); else
fi d ( & t [1]) } find_caps(caps, &str[1]);} return (caps);
Penelusuran pemanggilan untuk Fungsi Rekursi Menemukan Huruf
Penelusuran pemanggilan untuk Fungsi Rekursi Menemukan Huruf
Kapital
printf(...find_caps(caps, “JoJo”)); str is “JoJo” ‘J’ is uppercase sprintf(caps, “%c%s”,’J’, find_caps(restcaps, “oJo”)); return(caps) str is “oJo” “JJ” str is oJo ‘o’ is not uppercase find_caps(caps, “Jo”)); return(caps) str is “Jo” ‘J’ is uppercase sprintf(caps “%c%s” ’J’ “J” “J” str is “o” ‘o’ is not uppercase find_caps(caps, “ ”)); return(caps) sprintf(caps, %c%s , J , find_caps(restcaps, “o”)); return(caps) “ “ return(caps) str is “ ” caps is “ ” return(caps) “ “ return(caps)10.5 Pemecahan Masalah dengan Rekursi
Karena di dalam C tidak ada representasi dari himpunan struktur
data, kita akan mengimplementasikan operasi pada himpunan
dengan string sebagai himpunan.
Study Kasus: Operasi pada Himpunan
Studi Kasus Klasik dengan Rekursi
: Menara Hanoi
Menara Hanoi
adalah problem di mana kita harus memindahkan
balok yang mempunyai perbedaan ukuran dari suatu menara
(tower) ke menara lainnya.
•
Problem
A
B
C
Problem
•
Memindahkan n balok dari
menara A ke menara C
menggunakan menara B bila
dibutuhkan
A
B
C
dibutuhkan.
•
Hal yang harus dicermati :
–
Hanya satu buah balok saja
yang dapat dipindahkan
dalam satu waktu
–
Balok yang lebih besar tidak
boleh diletakkan di atas balok
yang lebih kecil
Analisis
Solusi dari menara hanoi terdiri dari daftar pemindahan
balok secara individual.
Kita membutuhkan fungsi rekursi yang dapat digunakan
untuk mencetak instruksi untuk memindahkan
balok-balok dari menara awal ke menara yang dituju
k
k ti
b
i
t
menggunakan menara ketiga sebagai perantara.
Data yang dibutuhkan :
Problem inputs
int n
/* jumlah balok yang dipindahkan */
Char awal
/* menara awal */
Char akhir
/* menara akhir atau menara yang dituju */
Ch
id /*
b
i
t
*/
Char mid /* menara sebagai perantara */
Problem Outputs
Desain
Algorithma
1. Jika n adalah 1 maka
2. Pindahkan balok satu dari menara awal ke menara akhir
if (n==1)
printf("pindahkan balok ke-%d dari %c ke %c\n",n,awal,akhir);
else / jika tidak
3 Pindahkan n 1 disks dari menara awal ke menara perantara
3. Pindahkan n-1 disks dari menara awal ke menara perantara
dengan menggunakan menara akhir
4. Pindahkan balok n dari menara awal ke menara akhir
5. Pindahkan n-1 balok dari menara perantara ke menara akhir
p
menggunakan menara awal.
masuk rekursi
else {
menara(awal,mid,akhir,n-1);( )
printf("pindahkan balok ke-%d dari %c ke %c\n",n,awal,akhir);
menara(awal,mid,akhir,n-1); }
6 Menghitung banyaknya perpindahan yang dibutuhkan
6. Menghitung banyaknya perpindahan yang dibutuhkan
jum=pow(2,n)-1;
7. Menampilkan banyaknya perpindahan
Implementasi Menara Hanoi
#include<stdio.h>
#include<math.h>
#include<conio h>
#include<conio.h>
int n;
char awal='A';
char akhir='C';
h
id 'B'
char mid='B';
void menara(char awal,char akhir,char mid,int n)
{
if (n==1)
(
)
printf("pindahkan balok ke-%d dari %c ke
%c\n",n,awal,akhir);
else
{
menara(awal,mid,akhir,n-1);
printf("pindahkan balok ke-%d dari %c ke
%c\n",n,awal,akhir);
%c\n ,n,awal,akhir);
menara(awal,mid,akhir,n-1);
}
void main() void main() {
int jum;
printf ("Masukkan banyak balok n : "); scanf ("%d",&n);
menara(awal,akhir,mid,n); jum=pow(2,n)-1;
printf("\n>>jumlah perpindahannya adalah : %d", jum); printf("\n\n\n");
#include <stdio.h> #include <string.h> #include <ctype.h> #define SETSIZE 65 #define TRUE 1 #define TRUE 1 #define FALSE 0
int is_empty (const char *set);
int is_element (char ele, const char *set); int is_set (const char *set);
int is_subset (const char *sub,const char *set);
char *set_union (char *result, const char *set1, const char *set2); void print_with_commas (const char *str);
void print set (const char *set); void print_set (const char set); char *get_set (char *set);
int main(void) {
h l t [SETSIZE] t t [SETSIZE] t th [SETSIZE] char ele, set_one[SETSIZE], set_two[SETSIZE], set_three[SETSIZE]; printf ("A set is entered as a string of up to %d letters\n", SETSIZE-3); printf ("and digits enclosed in {}");
printf ("for example, {a, b, c} is entered as {abc}\n"); printf ("enter a set to test validation function>");
p ( );
putchar ('\n');
print_set (set_one); if (is_set(set_one))
printf ("is a valid set\n"); l
else
printf ("is invalid\n");
printf ("Enter a single character, a space, and a set>"); while (isspace (ele = getchar()))
get set (set one); g _ ( _ ); printf ("\n%c", ele);
if (is_element(ele, set_one))
printf ("is an element of"); else
printf ("is not an element of"); printf ("is not an element of");
printf ("\nEntered two sets to test set_union>"); get_set (set_one);
get_set (set_two);
printf ("\nThe union of"); print_set (set_one); printf (" and "); print_set (set_two); printf ("is");
print set (set union(set three set one set two)); print_set (set_union(set_three, set_one, set_two)); putchar ('\n');
return (0); }
int is_empty (const char *set) {{
return (set [0] == '\0'); }
int is element(char ele, const char *set)_ ( , ) {
int ans;
if (is_empty(set))
ans = FALSE; else if (set [0] == ele) else if (set [0] == ele)
ans = TRUE; else
ans = is_element (ele, &set[1]); return (ans);
int is set (const char *set) int is_set (const char set)
{
int ans;
if (is_empty(set))
ans = TRUE;
l if (i l t ( t [0] & t [1])) else if (is_element (set [0], &set [1]))
ans = FALSE; else
ans = is_set (&set[1]); return (ans);
}
int is_subset (const char *sub, const char *set) {{
int ans;
if (is_empty(sub))
ans = TRUE;
else if (!is_element (sub [0], set)) ans = FALSE;
else
ans = is_subset (&sub[1], set); return (ans);
return (ans); }
char *set union (char *result const char *set1 const char *set2) char set_union (char result, const char set1, const char set2)
{
char temp [SETSIZE]; if (is_empty(set1))
strcpy (result, set2); l if (i l t ( t1 [0] t2)) else if (is_element (set1 [0], set2))
set_union (result, &set1 [1], set2); else
sprintf (result, "%c%s", set1 [0], set_union (temp, &set1 [1], set2)); return (result);
}
void print_with_commas (const char *str) {{ if (strlen (str)== 1) { putchar (str [0]); } else { printf ("%c, ", str [0]); print_with_commas (&str[1]); }} }
void print_set (const char *set) {
putchar ('{');
if (!is_empty(set))
print with commas(set); print_with_commas(set); putchar('}');
}
char *get_set (char *set) {
char inset [SETSIZE]; scanf ("%s", inset);
strncpy (set, &inset[1], strlen (inset)-2); set [strlen (inset) - 2] = '\0';
set [strlen (inset) 2] \0 ; return (set);