2011-03-18 212 views
1

如果我有這樣的遞歸函數:一個遞歸函數C++

int mystery(int n) { 

if (n == 0 || n == 1 || n == 2) return n ; 
return (mystery(n-1) + mystery(n-2) + mystery(n-3)) ; 
} 

我與發現之謎(20)工作。

如何計算函數的執行次數以及爲了計算神祕程度(20)有多少個mystery()的調用?

我嘗試添加一些COUT之類的語句:

int mystery(int n) { 
    if (n == 0 || n == 1 || n == 2) { 
     cout << n << endl; 
     return n ; 
    } 
     cout << n << endl; 
    return (mystery(n-1) + mystery(n-2) + mystery(n-3)) ; 
} 

但我真的無法理解它,因爲有輸出過千數。我不相信那些cout語句在告訴我進行了多少次加法運算以及爲了計算神祕程度(20)而有多少個mystery()的調用方面做了很多工作?

感謝您的幫助!

+0

對於每個打印出來的n> 2,有3個補充。沒有? – Falmarri 2011-03-18 00:52:08

+1

除了遞歸固有的開銷之外,請注意'mystery(n-1)'的調用已經計算了值,這些值將在'mystery(n-2)'的調用中重新計算,並且再次重新計算在電話「神祕(n-3)」中。這意味着糟糕可怕的表現。閱讀關於動態編程。 – wilhelmtell 2011-03-18 00:55:14

+0

@wilhelmtell - 我的猜測是,這是作業的一部分,他們將學習如何計算添加次數。所以使用動態編程來擺脫它們將會破壞目的。 – Omnifarious 2011-03-18 01:10:56

回答

4

最簡單的方法是增加一個全局(或靜態全局)變量。

像獲得神祕來電的號碼:

int nb_of_invok = 0; 
int mystery(int n) 
{ 
    nb_of_invok++; 
    ...your code here... 
} 

這讓增加的數量:

int nb_of_invok = 0; 
int nb_of_add = 0; 
int mystery(int n) 
{ 
    nb_of_invok++; 
    if(...)return n; 
    nb_of_add++; 
    return(...); 
} 
+0

這是最明顯的方法:) – Dagang 2011-03-18 00:58:26

+0

謝謝,但如何我可以跟蹤添加的次數,我應該在函數中放置一個全局變量以追蹤添加的位置?我沒有看到這是怎麼完成的? – Ben 2011-03-18 01:01:33

+0

@Rhinoo我已經更新了我的答案。 – BenjaminB 2011-03-18 01:06:40

2

如果我正確理解你......你可以使用一個靜態計數器變量,並且每次調用該方法時遞增。或者,您可以傳遞一個對計數器的引用,然後將其遞增。

0

聲明兩個不同的靜態int變量來跟蹤調用的次數和加法操作的次數。

2

這是可以找出數學。但是如果你想用經驗來衡量它,你可以在函數中使用一個靜態計數器。這個邏輯很容易擴展到計數添加的數量。

int mystery(int n) { 
    static int invocations = 1; 

    cout << "mystery has been invoked " << invocations++ << " times.\n"; 
    if (n == 0 || n == 1 || n == 2) { 
     return n ; 
    } 
    return (mystery(n-1) + mystery(n-2) + mystery(n-3)) ; 
} 

您也可以使用全局變量。儘管我不喜歡這兩種解決方案。他們很難做到多線程,並且違反了一些重要的設計原則。作爲一個一次性的來回答這個問題,然後從你的代碼,他們是很好,但如果我想這是一個永久性的功能,我會做刪除是這樣的:

#include <iostream> 

class counted_mystery { 
    public: 
    counted_mystery() : invocations_(0), additions_(0) { } 

    unsigned int getInvocations() const { return invocations_; } 
    void resetInvocations(unsigned int newval = 0) { invocations_ = newval; } 

    unsigned int getAdditions() const { return additions_; } 
    void resetAdditions(unsigned int newval = 0) { additions_ = newval; } 

    operator()(int n) { 
     ++invocations_; 
     counted_mystery &mystery = *this; 

     if (n == 0 || n == 1 || n == 2) { 
      return n ; 
     } 
     // The code is about to perform two additions. 
     additions_ += 2; 
     return (mystery(n-1) + mystery(n-2) + mystery(n-3)); 
    } 

    private: 
    unsigned int count_, additions_; 
}; 

int main(int argc, char *argv[]) 
{ 
    using ::std::cout; 

    counted_mystery mystery; 
    mystery(20); 
    cout << "mystery was called " << mystery.getCount() << " times for n == 20\n"; 
    return 0; 
}; 

搞清楚了這一點的數學是有趣的問題,但可能不會太難。我認爲它會變成指數級的。

順便說一句,不要使用endl除非這是你的意思使用。這是非常緩慢的,因爲無論何時使用它都會強制緩衝區刷新。使用'\n'

1

另一個選擇是使這是一個允許使用成員變量而不是全局的類的方法,並且同時保持界面清潔。