C 递归反向链表

C 递归反向链表,c,linked-list,C,Linked List,我在链表中定义了一个节点: typedef struct abc { int id; struct abc *next; }node; 我想递归地反转链表。我正在将头指针传递给函数。我的函数定义如下所示: node *reverseLinkedListRecursively(node *head) { node *current; node *rest; if(head == NULL) return head;

我在链表中定义了一个节点:

typedef struct abc
{
    int id;
    struct abc *next;        
}node;
我想递归地反转链表。我正在将头指针传递给函数。我的函数定义如下所示:

node *reverseLinkedListRecursively(node *head)
{
    node *current;
    node *rest;
    if(head == NULL)
        return head;

    current=head;
    rest=head->next;

    if(rest == NULL)
    {
       return rest;
    }
    reverseLinkedListRecursively(rest);
    current->next->next=rest;
    current->next=NULL;
    return rest;
}

我应该如何进行?我已经实现了迭代方法。

如果要反转列表,必须在节点结构中具有以前的节点指针:

typedef struct abc
{
    int id;
    struct abc *next;
    struct abc *prev;        
}node;
您的列表必须有指向头部和尾部的指针:

typedef struct list
{
    node * first;
    node * last;
} list;

其工作应如下:

node *reverseLinkedListRecursively(node *rest, node *reversed)
{
    node *current;

    if (rest == NULL)
        return reversed;

    current = rest;
    rest = rest->next;
    current->next = reversed;

    return reverseLinkedListRecursively(rest, current);
}
首先,从以下内容开始:

reverseLinkedListRecursively(linkedList, NULL);

顺便说一句:这个函数是尾部递归的。因此,最先进的编译器应该能够将此递归解决方案转换为更有效的迭代解决方案。

要递归地反转链表,我们(递归地)反转(递归地)包含除第一个节点以外的所有内容的子列表,然后将第一个节点放在末尾。为了将第一个节点放在末尾,我们需要递归调用来返回指向最后一个节点的指针,这样我们就可以访问它的
next
成员。当子列表为空时,我们停止递归,只返回当前节点。在我们将第一个节点附加到递归调用结果的末尾之后,当我们从当前递归调用返回时,第一个节点就是“最后一个节点”。最后还有一个细节:原始第一个节点(现在最后一个)仍将指向原始第二个节点(现在第二个最后一个)。我们需要将其修复为null,因为它现在是列表的末尾

因此:


还有一个问题,我想让你考虑一下:我们如何获得指向列表头的新的指针

对于每个递归,跟踪当前节点和其余节点的前端。当剩余值为空时返回。递归返回后,反转“rest”的下一个字段以指向current。为了跟踪新的第一个节点,递归函数只需将旧的最后一个节点传回

void recursive_reverse() {
    // driver for the recursive reverse function.
    // first is a data member of linked list that point to the first node of list.
    first = recursive_reverse(first, first->next);
}

Node* recursive_reverse(Node *current, Node *rest) {
    // if rest == NULL, the current must be the old last node,
    // which is also the new first node
    if (rest == NULL) return current;
    Node *new_first = recursive_reverse(current->next, rest->next);

    // rearrange pointers
    rest->next = current;
    current->next = NULL;

    // pass along the new first node
    return new_first;
}

我最初的实现使用sentinel节点,所以我没有在这里测试代码。很抱歉把它读作伪代码

大家在下面找到了有递归和无递归颠倒链表的程序,希望能对大家有所帮助

void RecursiveReverse(struct node** headRef)  
{  
    struct node* first;  
    struct node* rest; 

    if (*headRef == NULL) return; // empty list base case

    first = *headRef; // suppose first = {1, 2, 3}
    rest = first->next; // rest = {2, 3}

    if (rest == NULL) return; // empty rest base case
    RecursiveReverse(&rest); // Recursively reverse the smaller {2, 3} case after: rest = {3, 2}

    first->next->next = first; // put the first elem on the end of the list
    first->next = NULL; // (tricky step -- make a drawing)

    *headRef = rest; // fix the head pointer
}
LINK *reverse_linked_list_recursion(LINK *head)
{
        LINK *temp;
        if (!head) {
                printf("Empty list\n");
                return head;
        }
        else if (!head->next)
                return head;
        temp = reverse_linked_list_recursion(head->next);
        head->next->next = head;
        head->next = NULL;
        return temp;
}

LINK *reverse_linked_list_without_recursion(LINK *head)
{
        LINK *new, *temp;
        if (!head) {
                printf("No element in the list\n");
                return head;
        }
        else {
                new = head;
                while (head->next) {
                        temp = head->next;
                        head->next = temp->next;
                        temp->next = new;
                        new = temp;
                }
        }
        return new;
}

这是家庭作业吗?看起来像是家庭作业。如果你想让别人帮助你,那么你应该表明你至少自己尝试过解决这个问题。我在想,按照我提供的定义,我们做不到。看看我的答案。在不改变数据结构的情况下,这是可行的。在您之前的版本中,我了解到您希望在列表中进行反向迭代。感谢您分享逻辑。我不知道为什么我无法思考逻辑……您是如何找到解决方案的……请分享如何改进逻辑思维,以及优化,但不是教育性的,因为它实际上只是将迭代伪装成递归。那么我们如何获得指向列表新头的指针呢?你能回答吗。您的解决方案必须更改以返回新的头。
void RecursiveReverse(struct node** headRef)  
{  
    struct node* first;  
    struct node* rest; 

    if (*headRef == NULL) return; // empty list base case

    first = *headRef; // suppose first = {1, 2, 3}
    rest = first->next; // rest = {2, 3}

    if (rest == NULL) return; // empty rest base case
    RecursiveReverse(&rest); // Recursively reverse the smaller {2, 3} case after: rest = {3, 2}

    first->next->next = first; // put the first elem on the end of the list
    first->next = NULL; // (tricky step -- make a drawing)

    *headRef = rest; // fix the head pointer
}
LINK *reverse_linked_list_recursion(LINK *head)
{
        LINK *temp;
        if (!head) {
                printf("Empty list\n");
                return head;
        }
        else if (!head->next)
                return head;
        temp = reverse_linked_list_recursion(head->next);
        head->next->next = head;
        head->next = NULL;
        return temp;
}

LINK *reverse_linked_list_without_recursion(LINK *head)
{
        LINK *new, *temp;
        if (!head) {
                printf("No element in the list\n");
                return head;
        }
        else {
                new = head;
                while (head->next) {
                        temp = head->next;
                        head->next = temp->next;
                        temp->next = new;
                        new = temp;
                }
        }
        return new;
}