在函數內部,可以調用其他函數。如果一個函數在內部調用自身本身,這個函數就是遞歸函數。
一個數的階乘來演示遞歸
4!= 4 * 3 * 2 * 1
一般情況下我們可能會這樣寫:
result = 1
num = 1
while num < 5:
result *= num
num += 1
print(f"4的階乘結果為:{result}")
pycharm中執行結果:
4的階乘結果為:24
使用遞歸:
def get_num(number):
if number > 1:
return number * get_num(number - 1)
else:
return number
result = get_num(4)
print("4的階乘結果為:%s" % result)
pycharm中執行結果:
4的階乘結果為:24
畫圖理解:
文字理解:
===> get_num(4)
===> 4 * get_num(3)
===> 4 * (3 * get_num(2))
===> 4 * (3 * (2* get_num(1)))
===> 4 * (3 * (2 * (1 * 1)))
===> 4 * (3* (2 * 1))
===> 4 * (3 * 2)
===> 4 * 6
===> 24
遞歸函數的優點是定義簡單,邏輯清晰。理論上,所有的遞歸函數都可以寫成循環的方式,但循環的邏輯不如遞歸清晰。
注意: 使用遞歸函數需要注意防止棧溢出。在計算機中,函數調用是通過棧(stack)這種數據結構實現的,每當進入一個函數調用,棧就會加一層棧幀,每當函數返回,棧就會減一層棧幀。由於棧的大小不是無限的,所以,遞歸調用的次數過多,會導致棧溢出。
示例代碼:
def demo():
print("test...")
demo()
demo()
上面的代碼類似於寫了個while True 沒有寫結束循環的條件。
實例:
/* * 遞歸實現n個子母隨機組合每次輸出n個子母(每次輸出不同組合直至輸出所有組合結果) * */
public class TestRecursive {
public static void main(String[] args) {
char[] chs = { 'a', 'b', 'c' };
int number = 2; // 每次輸出幾個字符
arrange(chs, 0, chs.length, number);
}
public static void arrange(char[] chs, int start, int len, int number) {
if (start == len - 1) {
for (int i = 0; i < number; i++) {
System.out.print(chs[i]);
}
System.out.println();
return;
}
for (int i = start; i < len; i++) {
char temp = chs[start];
chs[start] = chs[i];
chs[i] = temp;
arrange(chs, start + 1, len, number);
temp = chs[start];
chs[start] = chs[i];
chs[i] = temp;
}
}
}
eclipse中執行結果:
ab
ac
ba
bc
cb
ca