功能以相反的顺序打印链表

时间:2017-01-01 00:39:44

标签: c struct linked-list

我正在搜索如何打印链接列表的反向,我找到了这段代码

/* Function to reverse the linked list */
void printReverse(struct node* head)
{
    // Base case  
    if (head == NULL)
       return;

    // print the list after head node
    printReverse(head->next);

    // After everything else is printed, print head
    printf("%d  ", head->data);
}

问题是我不理解它到达指向NULL的最后一个指针的部分以及它如何逐个返回并以相反的顺序打印链接列表。

返回声明是什么让它一步一步走?或者是其他东西?请帮助,因为我不明白。

5 个答案:

答案 0 :(得分:2)

这是一个递归函数。递归函数通过将变量推送到执行堆栈来工作。执行顺序从堆栈中按下的顺序以相反的顺序弹出堆栈。这意味着最后一次执行首先打印,然后打印前一次执行,依此类推,直到printReverse的所有执行都打印出它们的值。

答案 1 :(得分:0)

这是一个递归函数;也就是说,它自称。

让我们使用序列example作为您的示例数据:

首次运行该功能时,它指向头部,头部是包含数据e的项目。它具有next属性,该属性是包含数据x的项目。因此,head == NULL评估False并且if语句不会触发。

然后,该函数调用自身的第二个副本,指向列表中的下一个项目 - 包含x的项目。这有一个next属性,它是包含a的项目。然后,该函数使用此项调用自身的第三个副本,依此类推,直到它到达最终的e,然后使用该项的next属性调用自身的副本 - 即比方说,它以NULL为输入自称。

该函数的副本然后return由于if语句 - 至关重要,它return到调用它的函数,在这种情况下是自身的副本级别以上。然后,此副本继续执行printf("%d ", head->data); - 在此情况下,它会打印e。然后它脱离了函数的主体,因此return s到调用它的函数。此函数的副本的head->data值为l,这将打印如上。因此,它然后通过备份链直到它进入原始函数调用,打印第一个e,然后返回到调用它的函数。

希望这是有道理的,我知道它并不是递归的最佳或最优雅的解释,但是如果这令人困惑地解释递归是如何起作用以及它是多么有用的话,那里有很多材料。 !

答案 2 :(得分:0)

使其反转的事情是printf()在递归调用后调用

您可以尝试在

中交换两个电话
void printNormal(struct node* head)
{
    // Base case  
    if (head == NULL)
       return;

    // Before all, we print this node info.
    printf("%d  ", head->data);

    // print the rest of the list after this node
    printReverse(head->next);

}

您将获得列表的正向打印。

如此评论 Base case 的任务是避免无限递归。列表的结尾是特殊的,我们可以检查输入printReverse()函数,这样我们就可以处理空列表的特殊情况,或者我们必须在每次调用时都这样做(然后我们应该把它放到在调用其中的函数之前进行检查,以及调用递归函数的代码(最好将其放在开头)。

答案 3 :(得分:0)

其他人已经解释了递归版本。我建议您以相反的顺序查看此迭代版本的打印链表。与递归版本相比,这更易于理解和实现,但是会增加时间复杂度。

    // To ease testing of code here linked list is created randomly of given size.
    #include<stdio.h>
    #include<cstdlib>
    #include<time.h>
    #define size 10 //Size of list
    struct node
    {
          int info;
          struct node * next;
    };
    typedef struct node* Node;       
    Node start;
    int main()
    {
       int i;
       srand(time(NULL));
       for(i=0;i<size;i++)
       {
          Node ptr;
          ptr=(Node)malloc(sizeof(node));
          ptr->info=rand()%100; //random list is created of given size.
          ptr->next=NULL;
          if(start==NULL)
              start=ptr;
          else
          {
               ptr->next=start;
               start=ptr;
          }
    }
    printf(" Traversal of Linked List in forward direction -\n");
    Node temp=start;
    while(temp!=NULL)
    {
        printf(" %d ",temp->info);
        temp=temp->next;
    }
    printf("\n Traversal of Linked List in backward direction -\n");
    Node ptr=NULL;
    while(ptr!=start)
    {
        temp=start;
        while(temp->next!=ptr)
        temp=temp->next;
        printf(" %d ",temp->info);
        ptr=temp;
    }
       return 0;
    }

有关更多详细信息,请访问- https://github.com/SahdevKansal02/Data-Structures-And-Algorithms.git

答案 4 :(得分:-1)

吉姆罗杰斯击中了头部的钉子。但是,你可以通过双重链接列表让自己的生活变得轻松。

因此,例如,您的条目(节点)具有分别指向上一个条目和下一个条目的前一个和下一个成员。那你就不需要更多的&#34;混淆&#34;代码不必要。