【问题标题】:Reverse Linked List Recursively递归反向链表
【发布时间】:2011-12-19 06:46:42
【问题描述】:

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

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

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

【问题讨论】:

  • 这是作业吗?它看起来像家庭作业。如果您希望别人帮助您,那么您应该表明您至少尝试过自己解决问题。

标签: c linked-list


【解决方案1】:

它应该如下工作:

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

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

【讨论】:

  • 感谢分享逻辑。
  • 我不知道为什么我无法想到逻辑......你是如何找到解决方案的......请分享如何提高逻辑思维
  • 有效,并且是最佳的,但没有那么有教育意义,因为它实际上只是将迭代伪装成递归。
【解决方案2】:
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;
}

【讨论】:

    【解决方案3】:

    为了递归地反转链表,我们反转(递归地)由除第一个节点之外的所有内容组成的子列表,然后将第一个节点放在末尾。要将第一个节点放在最后,我们需要递归调用以返回指向最后一个节点的指针,以便我们可以访问其next 成员。当子列表为空时,我们停止递归,只返回当前节点。在我们将第一个节点附加到递归调用结果的末尾之后,当我们从当前递归调用返回时,第一个节点就是“最后一个节点”。最后还有一个细节:原来的第一个节点(现在是最后一个)仍将指向原来的第二个节点(现在是倒数第二个)。我们需要将其修复为 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 头部的指针? :)

    【讨论】:

    • 那么我们如何获得指向新列表头的指针呢?你可以回答吗。你的解决方案必须改变以返回新的头部。
    【解决方案4】:

    对于每个递归,跟踪当前节点和其余节点的前面。其余为 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;
    }
    

    我的原始实现使用了一个哨兵节点,所以我没有在这里测试代码。对不起!只需将其作为伪代码阅读即可。

    【讨论】:

      【解决方案5】:
      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
      }
      

      【讨论】:

        【解决方案6】:

        如果你想反转一个列表,你的节点结构中必须有以前的节点指针:

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

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

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

        【讨论】:

        • 我在想我们不能按照我提供的定义来做
        • 看我的回答。在不改变数据结构的情况下是可行的。
        • 以前的版本我知道您想在您的列表中进行反向迭代。
        【解决方案7】:

        大家好,请在下面找到使用和不使用递归的反向链表程序,希望这对你有所帮助。

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

        【讨论】:

          猜你喜欢
          • 2013-03-04
          • 1970-01-01
          • 1970-01-01
          • 2016-08-01
          • 2021-11-30
          • 1970-01-01
          相关资源
          最近更新 更多