使用递归反向链表

时间:2015-07-27 13:22:37

标签: c++ list c++11 recursion

我正在尝试使用递归来反转链接列表。我创建了reverse()函数来反转列表。我在main()中创建了一个链接列表,并定义了print()方法。 我不知道自己犯了什么错误。请帮我纠正一下。代码片段如下所示。

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

void reverse(node **firstnode,node *n)
{
    if(n==NULL)
    {
        head=n;
        return;
    }
    reverse(&head,n->next);
    struct node *q=n->next;
    n->next=q;
    q->next=NULL;
}

void main()
{
    ......

    head=first;
    reverse(&first,first);
    print(head);
}

4 个答案:

答案 0 :(得分:0)

它可能无法直接解决您的问题。但是,您在标记中提到了C ++ 11。所以,看看std::forward_list。它是基于单个链表的标准容器。

答案 1 :(得分:0)

我认为你在反向函数结束时混淆了你的寻址,它应该看起来像:

q->next=n;
n->next=NULL;

另外,我不确定你是否需要" firstnode"参数。

答案 2 :(得分:0)

List* recur_rlist(List* head)
{
    List* result;
    if(!(head && head->next)) 
        return head;

    result = recur_rlist(head->next);
    head->next->next = head;
    head->next = NULL;

    return result;
}

void printList(List* head)
{
    while(head != NULL) {
        std::cout<<head->data<<" ";
        head = head->next;
    }
}
void main()
{
    List* list = createNode(2);
    append(list, createNode(3));
    append(list, createNode(4));
    append(list, createNode(5));
    append(list, createNode(6));
    List* revlist = recur_rlist(list);
    printList(revlist);
}

答案 3 :(得分:0)

由于您希望了解代码,并且您已经拥有了几个已完成代码的优秀资源,因此不需要更多完成的代码示例。我将回答一些概念并指出您需要修复的错误。

首先,一些背景概念。

链接列表:第一个和休息

任何链接列表都是空的,或者可以分解为第一个(节点)和休息(较小的链接列表,或为空)。这使得递归变得更加容易。

if (head){
    node * first = head;
    node * rest  = head->next;
}

不变(简化):在函数的开头和结尾始终为true的保证。

在链表中,您希望头指向一个节点,该节点指向另一个节点,依此类推,直到您到达结尾,由nullptr发出信号。所有节点都不同。所有节点都有效。这些是在调用函数和函数返回之前必须为true的保证。

在递归函数中,不变量必须保留在每个步骤都要反转的子列表,因为您在每一步都从函数返回。但是这使得递归变得更加容易,因为你要做的就是确保如果输入是好的,那么你的函数将在当前步骤返回一个好的值。

递归结束: 您可以通过组合先前的概念来证明您的递归函数永远不会进入无限循环。如果不变量成立,那么每个步骤都会起作用,并且因为每个递归调用都会休息,这保证是nullptr或更短的列表,最终我们必须到达终点。当然,这表明你处理结束。

好的,关于实际问题:

您没有正确处理递归结束。你最后设置了head = nullptr,我很确定这不是你想要的头脑。您可能想要处理结束if(nullptr == n-&gt; next),因为那时您知道这是最后一个节点。当然,你仍然需要正确处理nullptr == head。

的简单情况

您不保留不变量。你试过了,但看起来你的簿记完全错了。我建议使用调试器或3x5记录卡来逐步完成你正在做的事情来修复交换事物的实际工作。例如,看起来您只是混淆了这个代码片段中的哪个节点:

struct node *q=n->next;   // n is first, q is rest
// what if nullptr == q?
n->next=q;                // n->next = n->next doesn't actually change anything
q->next=NULL;             // this must already be true if reverse(rest) did its job
// q and n were swapped?

此外,您的函数采用“firstnode”但不使用它,而是将全局变量“head”设置为副作用。