这都是假设的,
我有一个结构如下:
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
}
你可以将 ciruclar 链表变成线性链表
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;
}
当然,你会在链表中有一个某种起点(也许是你的第一个指针左右(,让我们称之为"root",例如,这样类就会看起来像这样:
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);
}
这里有很多可能性,当然这只是这里可能的想法之一。
好吧,我们必须区分:
空- 列表,磁头为空
- 我们位居榜首
- 我们位于列表的中间
- 我们在列表的末尾,即我们再次到达头部
为了能够区分,您需要跟踪头部!在给定的情况下,通过简单的迭代更容易完成任务,所以让我们从:
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);
}
假设你有一些固定的指向头部和iterator
指向头部的指针:
count(node *head, node *iterator, int *numOfElem)
{
if(head==iterator)
return;
else
{
(*numOfElem)++;
count(head, iterator->next, numOfElem);
}
}