Pertemuan 10 Pemrograman Terstruktur REKURSI
Fungsi Rekursi Fungsi Rekursi adalah fungsi yang memanggil dirinya sendiri Rekursi dapat digunakan sebagai alternatif tif dari iterasi/perulangan (looping)
Algoritma Rekursi Algoritma rekursif secara umum dapat dituliskan terdiri dari if statement sebagai berikut: if this is a simple case solve it else redefine the problem using recursion (recursive step)
Simple case & recursive step Simple case (base case) adalah kondisi untuk menghentikan rekursi Recursive step adalah kondisi i untuk melakukan k rekursi
Contoh1: Rekursi untuk Perkalian 2 Bilangan 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);
Contoh2: Menghitung jumlah Karakter dalam suatu String int count (char ch, const char *str) 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 */ ans = count(ch, &str[1]); return (ans);
Penelusuran (tracing) pada Fungsi Rekursi
Penelusuran fungsi rekusi yang mengembalikan suatu nilai Fungsi Rekursi untuk Perkalian 2 buah bilangan int multiply(int l t m, int n) int ans; if (n == 1) ans = m; /* simple case */ else ans = m + multiply (m, n - 1); /* recursive step */ 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 menggunakan sebuah array. dalam stack kita bisa menambah data dengan perintah operasi push dan menghapus data dengan menggunakan perintah operasi pop
Fungsi Rekursi pada Matematika Banyak fungsi matematika yang dapat didefinisikan dengan rekursi. Contoh: fungsi faktorial dari n (n!), dapat didefinisikan secara iteratif : 0! Adalah 1 n! Adalah n x (n-1)!, untuk n>0 Misal: 4! Adalah 4 x 3!, yang artinya 4 x 3 x 2 x 1, atau 24
Fungsi rekursi untuk faktorial Program : //menghitung n! Menggunakan definisi rekursi //pre : n>=0 Int factorial (int n) int ans; if (n == 0) ans = 1; /*simple case*/ else ans = n * factorial (n-1); return(ans); /*recursive step*/
Penulusuran dari fact= factorial(3); Fact=factorial(3); 6 n = 3 ans=3 * factorial (2) return(ans) 2 n = 2 ans=2 * factorial (1) return(ans) 1 n = 1 ans=1 * factorial (0) return(ans) 1 n = 0 ans=1 return(ans)
Program : //menghitung n! Menggunakan iteratif //pre : n>=0 Int factorial (int n) int i; /*variabel lokal */ Product =1; Iteratif untuk faktorial //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 Persamaan Sama-sama merupakan bentuk perulangan Dilakukan pengecekan kondisi terlebih dahulu sebelum mengulang Perbedaan Pada rekursi, dikenal adanya istilah recursive step Sedangkan pada iteratif ada decrement
Kelebihan dan kelemahan rekursi : Kelebihan solusi sangatlah efisien dapat memecahkan masalah yang sulit dengan tahapan yang mudah dan singkat Kelemahan sulit dipahami perlu stack besar (stack overrun)
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
Fungsi Rekursi dengan Parameter Array dan String Study Kasus: Menemukan Huruf Kapital dalam string Analisa input : String (str) 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])); else find_ caps(caps, p( p, &str[1]); []); 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 kapital dalam caps dan sisanya dalam str kembali. 3. Jika huruf pertama kapital, simpan sisanya dalam str.
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'; \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 find_caps(caps, &str[1]); return (caps);
Penelusuran pemanggilan untuk Fungsi Rekursi Menemukan Huruf Kapital printf(...find_caps(caps, JoJo )); JJ str is JoJo J is uppercase sprintf(caps, %c%s, J, find_caps(restcaps, ojo )); return(caps) J str is ojo o is not uppercase find_caps(caps, Jo )); return(caps) J str is Jo J is uppercase sprintf(caps, %c%s, J, find_caps(restcaps, o )); return(caps) str is o o is not uppercase find_caps(caps, )); return(caps) str is caps is 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. A B C Problem Memindahkan n balok dari menara A ke menara C menggunakan menara B bila 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 balokbalok dari menara awal ke menara yang dituju 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 Daftar perpindahan balok
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 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 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 jum=pow(2,n)-1; 7. Menampilkan banyaknya perpindahan printf("\n>>jumlah perpindahannya adalah : %d", jum);
Implementasi Menara Hanoi #include<stdio.h> #include<math.h> #include<conio.h> int n; char awal='a'; char akhir='c'; 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); menara(awal,mid,akhir,n-1);
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 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); char *get_set (char *set); int main(void) char ele, set_one[setsize], set_two[setsize], t set_three[setsize]; th 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>"); get_set (set_one);
putchar ('\n'); print_set (set_one); if (is_set(set_one)) printf ("is a valid set\n"); else printf ("is invalid\n"); printf ("Enter a single character, a space, and a set>"); while (isspace (ele = getchar())) get _ set (set _ one); printf ("\n%c", ele); if (is_element(ele, set_one)) printf ("is an element of"); else 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, three set_one, set_two)); 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) ans = TRUE; else ans = is_element (ele, &set[1]); return (ans);
int is_set set (const char *set) int ans; if (is_empty(set)) ans = TRUE; 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);
char *set_union (char *result, const char *set1, const char *set2) char temp [SETSIZE]; if (is_empty(set1)) strcpy (result, set2); 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); putchar(''); char *get_set (char *set) char inset [SETSIZE]; scanf ("%s", inset); strncpy (set, &inset[1], strlen (inset)-2); set [strlen (inset) - 2] ='\0'; \0; return (set);
Referensi Bab 10, Recursion, Problem Solving and Program Design in C, Jeri R. Hanly dan Elliot B. Koffman, Addison Wesley, 2002