【问题标题】:List reverse-printing列表反向打印
【发布时间】:2017-11-16 07:55:33
【问题描述】:

列表的每个节点与数据一起保存连续节点的地址。这就是递归运作良好的原因,如下例所示:它接受一个输入,例如123456,然后将其打印为列表6 -> 5 -> 4 -> 3 -> 2 -> 1 -> NULL.

/* Structure types ----------------------------------------------*/

typedef int data;
struct list_element {
   int                     data;
   struct list_element     *next;
};
typedef struct list_element ELEM;
typedef ELEM *LINK;


/* Recursive list create and list print---------------*/

LINK create_list(int n) {
   if (n == 0) {
      return NULL;
   }
   else {
      LINK head = (LINK) malloc(sizeof(ELEM));
      head -> data = n % 10;
      head -> next = create_list(n / 10);
      return head;
   }
}

void print_list(LINK head) {
   if(head == NULL)
      printf("NULL\n");
   else {
      printf("%d -> ", head -> data);
      print_list(head -> next);
   }
}

/* MAIN ---------------------------------------------------------*/

int main(int argc, char *argv[]) {
   int n; LINK ls;
   printf("\nType an integer:\n");
   scanf("%d", &n);
   ls = create_list(n);
   print_list(ls);
   return 0;
}

节点不保存其前一个邻居的地址。从这个考虑问题:

如何从它的 last 节点打印一个列表,以便拥有 NULL -> 6 -> 5 -> 4 -> 3 -> 2 -> 1

Reversing a linkedlist recursively in c 问题的答案实际上指向了一个稍微不同的问题。他们的目标是扭转名单本身。我不打算改变列表中数据的顺序。

【问题讨论】:

  • 点赞print_list(head -> next); printf(" -> %d", head -> data);
  • 注意:对于小型作业,递归很好,但当递归数量可能很大时,您通常会希望坚持程序解决方案。为什么?因为每个递归都是一个单独的函数调用,它为不同且单独的堆栈帧保留内存以处理该函数本地的所有变量。如果你递归 100,000 次,那就是 100,000 次单独的函数调用。随着递归数量的持续增长,这真的可以加起来。
  • 为什么不在这个问题上使用迭代?如果您只搜索递归,那么好的也是唯一的方法是反转列表(如果需要,创建一个新列表)并打印它。没有神奇的解决方案可以在不反转列表的情况下使其尾递归。

标签: c recursion linked-list


【解决方案1】:

您只需更改打印调用的顺序即可。如果您先打印列表的其余部分,则顺序将颠倒。

print_list(head -> next);
printf("%d -> ", head -> data);

这真的是你如何浏览列表的问题。

【讨论】:

    【解决方案2】:

    您只需要交换 printf 语句和递归调用。

    void print_list(LINK head){ 
         if(head == NULL)
              printf("NULL\n"); 
         else{
              print_list(head -> next);
              printf("%d -> ", head -> data);
          }
     } 
    

    那么最后一次递归调用中的printf语句会先执行,其他的会先执行。

    【讨论】:

      【解决方案3】:

      当您的列表变得非常大时,递归将无济于事,因为您最终将运行我们的堆栈空间。

      如果是要求,您可以反向打印列表,则必须调整数据结构(和算法)以实现要求而不会用完堆栈空间.

      简而言之,你必须实现一个双向链表,即不仅有next 成员,而且还有prev 成员。

      【讨论】:

      • 不一定——一个可以先还原列表,然后再还原它,打印出每个元素——所有元素都没有递归...注意:我不是说它是更好,我只是说:一个人没有“必须”...
      • @Aconcagua,确实如此。我的要求不够具体,应该包括“不修改列表[因为其他任务可能正在对其进行操作]”。
      【解决方案4】:

      在将 printf 语句压入堆栈时,只需遍历到最后一个节点。到达列表末尾后,堆栈将开始展开,您的打印函数将被调用。

      void print_list_reverse(LINK head){                                                                                                                                                                                                             
          if(head == NULL)                                                                                                                                                                                                                        
                  printf("NULL -> ");                                                                                                                                                                                                             
          else{                                                                                                                                                                                                                                   
                  print_list_reverse(head -> next);                                                                                                                                                                                               
                  printf("%d -> ", head -> data);                                                                                                                                                                                                 
          }                                                                                                                                                                                                                                       
      
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2014-04-21
        • 1970-01-01
        • 2012-04-08
        • 2014-11-27
        • 1970-01-01
        • 2012-11-19
        • 2020-09-29
        • 1970-01-01
        相关资源
        最近更新 更多