????????函數聲明:
????????1.告訴編譯器有一個函數叫什么,參數是什么,返回類型是什么,但是具體是不是存在,函數聲明決定不了。
????????2.函數的聲明一般出現在函數使用之前,要滿足先聲明后使用。
????????3.函數的聲明一般要放在頭文件中。
????????函數定義:
????????函數定義是指函數的具體實現,交代函數的功能實現。
????????函數定義在后面,在前面使用,會產生警告,因為是從前往后執行的。
????????在函數使用之前,加上函數聲明就不會產生警告。
????????函數遞歸
????????程序調用自身的編程技巧稱為遞歸。
? ? ? ? 遞歸作為一種算法在程序設計語言中廣泛應用,一個過程或函數在其定義或說明中有直接或間接調用自身的。
? ? ? ? 一種方法,它通常把一個大型復雜的問題層層轉換為與一個與原問題相似的規模較小的問題來求解,遞歸策略。
? ? ? ? 只需少量的程序就可描述出解題過程中需要的多次重復計算,大大減少了程序的代碼量。
? ? ? ? 遞歸的主要思考方式在于:把大事化小
????????遞歸的兩個必要條件
????????1.存在限制條件,當滿足這個限制條件的時候,遞歸便不在繼續。
? ? ? ? 2.每次遞歸調用后越來越接近這個限制條件。
//輸入1234,按位輸出:1 2 3 4
把大事化小:
print(1234) ---> print(123)? 4 --->?print(12)? 3 4 ---> print(1) 2 3 4? ---> 1 2 3 4
#include <stdio.h>void print(int x){if(x / 10 != 0){print(x / 10);}printf("%d\n",x % 10);
}
//輸入1234,輸出:1 2 3 4
int main()
{int n = 0;scanf("%d",&n);print(n);return 0;
}
????????自定義求字符串長度的函數
#include <stdio.h>//int my_strlen(char* ch){
// int count = 0;
// while(*ch != '\0')
// {
// count++;
// ch++;
// }
// return count;
//}
//不創建臨時變量,求字符串長度
int my_strlen(char* ch){if(*ch != '\0'){//return my_strlen(++ch) + 1;//這種寫法雖然可以,但是會改變chreturn my_strlen(ch + 1) + 1;}elsereturn 0;
}
int main()
{int length = 0;char ch[12] = "Hello World";length = my_strlen(ch);printf("%d\n",length);system("pause");return 0;
}
????????上面一種注釋掉的方法是用while循環,并創建臨時變量來輔助計數,也可以使用遞歸:
my_strlen("abc") ---> 1 +?my_strlen("bc") ---> 1 + 1 +?my_strlen("c") ---> 1 + 1 + 1 +?my_strlen("") ---> 1 + 1 + 1 + 0 = 3
????????計算k的階乘
#include <stdio.h>//計算k的階乘//遞歸實現
//int fac(int x){
// if(x != 1)
// return x * fac(x - 1);
// else
// return 1;
//}//迭代實現
int fac(int x){int i = 0;int ret = 1;for(i = 1;i <= x;i++)ret = ret * i;return ret;
}
int main()
{int k = 0;int n = 0;scanf("%d",&k);n = fac(k);printf("%d\n",n);return 0;
}
????????斐波那契數列:
#include <stdio.h>//斐波那契數列
//遞歸
//int Fibonacci(int x){
// if(x <= 2)
// return 1;
// else
// return Fibonacci(x - 1) + Fibonacci(x - 2);
//}
//非遞歸
int Fibonacci(int x){int i = 0;int a = 1;int b = 1;int c = 0;if(x <= 2)return 1;elsefor(i = 3;i <= x;i++){c = a + b;a = b;b = c;}return c;
}
//1 1 2 3 5 8
int main()
{int k = 0;int n = 0;scanf("%d",&k);n = Fibonacci(k);printf("%d\n",n);return 0;
}
????????系統分配給程序的棧空間是有限的,但是如果出現了死循環或死遞歸,這樣有可能導致一直開辟棧空間,最終產生棧空間耗盡的情況,這樣的現象我們成為棧溢出。
????????如何解決上述問題:
1.將遞歸改寫為非遞歸
2.使用 static 對象替代 nonstatic 局部對象。在遞歸函數設計中,可以使用static對象替代nonstatic局部對象(即棧對象),這不僅可以減少每次遞歸調用和返回時產生和釋放nonstatic對象的開銷,而且static對象還可以保存遞歸調用的中間狀態,并且可為每個調用層所訪問。