10-17 c遞迴與遞推初識

GJ504b發表於2024-10-18

遞迴與遞推學習

程式碼記錄


/*遞推【優於遞迴,減少重複工作】*/
//一·斐波拉契數列  A(n)=A(n-1)+A(n-2),輸入整數第n月,輸出每月兔子【1 1 2 3 5 8....】
//使用陣列儲存每一次結果,而不是函式自己執行自己
//#include<stdio.h>
//int main(){
//	int a[10] = {0};//宣告陣列,60比50稍微大一點,避免陣列越界
//	int n;
//	scanf("%d",&n);
//	a[1] = 1;
//	a[2] = 1;
//	for(int i=3;i<=n;i++){//之前忘記改資料了,i = 3,如果i = 0,編譯器將會產生不可知的行為
/*在程式設計中,每個程式都有自己的記憶體空間,這個空間被分為幾個部分,比如棧(stack)、堆(heap)和靜態儲存區(static storage)。當你宣告一個變數時,編譯器會為這個變數分配一塊記憶體,這塊記憶體是屬於你的程式的。

但是,如果你嘗試訪問一塊不屬於你的程式的記憶體,那麼就會發生“記憶體越界”或者“記憶體訪問錯誤”。這通常發生在以下幾種情況:

陣列越界:比如你有一個大小為10的陣列,但是你嘗試訪問陣列的第11個元素(比如array[10]),那麼你就會訪問到不屬於你的記憶體。
指標錯誤:如果你有一個指標,你沒有正確地初始化它,然後你嘗試透過這個指標訪問記憶體,那麼你可能會訪問到不屬於你的記憶體。
動態記憶體分配錯誤:如果你使用了動態記憶體分配(比如在C語言中使用malloc或new),但是你沒有正確地管理這些記憶體,比如忘記釋放或者釋放了之後還嘗試訪問,那麼你可能會訪問到不屬於你的記憶體。
當你訪問到不屬於你的記憶體時,可能會導致以下幾種結果:

程式崩潰:這是最常見的,因為作業系統會檢測到你的程式正在嘗試訪問不屬於它的記憶體,然後會終止你的程式。
資料損壞:如果你的程式修改了不屬於它的記憶體,那麼可能會導致其他程式或者作業系統的資料被破壞。
未定義行為:C語言標準將訪問不屬於你的記憶體定義為“未定義行為”,這意味著編譯器可以做任何它想做的事情,比如什麼也不做,或者讓你的程式崩潰,或者讓你的程式執行得很好,但是輸出錯誤的結果。*/		
//	a[i] = a[i-1] + a[i-2];
//		
//	}
//	for(int i=1;i<=n;i++){
//		printf("%d\n",a[i]);
//	}
//	return 0;
//}
//二·小方塊的堆積【遞推式 A(n) = A(n-1) + n  輸入一個整數n,顯示A(1).....A(n)】
//#include<stdio.h>
//int main(){
////	int arr[] = {0};這裡會出現陣列越界,就是說自己後面輸入一個值當作陣列長度,之前不預判長度的話就會出現陣列越界[這就是動態規劃導致的陣列越界]
///*  索引錯誤:最常見的原因是索引錯誤。例如,如果你的陣列有10個元素,索引範圍是0到9,但你嘗試訪問arr[10]或arr[-1],這就超出了陣列的範圍。
//	迴圈條件錯誤:在迴圈中處理陣列時,如果迴圈的條件設定得不正確,可能會導致陣列越界。例如,如果你的迴圈條件是i <= n,而陣列的大小是n,那麼當i等於n時,你將嘗試訪問arr[n],這會越界。
//	陣列大小動態變化:在某些情況下,陣列的實際大小可能會在程式執行時變化(例如,透過動態記憶體分配)。如果你沒有正確地跟蹤陣列的大小,可能會導致越界。
//	使用者輸入:如果你的程式依賴於使用者輸入來確定陣列的索引,而使用者輸入了一個超出範圍的值,這也可能導致陣列越界。
//	陣列初始化錯誤:如果你沒有正確地初始化陣列,可能會訪問到未初始化的記憶體。雖然這不一定是陣列越界,但它可能導致未定義的行為,這通常與陣列越界有關。*/
//	int arr[50] = {0};
//	int n = 0;
//	scanf("%d",&n);
//	arr[1]=1;
//	for(int i=2;i<=n;i++){
//		arr[i] = arr[i-1] + i;
//	}
//	for(int i=1;i<=n;i++){
//		printf("%d\n",arr[i]);
//	}
//	return 0;
//}
//變式:顯示一共有多少個方塊
//#include<stdio.h>
//int main(){
//	int n, sum = 0, ret;//一定要初始化sum!!!!!!!
//	scanf("%d",&n);
//	if(n == 1){
//		printf("1");
//	}else{
//		for(int i=1;i<=n;i++){
//			ret = 2 * i ;//就是找規律解決,反而沒有例一難
//			sum += ret;
//		}printf("%d",sum);
//	}
//	
//	return 0;
//}
//二.猴子吃桃子
//#include<stdio.h>
//int main(){
//	int sum = 0;
//	for(int i=1;i<=2;i++){
//		sum = (i + 1) * 2;
//		int ret = sum;
//			printf("%d\n",sum);
//	}
//	printf("%d",sum);
//	return 0;
//}
//!!!!沒有快取sum,迴圈又從i = 2,開始

//#include<stdio.h>
//int main(){
//	int arr[20] = {0};
//	arr[1] = 1;//要錄入第一天桃子資料
//	for(int i=2;i<=10;i++){
//		arr[i] = (arr [i-1] + 1) * 2;
////		printf("%d",arr[i]);
//	}
//	printf("%d",arr[10]);
//	return 0;
//}
//三·求解有規律的式子前n項和【1/1 +1/2 +2/3 +3/5 +5/8+...  輸入整數n,輸出小數,代表前n項和(保留三位小數)】
//遞迴法
//#include<stdio.h>
//int f(int n){
//	int res = 0;
//	if(n == 1||n ==2){
//		return 1;
//	}else{
//		res += f(n-1) + f(n-2);
//		return res;
//	}
//}//計算分子
//int h(int n){
//	int res = 0;
//	if(n == 1){
//		return 1;
//	}else if(n == 2){
//		return 2;//當時這裡也出錯了,有個else if
//	}
//	else{
//		res += h(n-1) + h(n-2);//記住了,是兩項的遞迴,怎麼當時就寫一項去了
//		return res;
//	}
//}//計算分母
//int main(){
//	double arr[50]={0} ,sum = 0 ,n = 0;
//	scanf("%lf",&n);
////	arr[1] = 1;
////	arr[2] = 1 / 2.0;
//	for(int i=1;i<=n;i++){
//		arr[i] = (double)f(i) / h(i);
//		sum += arr[i];
////		printf("%f  ",sum);
//	}
//	printf("%.3f",sum);
//	return 0;
//}


//遞推法
//#include<stdio.h>
//int main(){
//	int arr[50] = {0},a[50] = {0} ,n = 0;
//	double sum=0 ,ret = 0;
//	scanf("%d",&n);
//	arr[1] = 1;
//	arr[2] = 1;
//	a[1] = 1;
//	a[2] = 2;
//	if(n == 1){
//		printf("1.000")	;
//	}else if(n == 2){
//		printf("1.500");
//	}else{
//			for(int i=3;i<=n;i++){
//				arr[i] = arr[i-1] + arr[i-2];
//				a[i] = a[i-1] + a[i -2];
//				ret = (double) arr[i] / a[i];
//				sum += ret ;
//			}
//			printf("%.3f",sum+3/2.0);//注意要分類討論,不然前兩項沒有加到,而且一定注意 3/2 ==1!!!
//	}
//	return 0;
//}

相關文章