歡迎訪問我的新博客:http://www.milkcu.com/blog/
原文地址:http://www.milkcu.com/blog/archives/basic-recursion-and-tail-recursion.html
標題:基本遞歸與尾遞歸
作者:MilkCu
摘要:本文主要講解了遞歸的兩種基本形式,基本遞歸與尾遞歸,尾遞歸在一定程度上可以提高程序效率。然後簡要介紹了可執行程序的組成:代碼段,靜態數據區,堆,棧。從組成上闡述了基本遞歸的缺陷和尾遞歸的高效。
基本遞歸
遞歸過程的兩個基本階段:遞推與迴歸。
以基本遞歸方式計算階乘的函數實現:
#include <stdio.h>
int fact(int n)
{
if(n < 0) {
return 0;
} else if(n == 0) {
return 1;
} else if(n == 1) {
return 1;
} else {
return n * fact(n - 1);
}
}
int main(void)
{
printf("%d\n", fact(4));
return 0;
}
可執行程序組成
基本上來說一個可執行程序由4個區域組成:代碼段、靜態數據區、堆與棧。
-
代碼段包含程序運行時所執行的機器指令;
-
靜態數據區包含在程序生命週期內一直持久的數據,比如全局變量和靜態局部變量;
-
堆包含程序運行時動態分配的存儲空間,比如用malloc分配的內存;
-
棧包含函數調用的信息。
棧維護了每個函數調用的信息指導函數返回後才釋放,函數調用的開銷很大。可以採用尾遞歸避免這些缺點。
尾遞歸
當遞歸調用是整個函數中最後執行的語句且它的返回值不屬於表達式的一部分時,這個遞歸調用就是尾遞歸。
尾遞歸函數的特點是在迴歸函數中不用做任何操作,大多數現代的編譯器會利用這一特點自動生成優化的代碼。
以尾遞歸的形式計算階乘的一個函數實現:
#include <stdio.h>
int facttail(int n, int a)
{
if(n < 0) {
return 0;
} else if(n == 0) {
return 1;
} else if(n == 1) {
return a;
} else {
return facttail(n - 1, n * a);
}
}
int main(void)
{
printf("%d\n", facttail(4, 1));
return 0;
}
(全文完)
本文地址:http://www.milkcu.com/blog/archives/basic-recursion-and-tail-recursion.html