320 likes | 434 Views
5.13 遞迴. 遞迴函數 函數會呼叫他自己 只會解決最基本的情況 將問題分解成兩個區塊 知道怎麼做 不知道怎麼做 呼叫自己來解決已變小的問題 ( 遞迴步驟 ). 5.13 遞迴. Example: n 階乘 : 5! = 5 * 4 * 3 * 2 * 1 注意: 5! = 5 * 4! 4! = 4 * 3! ... 可以以遞迴的方式計算階乘 可以解決基本情況 (1! = 0! = 1) 則 2! = 2 * 1! = 2 * 1 = 2; 3! = 3 * 2! = 3 * 2 = 6;.
E N D
5.13 遞迴 • 遞迴函數 • 函數會呼叫他自己 • 只會解決最基本的情況 • 將問題分解成兩個區塊 • 知道怎麼做 • 不知道怎麼做 • 呼叫自己來解決已變小的問題 (遞迴步驟)
5.13 遞迴 • Example: n 階乘: • 5! = 5 * 4 * 3 * 2 * 1 • 注意: • 5! = 5 * 4! • 4! = 4 * 3! ... • 可以以遞迴的方式計算階乘 • 可以解決基本情況 (1! = 0! = 1) 則 • 2! = 2 * 1! = 2 * 1 = 2; • 3! = 3 * 2! = 3 * 2 = 6;
long 是指 long int的意思:即是用在會很大的整數變數 #include <stdio.h> long factorial( long ); int main(){ int i; for ( i = 1; i <= 10; i++ ) printf( "%2d! = %ld\n", i, factorial( i ) ); return 0; } long factorial( long number ){ if ( number <= 1 ) return 1; else return ( number * factorial( number - 1 ) ); } 1! = 1 2! = 2 3! = 6 4! = 24 5! = 120 6! = 720 7! = 5040 8! = 40320 9! = 362880 10! = 3628800
5.14 使用遞迴的實例: Fibonacci 級數 • Fibonacci 級數: 0 , 1 , 1 , 2 , 3 , 5 , 8 … • 每個數字都是前兩個數字的和 • fib(n) = fib(n-1) + fib(n-2):遞迴的公式 • long fib(long n) • { • if (n==0 || n==1) //基本情況 • return n; • else • return fib(n-1) + fib(n-2); • }
5.14 使用遞迴的實例: Fibonacci 級數 fib(3) return + fib(2) fib(1) return + fib(1) fib(0) return 1 return 1 return 0 fib(3)=1+0+1=2
完整的 Fibonacci 級數程式 #include <stdio.h> long fibonacci( long n ); int main() { long result; long number; printf( "Enter an integer: " ); scanf( "%ld", &number ); result = fibonacci( number ); printf( "Fibonacci( %ld ) = %ld\n", number, result ); return 0; } long fibonacci( long n ) { if ( n == 0 || n == 1 ) return n; else return fibonacci( n - 1 ) + fibonacci( n - 2 ); }
Enter an integer: 2 Fibonacci(2) = 1 Enter an integer: 3 Fibonacci(3) = 2 Enter an integer: 4 Fibonacci(4) = 3 Enter an integer: 5 Fibonacci(5) = 5 Enter an integer: 6 Fibonacci(6) = 8 Enter an integer: 10 Fibonacci(10) = 55 Enter an integer: 20 Fibonacci(20) = 6765 Enter an integer: 30 Fibonacci(30) = 832040 Enter an integer: 35 Fibonacci(35) = 9227465
5.15 遞迴 vs. 迭代 • 重複性 • 迭代:明確地使用迴圈 • 遞迴:重複呼叫函式 • 何時終止? • 迭代:迴圈繼續條件失敗 • 遞迴:收斂到基本情況 • 兩者都可能出現無窮迴圈 • 均衡一下 • 選擇效能 (迭代所需的執行時間與記憶體比較小)與 軟體工程(遞迴使程式較容易被瞭解,有時也使問題比較簡化)
利用函式寫一個程式:要求輸入邊長s,隨即在螢幕左邊印出一s x s的正方形『*』,如:s = 4 **** **** **** ****
#include <stdio.h> void square( int s ); int main() { int side; printf("輸入長度: " ); scanf( "%d", &side ); square( side ); return 0; } void square( int s ) { int i, j; for ( i = 1; i <= s; i++ ) { for ( j = 1; j <= s; j++ ) printf( "*" ); printf( "\n" ); } }
將前一個函式改為顯示字元可輸入 #include <stdio.h> void square( int side, char fillCharacter ); int main() { int s; char c; printf("輸入一個字元與長度: " ); scanf( "%c%d", &c, &s ); square( s, c ); return 0; }
void square( int side, char fillCharacter ) { int loop; int loop2; for ( loop = 1; loop <= side; loop++ ) { for ( loop2 = 1; loop2 <= side; loop2++ ) printf( "%c", fillCharacter ); printf( "\n" ); } }
章節大綱 6.1 簡介 6.2 陣列 6.3 定義陣列 6.4 使用陣列的例子 6.5 傳遞陣列給函式 6.6 陣列的排序 6.7 範例研究:使用陣列算平均數、中位數及眾數 6.8 搜尋陣列 6.9 多維陣列
6.2 陣列 陣列名稱 • 陣列 • 一群接連在一區的記憶空間位置 • 具有相同的名稱與型別 • 必須指定特定的名稱 • 陣列的名稱 • 以及位置編號 • 通式: 陣列名稱 [ 位置編號] • 第一個元素編號為 0 • 例如:C 陣列有n個元素如下: • c[ 0 ], c[ 1 ]...c[ n – 1 ] 位置編號
6.2 陣列 • 陣列的元素就像一般變數一樣 c[ 0 ] = 3; printf( "%d", c[ 0 ] ); • 另外,運算可以在位置編號中進行; 例如:若x = 3 c[ 5 - 2 ] == c[ 3 ] == c[ x ]
定義陣列 • 一開始要先定義宣告陣列(如一般變數) • 名稱 • 型別 • 元素個數 型別 陣列名稱[ 元素個數 ]; • 例如: int c[ 10 ]; float myArray[ 3284 ]; • 也可以將相同型別的陣列一同定義宣告 • 例如: int b[ 100 ], x[ 27 ];
#include <stdio.h> int main() { int n[ 10 ], i; for ( i = 0; i <= 9; i++ ) n[ i ] = 0; printf("%s%13s\n ", “Element", “Value" ); for ( i = 0; i <= 9; i++ ) printf( "%7d%13d\n", i, n[ i ] ); return 0; } Element Value 0 0 1 0 2 0 3 0 4 0 5 0 6 0 7 0 8 0 9 0
初始化串列 • 初始化串列 int n[ 5 ] = { 1, 2, 3, 4, 5 }; • 如果初始值個數少於陣列的元素個數則皆補 0, • 例如:int n[ 5 ] = { 0 } 則表示所有元素皆為 0 • 如果初始值過多會產生語法上的錯誤 • 如果在一個有初始化串列的定義上省略元素個數, 則元素個數將等於初始化串列上的元素個數, 例如: int n[ ] = { 1, 2, 3, 4, 5 }; 則此陣列的元素個數等於 5
#include <stdio.h> int main() { int n[ 10 ] = { 32, 27, 64, 18, 95, 14, 90, 70, 60, 37 }; int i; printf( "%s%13s\n", "Element", "Value" ); for ( i = 0; i <= 9; i++ ) printf( "%7d%13d\n", i, n[ i ] ); return 0; } Element Value 0 32 1 27 2 64 3 18 4 95 5 14 6 90 7 70 8 60 9 37
# define SIZE 10:前置處理器會在程式編譯之前將所有出現SIZE的地方代換為10 #include <stdio.h> #define SIZE 10 int main() { int s[ SIZE ], j; for ( j = 0; j <= SIZE - 1; j++ ) s[ j ] = 2 + 2 * j; printf( "%s%13s\n", "Element", "Value" ); for ( j = 0; j < SIZE; j++ ) printf( "%7d%13d\n", j, s[ j ] ); return 0; } Element Value 0 2 1 4 2 6 3 8 4 10 5 12 6 14 7 16 8 18 9 20
Total of array element values is 383 #include <stdio.h> #define SIZE 12 int main() { int a[ SIZE ] = { 1, 3, 5, 4, 7, 2, 99,16, 45, 67, 89, 45 }; int i, total = 0; for ( i = 0; i <= SIZE - 1; i++ ) total += a[ i ]; printf( "Total of array element values is %d\n", total ); return 0; }
來看看這個程式多了什麼? #include <stdio.h> #define SIZE 10 int main() { int n[ SIZE ] = { 19, 3, 15, 7, 11, 9, 13, 5, 17, 1 }; int i, j; printf( "%s%13s%17s\n", "Element", "Value","Histogram" ); for ( i = 0; i <= SIZE - 1; i++ ) { printf( "%7d%13d ", i, n[ i ]) ; for ( j = 1; j <= n[ i ]; j++ ) printf( "%c", '*' ); printf( "\n" ); } return 0; }
Element Value Histogram 0 19 ******************* 1 3 *** 2 15 *************** 3 7 ******* 4 11 *********** 5 9 ********* 6 13 ************* 7 5 ***** 8 17 ***************** 9 1 *
#include <stdio.h> #include <stdlib.h> #include <time.h> int main(){ int face, roll, frequency1 = 0, frequency2 = 0; int frequency3 = 0, frequency4 = 0; int frequency5 = 0, frequency6 = 0; srand(time(NULL)); for ( roll = 1; roll <= 6000; roll++ ) { face = 1 + rand() % 6; switch ( face ) { case 1: ++frequency1; break; case 2: ++frequency2; break; 這是之前算擲6000次骰子的程式,還記得嗎?
case 3: ++frequency3; break; case 4: ++frequency4; break; case 5: ++frequency5; break; case 6: ++frequency6; break;} } printf( "%s%13s\n", "Face", "Frequency" ); printf( " 1%13d\n", frequency1 ); printf( " 2%13d\n", frequency2 ); printf( " 3%13d\n", frequency3 ); printf( " 4%13d\n", frequency4 ); printf( " 5%13d\n", frequency5 ); printf( " 6%13d\n", frequency6 ); return 0; }
算擲6000次骰子的程式,利用陣列可以改成這樣算擲6000次骰子的程式,利用陣列可以改成這樣 #include <stdio.h> #include <stdlib.h> #include <time.h> #define SIZE 7 int main() { int face, roll, frequency[ SIZE ] = { 0}; srand( time( NULL ) ); for ( roll = 1; roll <= 6000; roll++ ) { face = rand() % 6 + 1; ++frequency[ face]; } printf( "%s%17s\n", "Face", "Frequency" ); for ( face = 1; face <= SIZE - 1; face++ ) printf( "%4d%17d\n", face, frequency[ face ] ); return 0; } 當face=2時,程式 就將陣列[2]加1
Face Frequency • 1 1029 • 2 951 • 3 987 • 4 1033 • 5 1010 • 6 990
字元陣列 • 單字 “first” 實際上可以視為一個字元陣列 • 字元陣列可以使用字串常數來指定初始值,例如: char string1[] = "first"; • 空字元 ‘\0’ 所有的字串都用它來終止 • 所以string1 實際上有六個元素 • 它等於: char string1[] = { 'f', 'i', 'r', 's', 't', '\0' }; • 可以直接存取字串中的個別字元,如: string1[ 3 ] 是字元 ‘s’ • 在scanf中,輸入陣列名稱不需要再加上『&』,如: scanf( "%s", string2 ); • scanf會讀取到出現第一個空格為止 • 讀入的字元數如果多過陣列元素數也會出現錯誤
#include <stdio.h> int main() { char string1[ 20], string2[ ] = "string literal"; int i; printf(" Enter a string: "); scanf( "%s", string1 ); printf( "string1 is: %s\nstring2: is %s\n" "string1 with spaces between characters is:\n", string1, string2 ); for ( i = 0; string1[ i ]!= '\0'; i++ ) printf( "%c ", string1[ i ] ); printf( "\n" ); return 0; }
Enter a string: Hello Kitty string1 is: Hello string2 is:string literal string1 with spaces between characters is: H e l l o
5/4 上機課 1. 請試著寫一個函式來判斷某數是否為質數 #include <stdio.h> int prime(int a); int main() { int x; printf("請輸入一整數:\n"); scanf("%d",&x); printf("\n"); return 0; } 主程式已在左邊請加入 prime函式在下面 If/else敘述式 印出(Yes or No)質數 2. 如果以做出上題,請印出1~10000所有的質數 prime函式