简体   繁体   English

使用C中的递归来反向链接列表

[英]Reverse a linked list using recursion in C

I was trying the reversal of a linked list using recursion. 我正在尝试使用递归来反转链表。 I viewed the sample program in geeksforgeeks website. 我在geeksforgeeks网站上查看了示例程序。 They had a good explanation . 他们有一个很好的解释 But I could not understand what the *headref will hold on every stack unwinding. 但是我不明白* headref在展开的每个堆栈中将保存什么。 Doesnt it hold the next address during every stack unwinding, if its that way then how does the rest value is same during all the stack unwinding calls. 在每次堆栈展开期间它是否保持下一个地址,如果是这样的话,那么在所有堆栈展开调用期间其余值是如何相同的。 The first value gets changed during the stack unwinding and so is the rest value. 在堆栈展开期间,第一个值更改,其余值也更改。 Why doesnt rest value is not changed when the first value is changed for every stack unwinding. 为每个堆栈展开更改第一个值时,为什么不会更改静止值。 Please help to understand. 请帮忙理解。

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;  

    /* reverse the rest list and put the first element at the end */
    recursiveReverse(&rest);
    first->next->next  = first; 

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

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

Once the 'rest list' got reversed in the recursive step, its first item, pointed at by rest , became its last item, so the previous 'first' gets appended after that. 一旦'rest list'在递归步骤中被反转,它的第一个项目(由rest指向)成为它的最后一个项目,因此之前的'first'会之后被追加。 Then it is the last item, so its next member becomes NULL . 然后它是最后一项,因此它的next成员变为NULL Finally we return the new head through the call parameter. 最后,我们通过call参数返回新头。

The head is changed in every recursive call. 每次递归调用都会更改头部。

Each recursive call takes the sublist [k,n] , where k is the previously parsed elements. 每个递归调用都采用子列表[k,n],其中k是先前解析的元素。

The first entry is [0,n] , which in the code above is [first,rest] . 第一个条目为[0,n],在上面的代码中为[first,rest]。

Initially links are from first to rest. 最初链接是从第一个到休息。 Before each recursive call rest gets linked to first having a temporary loop inside the list (first points to rest, rest points to first). 在每个递归调用中,rest在列表中首先具有一个临时循环之前被链接(第一个指向rest,rest指向第一个)。

Then , after the recursive call returns, the loop is killed by removing the first to rest link and putting first to be rest's next . 然后,在递归调用返回之后,通过删除第一个为rest的链接并将第一个为rest的next杀死循环。 (basically keeping only the inverse order). (基本上只保持相反的顺序)。

As any single linked list, the last element needs to have no childern, and right now first is the last element, so first->next becomes null. 与任何单个链表一样,最后一个元素不必具有子元素,现在第一个是最后一个元素,因此first-> next变为null。

The new head of the list is the last element, which in this case will be rest , which gets passed on from the deepest recursion upwards. 列表的新头是最后一个元素,在这种情况下将是rest,它从最深的递归向上传递。

This algorithm is so much faster and easier to implement with an iterative approach. 使用迭代方法可以更快,更轻松地实现此算法。

Problem of such algorithm is memory consumption required by recursive calls. 这种算法的问题是递归调用所需的内存消耗。

You have one parameter pointer and two var pointer, each call that goes on top of the memory stack. 你有一个参数指针和两个var指针,每个调用都在内存堆栈的顶部。 But it is the reason it works and the var is not changed. 但这是它工作的原因,并且var没有改变。 It does not reference the same memory area. 它不引用相同的内存区域。

You can note that an iterative approch is faster and easier in fact. 您可以注意到迭代的approch实际上更快更容易。

void iterativeReverse(struct node** head_ref) {
    struct node *prev=NULL, *next;
    while (*head_ref) {
       next=*head_ref->next;
       *head_ref->next=prev;
       prev=*head_ref;
       *head_ref=next;
    }
    *head_ref=prev;
}

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

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