递归反向链接列表

时间:2011-11-01 06:46:03

标签: 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;

    current=head;
    rest=head->next;

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

我该怎么办?我已经实现了迭代方法。

7 个答案:

答案 0 :(得分:9)

它应该如下工作:

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);

BTW:这个函数是尾递归的。因此,最先进的编译器应该能够将这种递归解决方案转变为更有效的迭代解决方案。

答案 1 :(得分:6)

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


    current=head;
    rest=head->next;

    if(rest == NULL)
    {
        /* Wrong. Think about the simple case of a one-element list.
           Your code will return NULL as the reversed list. */
        //return rest;
        return current;
    }
    /* You lost the return value, which will be the beginning of the reversed 'rest'. */
    //reverseLinkedListRecursively(rest);
    rest = reverseLinkedListRecursively(rest);

    /* current->next points to the last element in the reversed 'rest'.
       What do you want that to point to? */
    //current->next->next=rest;
    current->next->next = current; // temporarily circular
    current->next=NULL;

    /* Now you can return rest, since you set it to the beginning of the reversed list. */
    return rest;
}

答案 2 :(得分:2)

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

因此:

node* reverseLinkedListHelper(node* head) {
    if (head->next == NULL) { return head; }
    node* last = reverseLinkedListRecursively(head->next);
    last->next = head;
    return head;
}

void reverseLinkedList(node* head) {
    assert (head != NULL);
    reverseLinkedListHelper(head);
    head->next = NULL;
}

还有一个问题,我会让你思考:我们如何获得指向列表中 new 头部的指针? :)

答案 3 :(得分:1)

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

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节点,所以我没有在这里测试代码。抱歉!只需将其读作伪代码即可。

答案 4 :(得分:1)

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
}

答案 5 :(得分:0)

如果要反转列表,则必须在节点结构中包含先前的节点指针:

typedef struct abc
{
    int id;
    struct abc *next;
    struct abc *prev;        
}node;

并且你的列表必须有指向头部和尾部的指针:

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

答案 6 :(得分:0)

嘿家伙们在下面找到了带有和不带递归的链接列表的程序,希望这对你有帮助。

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;
}