[英]How do I trace recursive function
所以在我的一個班級中,我正在學習遞歸,有一個問題我試圖追查但無法得到正確的答案。
我一直得到 11,但正確答案是 6。有人可以幫助我更好地理解並希望解釋您將如何跟蹤代碼。 謝謝你。
我現在追蹤它的方式:
int f(int x, int y) {
if (x <= 0) {
return y;
}
return f(x - 1, y + 1) - f(x / 2, y * 2);
}
What is f(4, -1)?
f(4,-1)
return f(3,0) - f(2,-2)
return f(2,1) - f(1,-4)
return f(1,2) - f(0,-8)
return f(0,3) - (-8)
return 3 + 8 = 11.
你是不是考慮到大部分調用的f()
然后進行到2個內部呼叫f()
所以真正的跟蹤會更像下面這樣分解。 真正的答案是2
,而不是你教授告訴你的6
:
f(4,-1) = f(3,0) - f(2,-2)
(
f(3,0) = f(2,1) - f(1,0)
(
f(2,1) = f(1,2) - f(1,2)
(
f(1,2) = f(0,3) - f(0,4)
(
f(0,3) = 3
)
(
f(0,4) = 4
)
= (3) - (4) = -1
)
(
f(1,2) = f(0,3) - f(0,4)
(
f(0,3) = 3
)
(
f(0,4) = 4
)
= (3) - (4) = -1
)
= (-1) - (-1) = 0
)
(
f(1,0) = f(0,1) - f(0,0)
(
f(0,1) = 1
)
(
f(0,0) = 0
)
= (1) - (0) = 1
)
= (0) - (1) = -1
)
(
f(2,-2) = f(1,-1) - f(1,-4)
(
f(1,-1) = f(0,0) - f(0,-2)
(
f(0,0) = 0
)
(
f(0,-2) = -2
)
= (0) - (-2) = 2
)
(
f(1,-4) = f(0,-3) - f(0,-8)
(
f(0,-3) = -3
)
(
f(0,-8) = -8
)
= (-3) - (-8) = 5
)
= (2) - (5) = -3
)
= (-1) - (-3) = 2
final answer: 2
這是帶有遞歸調用控制流的 ASCII 藝術,
f(4,-1)-------->+
. //f(4 - 1, -1 + 1)
. f(3,0)------->+
. . |
. . //f(3-1,0+1)
. . f(2,1)----------->+
. . . |
. . . // f(2-1,1+1)
. . . f(1,2)--------->+
. . . . |
. . . . //f(1-1,2+1)
. . . . f(0,3)--------->+
. . . . . //as (x == 0) return 3
. . . . . |
. . . . |<----(3)---+
. . . . |
. . . . //f(1/2,2*2)
. . . . f(0,4)--------->+
. . . . . //as (x == 0) return 4
. . . . . |
. . . . +<----(4)---+
. . . . |
. . . . //f(1-1,2+1) - f(1/2,2*2) = 3 - 4 = -1
. . . +<---(-1)---+
. . . |
. . . // f(2/2,1*2)
. . . f(1,2)--------->+
. . . . |
. . . . //f(1-1,2+1)
. . . . f(0,3)--------->+
. . . . . //as (x == 0) return 3
. . . . . |
. . . . +<----(3)---+
. . . . |
. . . . //f(1/2,2*2)
. . . . f(0,4)--------->+
. . . . . //as (x == 0) return 4
. . . . . |
. . . . +<----(4)---+
. . . . |
. . . . //f(1-1,2+1) - f(1/2,2*2) = 3 - 4 = -1
. . . +<---(-1)---+
. . +<----(0)-------+
. . |
. . //f(3/2,0*2)
. . f(1,0)----------->+
. . . |
. . . //f(1-1,0+1)
. . . f(0,1)--------->+
. . . . //as (x == 0) return 1
. . . . |
. . . +<----(1)---+
. . . |
. . . //f(1/2,0*2)
. . . f(0,0)--------->+
. . . . //as (x == 0) return 0
. . . . |
. . . +<----(0)---+
. . . |
. . . //f(0,1)-f(0,0) = 1- 0 = 0
. . +<-----(1)------+
. . |
. . // f(3-1,0+1) - f(3/2,0*) = 0 - 1 = -1
. +<----(-1)--+
. |
. //f(4/2,-1*2)
. f(2,-2)------->+
. . |
. . //f(2-1,-2+1)
. . f(1,-1)---------->+
. . . |
. . . //f(2-1,-2+1)
. . . f(0,0)--------->+
. . . . //as (x == 0) return 0
. . . . |
. . . +<----(0)---+
. . . |
. . . //f(1/2,-1*2)
. . . f(0,-2)-------->+
. . . . //as (x == 0) return -2
. . . . |
. . . +<---(-2)---+
. . . |
. . . //f(0,0)-f(0,-2) = 0 - (-2) = 2
. . +<----(2)-------+
. . |
. . //f(2/2,-2*2)
. . f(1,-4)---------->+
. . . |
. . . f(0,-3)-------->+
. . . . //as (x == 0) return -3
. . . . |
. . . +<---(-3)---+
. . . |
. . . f(0,-8)-------->+
. . . . //as (x == 0) return -8
. . . . |
. . . +<---(-8)---+
. . . |
. . . //f(0,-3) -f(0,-8) = -3 -(-8) = 5
. . +<-----(5)------+
. . |
. . //f(1,-1)-f(1,-4) = 2 - 5 = -3
. +<----(-3)--+
. |
. //f(4 - 1, -1 + 1) - f(4/2,-1*2) = -1 - (-3) = 2
<----(2)----+
如何理解,
<--(x)---
代表返回值x
當函數 f(x,y) 被調用時,對 f(x-1,y+1) 的遞歸調用被調用,直到 x 為零,然后 f(x/2,y*2) 被遞歸調用。
考慮以下情況,f(1,2) 調用對 f(0,3) 和 f(0,4) 進行兩次后續遞歸調用,並且兩者的返回值都計算為 f(1,2) 的返回值
f(1,2)--------->+
. |
. //f(1-1,2+1)
. f(0,3)--------->+
. . //as (x == 0) return 3
. . |
. |<----(3)---+
. |
. //f(1/2,2*2)
. f(0,4)--------->+
. . //as (x == 0) return 3
. . |
. +<----(4)---+
. |
. //f(1-1,2+1) - f(1/2,2*2) = 3 - 4 = -1
+<---(-1)---+
如果需要,您可以手動打印出這些痕跡。 在大多數情況下可能不如調試器好,但它偶爾會派上用場。 https://godbolt.org/z/WpSYNj
#include <iostream>
int g_tabs = 0;
struct trace
{
trace(int x, int y)
{
for(int i = 0; i < g_tabs; ++i)
std::cout << " ";
std::cout << "f(" << x << ", " << y << ") {\n";
++g_tabs;
}
~trace()
{
--g_tabs;
for(int i = 0; i < g_tabs; ++i)
std::cout << " ";
std::cout << "}\n";
}
};
void print(int res)
{
for(int i = 0; i < g_tabs; ++i)
std::cout << " ";
std::cout << "result[ " << res << " ]\n";
}
void print(int l, int r, int res)
{
for(int i = 0; i < g_tabs; ++i)
std::cout << " ";
std::cout << "result[ " << res << " ] = " << l << " - " << r << '\n';
}
int f(int x, int y)
{
trace t(x, y);
if (x <= 0) {
print(y);
return y;
}
int left = f(x - 1, y + 1);
int right = f(x / 2, y * 2);
int result = left - right;
print(left, right, result);
return result;
}
int main()
{
f(5, 3);
return 0;
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.