由於您的示例方法是尾遞歸,因此將其翻譯爲迭代樣式很容易,甚至不需要顯式堆棧。
這裏有一些步驟,可應用於任何遞歸函數:
步驟1:重寫方法,因此調用自身一次(你的方法已經這樣做了),都只有一個return
語句,使用if
和goto
代替else
,while
,for
和foreach
:
int gcd(int m, int n)
{
int result;
if (n == 0)
{
result = m;
goto done;
}
result = gcd(n, m % n);
done:
return result;
}
步驟2:替換的新參數的參數賦值遞歸調用和goto
的方法開始:
int gcd(int m, int n)
{
int result;
start:
if (n == 0)
{
result = m;
goto done;
}
int old_m = m;
m = n;
n = old_m % n;
goto start;
done:
return result;
}
如果該方法不是尾遞歸的方法將需要保存其狀態在goto
之前,稍後再恢復它。
步驟3:再次拆下goto
S:
int gcd(int m, int n)
{
int result;
while (true)
{
if (n == 0)
{
result = m;
break;
}
int old_m = m;
m = n;
n = old_m % n;
}
return result;
}
步驟4:使方法看起來更好:
int gcd(int m, int n)
{
while (n != 0)
{
int old_m = m;
m = n;
n = old_m % n;
}
return m;
}
下面是不是尾的示例 - 遞歸:
int fac(int x)
{
if (x == 0)
{
return 1;
}
return x * fac(x - 1);
}
步驟1:
int fac(int x)
{
int result;
if (x == 0)
{
result = 1;
goto end;
}
result = x * fac(x - 1);
end:
return result;
}
步驟2:
int fac(int x)
{
Stack<int> stack = new Stack<int>();
int result;
start:
if (x == 0)
{
result = 1;
goto end;
}
stack.Push(x);
x = x - 1;
goto start;
end:
if (stack.Count != 0)
{
x = stack.Pop();
result = x * result;
goto end;
}
return result;
}
步驟3:
int fac(int x)
{
Stack<int> stack = new Stack<int>();
int result;
while (true)
{
if (x == 0)
{
result = 1;
break;
}
stack.Push(x);
x = x - 1;
}
while (stack.Count != 0)
{
x = stack.Pop();
result = x * result;
}
return result;
}
第4步:
int fac(int x)
{
Stack<int> stack = new Stack<int>();
while (x != 0)
{
stack.Push(x);
x = x - 1;
}
int result = 1;
while (stack.Count != 0)
{
x = stack.Pop();
result = x * result;
}
return result;
}
來源
2011-09-03 13:51:14
dtb
您的gcd示例中沒有收藏,您爲什麼需要一個堆棧?你想在那裏存儲什麼? –
這完全是一個例子..當然,我知道我甚至不需要在這種情況下使用'堆棧'..但它是最簡單的情況下,我可以想到關於遞歸。 – colinfang