简体   繁体   English

链表反递

[英]Linked list recursive reverse

I was looking at the code below from stanford library: 我在stanford库中查看下面的代码:

void recursiveReverse(struct node** head_ref)
{
    struct node* first;
    struct node* rest;

    /* empty list */
    if (*head_ref == NULL)
       return;  

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

    /* List has only one node */
    if (rest == NULL)
       return;  

    /* put the first element on the end of the list */
    recursiveReverse(&rest);
    first->next->next  = first; 

    /* tricky step -- see the diagram */
    first->next  = NULL;         

    /* fix the head pointer */
    *head_ref = rest;
}

What I don't understand is in the last recursive step for eg if list is 1-2-3-4 Now for the last recursive step first will be 1 and rest will be 2. So if you set *head_ref = rest .. that makes the head of the list 2 ?? 我不明白的是在最后的递归步骤中,例如,如果列表是1-2-3-4现在最后的递归步骤首先将是1而休息将是2.所以如果你设置* head_ref = rest ..这使得列表的头部2 ?? Can someone please explain how after reversing the head of the list becomes 4 ?? 有人可以解释一下如何在倒转列表的头部后变成4吗?

Draw out a stack trace... 绘制堆栈跟踪...

Intial - {1,2,3,4}
Head - 1
Rest = 2,3,4
Recurse(2,3,4)
Head = 2
Rest = 3,4
Recurse(3,4)
Head = 3 
Rest = 4
Recurse (4)
Head = 4
Rest = null //Base Case Reached!! Unwind.

So now we pick up 
Recurse(3,4)
Head = 3 
Rest = 4
// Return picks up here
first->next->next  = first; 
so list is:
3,4,3
// set head to null,
null ,4,3,
//Off with his head!
4,3
Return

Now we're here
Recurse(2,3,4)
Head = 2
Rest = 3,4
Previous return leaves state as:
Head = 2  //But Head -> next is still 3! -- We haven't changed that yet..
Rest = 4,3  
Head->next is 3, 
Head->next->next = 2 makes the list (actually a tree now)
4->3->2
   ^
   |
   2
And chop off the head leaving
4->3->2
and return.

Similarly, do the last step which will leave
4->3->2->1
      ^
      |
      1
and chop off the head, which removes the one. 

Consider the list: 考虑清单:

   1  ->  2  ->  3  ->  4 -> NULL
   ^      ^
   |      |
 first   rest

Where first points to the first node and rest points to the node next to first . first指向第一个节点,其余指向first节点旁边的节点。

Since the list is not empty and list does not contain one node we make recursive call to reverse to reverse the list pointed to by rest . 由于列表不为空且列表不包含一个节点,因此我们进行递归调用以reverse以反转rest指向的列表。 This is how the list looks after reversing the rest of the list: 这是反转列表其余部分后列表的显示方式:

   1  ->  2  <-  3  <-  4
   ^      |             ^
   |     NULL           |
 first                 rest

As seen rest now points to the reversed list which has 4 at the beginning and 2 at the end of list. 现在看到rest指向反向列表,其中列表开头有4 ,列表末尾有2 The next pointer of node 2 is NULL . 节点2的下一个指针是NULL

Now we need to append the first node to the end of the reversed-rest list. 现在我们需要将第一个节点附加到reverse-rest列表的末尾。 To append anything to the end of the list we need to have access to the last node of the list. 要将任何内容附加到列表的末尾,我们需要访问列表的最后一个节点。 In this case we need to have access to the last node of the reversed-rest list. 在这种情况下,我们需要访问reverse-rest列表的最后一个节点。 Look at the diagram, first -> next points to the last node reversed-rest list. 查看图表, first -> next指向最后一个节点的反向休息列表。 Therefore first -> next -> next will be next pointer of the last node of the reversed-rest list. 因此, first -> next -> next将是reverse-rest列表的最后一个节点的下一个指针。 Now we need to make it point to first so we do: 现在,我们需要让它指向first ,所以我们做的:

first -> next -> next = first;

After this step the list looks like: 在此步骤之后,列表如下所示:

   1  <-  2  <-  3  <-  4
   ^  ->                ^
   |                    |
 first                 rest

Now the next field of the last node of the list must be NULL . 现在,列表最后一个节点的next字段必须为NULL But it is not the case now. 但现在情况并非如此。 The next field of the last node ( node 1 ) is pointing to the node before it ( node 2 ). 最后一个节点(节点1 )的next字段指向它之前的节点(节点2 )。 To fix this we do: 要解决这个问题,我们会:

first -> next = NULL;

After this the list looks like: 在此之后,列表看起来像:

NULL <- 1  <-  2  <-  3  <-  4
        ^                    ^
        |                    |
      first                 rest

As seen the list is now correctly reversed with rest pointing to the head of the reversed list. 如图所示,现在正确地反转列表,其中rest指向反转列表的头部。

We need to return the new head pointer so the that changes are reflected in the calling function. 我们需要返回新的头指针,以便更改反映在调用函数中。 But this is a void function and head is passed as double pointer so changing the value of *head will make the calling function see the changed head: 但这是一个void函数, head作为双指针传递,因此更改*head的值将使调用函数看到更改的头:

*head = rest;

The rest isn't 2 , it's 2 -> 3 -> 4 , which gets reversed recursively. 其余的不是2 ,它是2 -> 3 -> 4 ,递归反转。 After that we set *head_ref to rest , which is now (recursively reversed!) 4 -> 3 -> 2 . 之后我们将*head_ref设置为rest ,现在(递归反转!) 4 -> 3 -> 2

The important point here is that although both first and rest have the same type, ie node* , they are conceptually fundamentally different: first points to one single element, while rest points to a linked list of elements. 这里重要的一点是,虽然firstrest都有相同的类型,即node* ,但它们在概念上基本上是不同的: first指向一个单独的元素,而rest指向一个链接的元素列表 This linked list is reversed recursively before it gets assigned to *head_ref . 在将链接列表分配给*head_ref之前,该链接列表*head_ref递归方式反转。

I recently wrote a recursive method for reversing a linked list in ruby. 我最近编写了一个用于在ruby中反转链表的递归方法。 Here it is: 这里是:

def reverse!( node_1 = @head, node_2 = @head.link )
    unless node_2.link 
        node_2.link = node_1
        @head = node_2
        return node_1
    else 
        return_node = reverse!(node_1.link, node_2.link)
        return_node.link = node_1
        node_1.link = nil
        return node_1
    end
    return self
end

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM