在 C 語言里,函數遞歸是一種函數調用自身的編程技術。下面開始逐一介紹。
一、什么是遞歸?
遞歸其實是?種解決問題的?法,在C語?中,遞歸就是函數??調???。
int main()
{
?? ?printf("hehe\n");
?? ?main();//main函數中?調?了main函數
?? ?return 0;
}

5!= 5 * 4 * 3 * 2 * 1
4!= 4 * 3 * 2 * 1
所以:5!= 5 * 4!

{
?? ?if (n == 0)
?? ??? ?return 1;
?? ?else
?? ??? ?return n * Fact(n - 1);
}
int Fact(int n)
{
?? ?if (n == 0)
?? ??? ?return 1;
?? ?else
?? ??? ?return n * Fact(n - 1);
}
int main()
{
?? ?int n = 0;
?? ?scanf("%d", &n);
?? ?int ret = Fact(n);
?? ?printf("%d\n", ret);
?? ? return 0;
}


Print(n)
如果n是1234,那表?為
Print(1234) //打印1234的每?位
其中1234中的4可以通過 % 10得到,那么
Print(1234)就可以拆分為兩步:
1. Print(1234 / 10) //打印123的每?位
2. printf(1234 % 10) //打印4
完成上述2步,那就完成了1234每?位的打印
那么Print(123)?可以拆分為Print(123 / 10) + printf(123 % 10)
以此類推下去,就有
Print(1234)
==> Print(123) + printf(4)
==> Print(12) + printf(3)
==> Print(1) + printf(2)
==> printf(1)
直到被打印的數字變成?位數的時候,就不需要再拆分,遞歸結束。
那么代碼完成也就?較清楚:
void Print(int n)
{
?? ?if (n > 9)
?? ?{
?? ??? ?Print(n / 10);
?? ?}
?? ?printf("%d ", n % 10);
}
int main()
{
?? ?int m = 0;
?? ?scanf("%d", &m);
?? ?Print(m);
?? ?return 0;
}
輸入和輸出的結果:
在這里,我們運用到了大事化小的思路。
三、遞歸與迭代

{
?? ?if (n == 0)
?? ??? ?return 1;
?? ?else
?? ??? ?return n * Fact(n - 1);
}


factorial(5) 調用 5 * factorial(4)。
factorial(4) 調用 4 * factorial(3)。
factorial(3) 調用 3 * factorial(2)。
factorial(2) 調用 2 * factorial(1)。
factorial(1) 滿足基本情況,返回 1。
然后逐步回溯計算:
factorial(2) 返回 2 * 1 = 2。
factorial(3) 返回 3 * 2 = 6。
factorial(4) 返回 4 * 6 = 24。
factorial(5) 返回 5 * 24 = 120。
優點:
代碼簡潔:遞歸可以讓代碼更加簡潔、易讀,尤其是處理一些具有遞歸結構的問題,如樹的遍歷、分治算法等。
易于理解:對于某些問題,遞歸的思路更貼合人類的思維方式,更容易設計和實現。
缺點:
性能問題:遞歸調用會頻繁地進行函數調用和返回操作,帶來額外的開銷,可能會導致性能下降。
棧溢出風險:如果遞歸深度過大,會導致棧空間耗盡,引發棧溢出錯誤。
注意事項
要確保遞歸函數包含基本情況,防止無限遞歸。
注意遞歸深度,避免棧溢出。在必要時,可以考慮使用迭代(循環)來替代遞歸。
迭代:通常情況下,迭代的執行效率相對較高,因為它避免了函數調用棧的頻繁操作,只是在循環結構內進行簡單的指令重復執行,減少了額外的開銷。
遞歸:遞歸由于不斷地進行函數調用和返回,會有一定的時間和空間開銷,尤其是在遞歸深度較大時,可能會出現棧溢出等性能問題。
代碼可讀性:
迭代:對于一些簡單邏輯,迭代代碼的結構清晰,易于理解和調試,直接通過循環條件和循環體就能明白代碼的執行流程。
遞歸:遞歸代碼在處理具有遞歸結構的問題(如樹的遍歷、分治算法等)時,代碼可能更簡潔,更符合人們對問題的分解式思考方式,但對于初學者或者復雜邏輯,理解起來可能有一定難度。
迭代和遞歸各有優缺點,在實際編程中,需要根據問題的特點、性能要求和代碼的可讀性來選擇合適的方法。有時候,迭代和遞歸可以相互轉換,通過合理的設計和優化,可以提高代碼的性能和可維護性。