簡體   English   中英

如何在C ++中找到遞歸函數的深度

[英]How can I find the depth of a recursive function in C++

如何在不傳遞上一級的情況下在C ++中找到遞歸函數內的當前深度? 即,是否可以知道調用函數的次數而不使用參數來跟蹤級別並在每次調用函數時將該數字作為參數傳遞?

例如,我的遞歸函數如下所示:

DoSomething(int level)
{
  print level;
  if (level > 10)
    return;
  DoSomething(++level);
}

main
{
  DoSomething(0);
}

基於JoshD已經給出的答案

void recursive() 
{ 
    static int calls = 0;
    static int max_calls = 0;
    calls++;
    if (calls > max_calls)
        max_calls = calls;

    recursive();

    calls--;
}

這會在遞歸函數完成后重置計數器,但仍會跟蹤遞歸的最大深度。

除了快速測試之外,我不會像這樣使用靜態變量,不久之后就會被刪除。 如果你真的需要持續跟蹤這個,那么有更好的方法。

你可以在函數中使用一個靜態變量......

void recursive()
{
 static int calls = 0;
 calls++;
 recursive();
}

當然,當你開始一個新的始發呼叫時,這將繼續計數....

如果您不關心線程安全性,可以使用本地靜態變量。

雖然,這只會在您第一次運行遞歸例程時給出正確的計數。 更好的技術是RAII保護類型,它包含一個內部靜態變量。 在遞歸例程開始時,構造保護類。 構造函數會增加內部靜態變量,析構函數會減少它。 這樣,當您創建一個新的堆棧幀時,計數器會增加1,當您從每個堆棧幀返回時,計數器將減1。

struct recursion_guard
{
    recursion_guard() { ++counter; }

    ~recursion_guard() { --counter; }

    static int counter;
};

int recursion_guard::counter = 0;

void recurse(int x)
{
    recursion_guard rg;
    if (x > 10) return;
    recurse(x + 1);
}

int main()
{
    recurse(0);
    recurse(0);
}

但請注意,這仍然不是線程安全的。 如果需要線程安全性,可以使用boost::thread_specific_ptr或C ++ 0x thread本地工具將thread-local-storage變量替換為static-storage變量。

如果您希望它是可重入且線程安全的,為什么不:

void rec(int &level)  // reference to your level var
{
   // do work

   rec(++level); // go down one level
}

main()
{
   //and you call it like
   int level=0;
   rec(level);

   cout<<level<<" levels."<<endl;
}

沒有靜態/全局變量來破壞線程,你可以為不同的遞歸鏈使用不同的變量來解決重入問題。

如果可以在編譯時確定,也可以將級別作為模板參數傳遞。 您還可以使用函數對象。 這是迄今為止最好的選擇 - 減少麻煩,應盡可能避免靜態變量。

struct DoSomething {
    DoSomething() {
        calls = 0;
    }
    void operator()() {
        std::cout << calls;
        calls++;
        if (calls < 10)
            return operator()();
        return;
    }
    int calls;
};

int main() {
    DoSomething()(); // note the double ().
    std::cin.get();
}

level轉換為能夠包含參數和(可能)函數的新對象(通常是模板)的實例變量。 然后你可以重用遞歸累加器接口。

您還可以嘗試使用全局變量來記錄深度。

var depth = 0;

DoSomething()
{
  print ++depth;
  if (depth > 10)
    return;
  DoSomething();
}

main
{
  DoSomething(0);
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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