簡體   English   中英

如何將遞歸 function 轉換為迭代

[英]How to transform a recursive function to an iterative one

我正在嘗試使用堆棧將此遞歸 function 轉換為迭代:

void GetToTownRecursive(int x, Country &country, AList *accessiblesGroup, vector<eTownColor> &cities_colors)
{

    cities_colors[x - 1] = eTownColor::BLACK;
    accessiblesGroup->Insert(x);

    List *connected_cities = country.GetConnectedCities(x);
    if (!connected_cities->IsEmpty())
    {
        ListNode *curr_city = connected_cities->First();
        while (curr_city != nullptr)
        {
    
            if (cities_colors[curr_city->GetTown() - 1] == eTownColor::WHITE)
            {
                GetToTownRecursive(curr_city->GetTown(), country, accessiblesGroup, cities_colors);
            }
            curr_city = curr_city->GetNextNode();
        }
    }
}

function 將城鎮編號作為輸入並返回與該城鎮相連(直接和間接)的城鎮列表。

由於內部的 while 循環以及遞歸調用后采取的唯一操作是提升列表迭代器 - curr_city ,我很難轉換它。 在這種情況下我應該將什么壓入堆棧?

很高興為您提供幫助!

遞歸調用之后采取的操作是 while 循環的全部剩余部分(所有剩余的迭代)。 在堆棧上,您必須保存在遞歸調用期間可能更改但之后需要的所有變量。 在這種情況下,這只是curr_city的值。

如果goto仍然存在,則可以將遞歸調用替換為:

  1. 保存curr_city
  2. 設置x = curr_city->GetTown()
  3. 轉到開始

那么最后,你必須

  1. 檢查堆棧
  2. 如果有一個保存的curr_city ,恢復它並在 (3) 之后轉到

因為對這種事情使用 gotos 是不可接受的(它們使您的代碼難以理解),所以您必須將 function 分成 3 個頂級部分:

  • 第 1 部分:第一次遞歸調用之前的所有內容,以 1-3 結尾
  • 第 2 部分:在遞歸調用之間執行所有操作的循環,如果到達另一個遞歸調用則以 1-3 結束,否則以 4-5 結束。
  • 第 3 部分:在最后一次遞歸調用之后發生的任何事情,在這種情況下什么都不是。

通常,在此重新安排之后,您可以進行大量清理和簡化工作。

基本思想如下所示。

void GetToTown(int x, Country &country, AList *accessiblesGroup,
   vector<eTownColor> &cities_colors)
{
    Stack<int> pendingX = new ...
      
    pendingX.push(x);
    
    while (!pendingX.isEmpty()) {
        int localX = pendingX.Pop();
        cities_colors[localX - 1] = eTownColor::BLACK;
        accessiblesGroup->Insert(localX);
        
        List *connected_cities = country.GetConnectedCities(localX);
        if (!connected_cities->IsEmpty())
        {
            ListNode *curr_city = connected_cities->First();
            while (curr_city != nullptr)
            {            
                if (cities_colors[curr_city->GetTown() - 1] == nColor::WHITE)
                {
                    pendingX.Push(curr_city->GetTown());
                }
                curr_city = curr_city->GetNextNode();
            }
         }
    }
}

暫無
暫無

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

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