簡體   English   中英

如何跟蹤遞歸函數

[英]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)----+

如何理解,

  1. 每列代表一個函數調用,它進行 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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM