递归反向链表

时间:2019-06-01 12:13:18

标签: c recursion linked-list reverse singly-linked-list

我很难理解此递归代码的工作原理,我已经制作了图纸并通过gdb运行了代码。

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 element on the end of the list
  first->next = NULL;

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

我了解到,在构建递归调用堆栈时,一旦列表仅包含{3},空的休息基本情况if (rest == NULL)的第一个是true时间。


此后,递归调用堆栈开始中断,并以{2,3},

首次命中first->next->next = first;

在执行此行之前,在gdb中输出:

(gdb)p *first
{data = 2, next = 0x1003001f0}

(gdb) p *rest
{data = 3, next = 0x0} 

执行此行后,

(gdb) p *rest
{data = 3, next = 0x1003000a0}

第二次继续执行代码以击中first->next->next = first;

(gdb) p **head_ref
{data = 1, next = 0x1003000a0}

(gdb) p *rest
{data = 3, next = 0x1003000a0} // expected p *rest to be 2

在这里,我期望本地指针rest指向节点2,因为在建立递归调用栈时,**headRef指向节点1并在行rest = first->next;之后被执行{ {1}}指向节点2。

执行rest之后,*headRef = rest;是否应该指向节点2?

怎么会丢失本地状态,而其余状态指向节点3?

2 个答案:

答案 0 :(得分:2)

让我们假设您有一个列表,其余部分已经被撤消。

在反转其余部分之前,列表具有此结构

first -> first_of_rest -> second_of_rest->...->nth_of_rest->nullptr

反转其余部分后,您将得到

first -> nullptr <- first_of_rest <- second_of_rest <-...<-nth_of_rest
         |                                                      |
         ________________________________________________________
                            the rest part of the list

因此,节点first的下一个数据成员指向first_of_rest,而节点first_of_rest的下一个数据成员“指向” nullptr。

因此,我们现在需要做的是将节点first_of_rest的数据成员设置为指向节点first

first->next->next = first;

abd将节点first的下一个数据成员设置为“指向” nullptr。

first->next = NULL;

因此我们有

nullptr <-first <- first_of_rest <- second_of_rest <-...<-nth_of_rest

答案 1 :(得分:0)

这是简化的伪代码。基本上是这样的:

RecursiveReverse(head):
    if head is empty:
        return
    RecursiveReverse(head->next)

    // When we come here, the whole list except the first
    // element has been reversed. So all that's left to do
    // is to reverse the final step

    head->next->next = head
    head->next = NULL

最重要的是在递归调用之后,除了第一个元素之外的整个列表都被反转了。