简体   繁体   English

在c中递归地反转链表

[英]Reversing a linkedlist recursively in c

The following code works fine when head is sent as a parameter to it.当 head 作为参数发送给它时,以下代码工作正常。 As I am new to C, I couldn't understand how it works.由于我是 C 的新手,我无法理解它是如何工作的。 Help me out please.请帮帮我。

struct node *recursiveReverseLL(struct node *list)
{
    struct node *revHead;
    if (list == NULL || list->link == NULL)
    {
        return list;
    }

    revHead = recursiveReverseLL(list->link);
    list->link->link = list;
    list->link = NULL; 

    return revHead;
}

I dont know how the links are provided using those recursive calls.我不知道如何使用这些递归调用提供链接。 ie) if the links are as,即)如果链接是,

1 -> 2 -> 3 -> 4 

then hw is it changed as,那么 hw 被更改为,

4 -> 3 -> 2 -> 1

The general recursive algorithm for this is:通用的递归算法是:

  1. Divide the list in 2 parts - first node and rest of the list. Divide名单中2部分-第一节点和休息之列。
  2. Recursively call reverse for the rest of the linked list.对链表的rest递归调用 reverse 。
  3. Link rest to first .rest链接到first
  4. Fix head pointer修复head指针

Here is the code with inline comments:这是带有内联注释的代码:

struct node* recursiveReverseLL(struct node* first){

   if(first == NULL) return NULL; // list does not exist.

   if(first->link == NULL) return first; // list with only one node.

   struct node* rest = recursiveReverseLL(first->link); // recursive call on rest.

   first->link->link = first; // make first; link to the last node in the reversed rest.

   first->link = NULL; // since first is the new last, make its link NULL.

   return rest; // rest now points to the head of the reversed list.
}

I hope this picture will make things clearer:我希望这张图能让事情更清楚:

图像
(source: geeksforgeeks.org ) (来源: geeksforgeeks.org
. .

Alternate solution :替代解决方案:

struct node *head;
void reverse(struct node *prev, struct node *cur)
{
   if(cur){
      reverse(cur,cur->link);
      cur->link = prev;
    }
    else{
      head = prev;
    }
}

In main, call reverse(NULL,head);在 main 中,调用 reverse(NULL,head);

/* Reverses a linked list, returns head of reversed list
*/
NodePtr reverseList(NodePtr curr) {
    if (curr == NULL || curr->next == NULL) return curr; // empty or single element case

    NodePtr nextElement = curr->next;
    curr->next = NULL;
    NodePtr head = reverseList(nextElement);
    nextElement->next = curr;
    return head;
}

Another solution:另一种解决方案:

struct node *reverse_recur(struct node *temp)
{
    if(temp->link==NULL)
    {
        return temp;
    }

    struct node *temp1=temp->link;

    temp->link=NULL;

    return (reverse_recur(temp1)->link=temp);

}

Let the linked list be 1-> 2 -> 3 ->4让链表为 1-> 2 -> 3 -> 4

the function in c is-- c中的函数是--

struct linked_node * reverse_recursive(struct linked_node * head)
{
struct linked_node * first;/*stores the address of first node of the linked
list passed to function*/
struct linked_node * second;/* stores the address of second node of the
linked list passed to function*/
struct linked_node * rev_head;/*stores the address of last node of initial 
linked list. It also becomes the head of the reversed linked list.*/
//initalizing first and second
first=head;
second=head->next;
//if the linked list is empty then returns null
if(first=NULL)
   return(NULL);
/* if the linked list passed to function contains just 1 element, then pass
address of that element*/
if(second==NULL)
   return(first);
/*In the linked list passed to function, make the next of first element 
 NULL. It will eventually (after all the recursive calls ) make the
 next of first element of the initial linked list NULL.*/
first->next=NULL;
/* storing the address of the reverse head which will be passed to it by the
 condition if(second==NULL) hence it will store the address of last element
 when this statement is executed for the last time. Also here we assume that 
the reverse function will yield the reverse of the rest of the linked 
list.*/
rev_head=reverse(second);
/*making the rest of the linked list point to the first element. i.e. 
 reversing the list.*/
second->next=first;

/*returning the reverse head (address of last element of initial linked 
list) . This condition executes only if the initial list is 1- not empty 
2- contains more than one element. So it just relays the value of last 
element to higher recursive calls.  */
return(rev_head);
}

now running the function for the linked list 1-> 2-> 3 -> 4现在运行链表 1-> 2-> 3 -> 4 的函数

  • inside reverse(&1) the code runs until rev_head=reverse(&2);在 reverse(&1) 中,代码运行直到 rev_head=reverse(&2); // here &1 is address of 1. // 这里 &1 是 1 的地址。

list of function is功能列表是
1(first)->2(second) -> 3 -> 4 1(第一)-> 2(第二)-> 3 -> 4

  • inside reverse(&2) code runs until rev_head=reverse(&3);内部 reverse(&2) 代码运行直到 rev_head=reverse(&3); list of function功能列表
    2(first)->3 (second)-> 4 2(第一)-> 3(第二)-> 4

  • inside reverse(&3) code runs until rev_head=reverse (&4);内部 reverse(&3) 代码运行直到 rev_head=reverse (&4); list if function列出 if 函数
    3(first)-> 4 (second) 3(第一)-> 4(第二)

  • inside reverse(&4) terminating condition second==NULL is true so return is executed and address of 4 is returned.内部 reverse(&4) 终止条件 second==NULL 为真,因此执行 return 并返回 4 的地址。

list of function功能列表

4(first)-> NULL(second) 4(第一)-> NULL(第二)

  • back to reverse(&3) list of function is返回 reverse(&3) 函数列表是
    NULL<-3(first) 4 (second) NULL<-3(第一) 4(第二)
    and the value of rev_head=&4 which was returned以及返回的 rev_head=&4 的值

after executing second->next=first;执行 second->next=first 后; list becomes列表变成

NULL<- 3(first) <-4 (second) NULL<- 3(第一)<-4(第二)

return (rev_head );返回 (rev_head); is executed which passes &4 because rev_head=&4执行通过 &4 因为 rev_head=&4

  • back to rev(&2)回到 rev(&2)

list in function is功能列表是

NULL<-2(first) 3(second)<-4 NULL<-2(第一) 3(第二)<-4

and rev_head is &4 which was returned by rev(&3)并且 rev_head 是 &4 由 rev(&3) 返回

after executing second->next=first , list becomes执行 second->next=first 后,列表变为

NULL<-2(first)<-3(second)<-4 NULL<-2(第一)<-3(第二)<-4

return(rev_head);返回(rev_head); is executed which returns &4 to rev(&1);执行返回 &4 到 rev(&1);

  • back to rev(&1)回到 rev(&1)

list in function is功能列表是

NULL<-1(first) 2(second)<-3<-4 NULL<-1(第一) 2(第二)<-3<-4

and value of rev_head is &4 which was passed by reverse(&3) rev_head 的值是 &4,由 reverse(&3) 传递

now second->next =first is executed and list becomes现在 second->next =first 被执行并且列表变成

NULL<-1(first) <- 2(second)<-3<-4 NULL<-1(第一)<- 2(第二)<-3<-4

return(rev_head);返回(rev_head); is executed // rev_head=&4 which was returned by reverse(&2) and the value of rev_head is passesd to the main function.执行 // rev_head=&4 由 reverse(&2) 返回,rev_head 的值被传递给主函数。

hope this helps.希望这可以帮助。 It took me quite a lot of time to understand this and also to write this answer.我花了很多时间来理解这一点并写下这个答案。

    To fix head also:

void reverse_list_recursive_internal (struct list **head, struct list *node)
{
    /* last node, fix the head */
    if (node->next == NULL) {
        *head = node;
        return; 
    }
    reverse_list_recursive_internal(head, node->next);
    node->next->next = node;
    node->next = NULL;
}

void reverse_list_recursive (struct list **head)
{
    if (*head == NULL) {
        return;
    }
    reverse_list_recursive_internal(head, *head);
}

This is a beautiful approach one can follow to reverse SLL recursively:这是一种可以用来递归反转 SLL 的漂亮方法:

1.    struct node* head; // global head
2.    void rec_reverse(struct node* prev, struct node* cur)
3.    {
4.        if (cur)
5.        {
6.            rec_reverse(cur, cur->next);
7.            cur->next = prev;
8.        }
9.        else
10.            head = prev;
11.    }

Call the function this way:以这种方式调用函数:

rec_reverse(NULL, head);

Approach:方法:

  • Calling the function recursively (line 6) we go to the last node of linked list.递归调用该函数(第 6 行),我们转到链表的最后一个节点。
  • Then we update head with the address of the last node (line 10).然后我们用最后一个节点的地址更新 head(第 10 行)。
  • Finally, we point link of each node to its previous node (line 7).最后,我们将每个节点的链接指向其前一个节点(第 7 行)。

It seems to me that nobody has suggested an algorithm that is tail-recursive .在我看来,没有人提出过尾递归算法。 In principle, a tail-recursive algorithm can be compiled without a stack (provided that the compiler is smart enough), thus producing code that consumes less memory.原则上,尾递归算法可以在没有堆栈的情况下进行编译(前提是编译器足够聪明),从而生成占用更少内存的代码。

Assume TList is a custom data-type for single-linked list, it is a pointer to a structure that as a link field for accessing the next element in the list.假设TList是单链表的自定义数据类型,它是一个指向结构的指针,作为访问列表中下一个元素的link字段。

The algorithm is the following:算法如下:

``` ``

TList reverse_aux(TList l, TList solution) {
    if (l == NULL) {
        return solution;
    } else {
        TList tmp = l->link;
        l->link = solution;
        return reverse_aux(tmp, l);
    }
}

TList reverse(TList l) {
    return reverse_aux(l, NULL);
}

``` ``

ll *rev_list(ll *prev, ll *cur)
{
    if (!cur) {
        return prev;
    }

    ll *tmp = cur;
    cur = cur->next;
    tmp->next = prev;
    prev = tmp;
    return rev_list(prev, cur);
}

Find complete code : https://github.com/vijaythreadtemp/Data-Structures-And-Algorithms/blob/master/rev_link_list_rec.cxx查找完整代码: https : //github.com/vijaythreadtemp/Data-Structures-And-Algorithms/blob/master/rev_link_list_rec.cxx

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

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