【问题标题】:Recursive base case for c++ circular linked listc++循环链表的递归基本情况
【发布时间】:2018-10-24 18:03:06
【问题描述】:

这都是假设,

我有一个这样的结构:

struct node
{
    int     data;
    node*   next;
};

和一个只有一个头指针的循环链表,我将如何为一个计算循环链表节点的递归函数设置一个基本情况?我什至不知道从哪里开始,因为我集思广益,很快意识到行不通,因为列表中的最后一个节点直接指向头部而不是 NULL。

示例函数:

int count(node *head)
{
   int listCount = 0;

   if(base case)
   {
     then return 0;
   }
   else
   {
     calculate listCount
     count(head->next);
   }

   return listCount
}

【问题讨论】:

  • 您能否包含实际的 C++ 代码,而不仅仅是一些无法编译的虚拟代码?链表是一种极其常见的数据结构,所以如果您不熟悉它们是什么,那么在一些open courseware 中进行入门是个好主意。
  • 我正在处理一个构建循环链表并使用固定“头”指针的目标文件,我想在单独的 cpp 文件中实现此循环链接的递归函数列表。我无法发布代码,因为我什至不知道从哪里开始递归函数的基本情况。我接受的每个选项都会导致无限递归调用。
  • 所以我真正难过的是,我如何在递归函数中达到一个基本情况,该函数涉及一个只有一个头指针的循环链表(最后一个节点指向头) .
  • count 是节点的成员吗?如果 node 是您的函数知道的唯一状态,则根据定义,这对于循环列表是不可能的。
  • 对不起,这是一个本地 int 变量,让我编辑帖子以反映这一点。

标签: c++ recursion linked-list


【解决方案1】:

你可以把循环链表变成线性链表

int wrapper_function(node*head)
{
    node*current = head;
    head  = head -> next;
    current -> next = NULL;
    count(head);
    current -> next = head;
    head = current;
    return 0;
}


int count(node *head)
{
   int count = 0;

   if(!head)
   {
   then return 0;
   }
   else
  {
   calculate count
   count(head->next);
  }

   return;
}

【讨论】:

  • 嗯,我从来没想过,这是唯一可行的方法吗?
  • 对不起,我的意思是限制只有一个函数参数“node *head”并且不使用迭代方法。
  • 好办法,即使你的循环链表不允许修改,你也可以将链表连接回循环形式:))
  • 我想我会试试你发布的方法,非常感谢!
  • 哈哈,这是为我的实验室准备的,我不确定我们是否能打破这个圈子,但我会这样做,并希望一切顺利!这就是我喜欢 CS 的原因,希望有一天我也能帮助其他人。
【解决方案2】:

为了确保您将在链表中找到某种起点(可能是您的第一个指针左右),例如,我们将其称为“根”,这样该类将如下所示:

class circle_list {
    node *root;

    ...

    public:
    int count(node *head);
};

现在你可以从这个节点迭代一个基本情况,如果你和根节点在同一个指针上,你返回 0。它会在第一次迭代中返回,所以你可以通过这个问题几种方法,例如,您可以将 head(默认参数)作为“nullptr”发送并检查“head == nullptr”是否在基本情况之后将 head 设置为 root:

int count(node *head = nullptr) {
    if (head == root) {
        return 0;
    }

    if (head == nullptr) {
        head = root;
    }

    return 1 + count(head->next);
}

这里有很多可能性,当然这只是可能的想法之一。

【讨论】:

    【解决方案3】:

    好吧,我们必须区分:

    • 空列表,head 为 nullptr
    • 我们位居榜首
    • 我们在列表中间
    • 我们位于列表的末尾,即。 e.我们再次到达头部

    为了能够区分,您需要跟踪头部!在给定的情况下,通过简单的迭代来完成任务会更容易,所以让我们开始吧:

    unsigned int count(node* head)
    {
        if(head == nullptr)
            return 0;
        unsigned int n = 1;
        node* current = head->next; // start at next element!
        while(current != head)      // only way to detect end!
        {
           ++n;
           current = current->next;
        }
        return n;
    }
    

    现在,如果您坚持使用递归函数:由于我们需要跟踪头部,我们需要两个指针。没办法。但是我们可以提供一个单独的入口函数,只接受头部,然后将两个指针传递给实际的递归函数:

    unsigned int count(node* head)
    {
        if(head == nullptr)
            return 0;
        return count(head, head->next);
    }
    unsigned count(node* head, node* current)
    {
        if(current == head) // our end condition!
            return 1;
        return 1 + count(head, current->next);
    }
    

    【讨论】:

      【解决方案4】:

      假设你有一些指向 head 的固定指针,iterator 指向 head:

      count(node *head, node *iterator, int *numOfElem)
      {      
      
         if(head==iterator)
            return;
         else
           { 
              (*numOfElem)++;
              count(head, iterator->next, numOfElem);
           }
      }
      

      【讨论】:

      • 我忘了说我唯一可以使用的函数参数是“node *head”。
      • 在 C++ 中,您需要将 reference 而非指针传递给可变参数。这不是必需的,因为您始终可以使用return 1 + count(head, iterator->next) 并具有常规返回类型。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-08-12
      • 2021-09-01
      • 1970-01-01
      • 1970-01-01
      • 2011-08-11
      相关资源
      最近更新 更多