【问题标题】:reversing linked list反向链表
【发布时间】:2011-05-03 23:50:14
【问题描述】:

我正在尝试使用递归来反转链表并为其编写以下代码。列表的开头是列表的开头。

 node *reverse_list_recursive(node *list)
 {
      node *parent = list;
      node *current = list->next;

      if(current == NULL)
       return parent;

      else
       {
           current = reverse_list_recursive(current);
           current->next = parent;
           printf("\n %d  %d \n",current->value,parent->value);
           return parent;
       }

  }

我可以看到所有链接都被反转了。但是,当我尝试显示时,我得到了无限的数字打印。当我尝试反转列表中第一个数字的链接时,我怀疑出现错误。

我做错了什么?

【问题讨论】:

标签: c data-structures linked-list


【解决方案1】:

你需要将新尾部(即旧头部)的下一个指针设置为 NULL

编辑:这是一个递归版本

node *reverse_list_recursive(node *list)
  {
      node *parent = list;
      node *child = list->next;
      node *new_head;


    if (child == NULL)
          return parent ;  /* new head */

    new_head = reverse_list_recursive(child)
    child->next = parent; /* Old parent is the new child of the old child when reversed */
    parent->next = NULL; /* might be tail, will be overwritten after we return if we're not at the top level */
    return new_head;
}

【讨论】:

  • 是的......我有点困惑如何做到这一点......你能给我修改一下吗>?
【解决方案2】:

到达列表末尾时,返回最后一个节点。然后将最后一个节点的下一个值分配给它自己,因此您会产生不一致。如果 current 为 NULL,则返回 NULL,如果返回 NULL,则简单地忽略其余代码。

【讨论】:

    【解决方案3】:

    您忘记更新链表上第一项的next 成员。在递归调用前添加parent->next = NULL;

    【讨论】:

      【解决方案4】:

      current = reverse_list_recursive(current); 行之后,您将新的列表头存储在当前,所以current->next = parent; 是错误的。新的current 是新的列表头,但您需要访问新的列表尾,即旧的current

      node* newhead = reverse_list_recursive(current);
      current->next = parent;
      printf("\n %d  %d \n",current->value,parent->value);
      return newhead;
      

      【讨论】:

      • 修改后得到相同的输出
      【解决方案5】:

      我可以看到的一些问题:

      • 你需要使下一个指针 新的最后一个节点 NULL。
      • 如果我这样做,你现有的功能将会崩溃 最初将 NULL 传递给它。

      【讨论】:

        【解决方案6】:

        我没有看到递归的好处,迭代也可以。自从我编写 C 语言以来,它已经永远存在了(并且没有简单的方法来测试以下语法错误......或 cringe 核心转储,但你明白了)。

        node *reversed_list(node *list) {
            node *fwd=list;//Purely for readability
            node *last=null;
            node *next=null;
            node *rev=null;
            do {
                //Cache next
                next=fwd->next;
                //Set current
                rev=fwd;
                //Reset next to point back
                rev->next=last;
                //Update last
                last=fwd;
                //Forward ptr;
                fwd=next;
            } while (fwd!=null);
            return rev;
        }
        

        很确定你的*list 在你调用它之后是没用的,因为它现在指向列表中包含->next=null 的最后一个元素,可以只更新它而不是返回指针。

        更新(用于递归解决方案)

        正如其他人所说,你的新尾巴搞砸了(指向最后一个元素,但应该指向 null)......并且你没有返回正确的头部,你返回了第二个元素。使用您的算法考虑列表a->b->null

        p=a,
        c=b;
        c=
           p=b
           c=null
           return b; //b->null
        c=b
        c->next=a //b->a
        return a; //a->b, b->a, a returned
        //But what you wanted is a->null, b->a, and b returned
        

        以下更新的代码将修复:

        node *reverse_list_recursive(node *list)
          {
              node *parent = list;
              node *current = list->next;
        
              if(current == NULL)
               return parent;
        
              else
               {
                   current = reverse_list_recursive(current);
                   current->next = parent;
                   parent->next=null; //Fix tail
                   printf("\n %d  %d \n",current->value,parent->value);
                   return current; //Fix head
               }
        
          }
        

        有列表a->b->null:

        p=a,
        c=b;
        c=
           p=b
           c=null
           return b; //b->null
        c=b
        c->next=a //b->a
        p->next=null //a->null
        return b; // b->a->null
        

        【讨论】:

        • 很公平{下次可能要提到这个问题},我添加了更新的递归方法(新头和新尾的两个小改动)
        【解决方案7】:

        假设我有一个链表:

         ----------      ----------      ----------      ---------- 
        |  1  |    |--->|  2  |    |--->|  3  |    |--->|  4  |    |--->NULL
         ----------      ----------      ----------      ---------- 
        

        您的代码将其转换为:

           ----------------------          ----------------------
           |                    |          |                    |
           v                    |          v                    |
         ----------      ----------      ----------      ----------
        |  1  |    |--->|  2  |    |    |  3  |    |    |  4  |    | 
         ----------      ----------      ----------      ---------- 
                           ^                    |
                           |                    |
                           ----------------------
        

        请注意,第一个元素仍然指向 2。

        如果你在前两行后面加上parent->next = NULL,你会得到:

                   ----------------------          ----------------------
                   |                    |          |                    |
                   v                    |          v                    |
                 ----------      ----------      ----------      ----------
        NULL<---|  1  |    |    |  2  |    |    |  3  |    |    |  4  |    | 
                 ----------      ----------      ----------      ---------- 
                                   ^                    |
                                   |                    |
                                   ----------------------
        

        这实际上是正确的结构。

        完整代码为:(每次递归调用只需要打印当前值)

        node *reverse_list_recursive(node *list)
          {
              node *parent = list;
              node *current = list->next;
        
              if(current == NULL)
               return parent;
        
              else
               {
                   current = reverse_list_recursive(current);
                   parent->next = NULL;
                   current->next = parent;
                   printf("\n %d \n",current->value);
                   return parent;
               }
        
          }
        

        【讨论】:

          【解决方案8】:

          这里是递归代码来反转一个链表。

          list * reverse(list * head)
          {
              if( head == NULL || head -> link == NULL )
                  return head;
              list *node = reverse( head- > link );
              head -> link -> link = head;
              head -> link = NULL;
              return node;
          }
          

          【讨论】:

            【解决方案9】:

            上面的几个版本不能像 OP 想要的那样工作,所以这是我的递归版本测试良好:

            node * reverseRecursive(node *p,node **head)
            {
                 if(p->next == NULL)
                 {
                     *head = p;
                      return p;
                 }
                 node *before;
                 before = reverseRecursive(p->next,head);
                 before->next = p;
                 p->next = NULL;
                 return p;
            }
            
            //call from main
            node*head; 
            //adding value
            //assuming now head is now 1->2->3->4->NULL
            node* newHead;
            reverseRecursive(head,&newHead);
            //now now newHead is now 4->3->2->1->NULL
            

            【讨论】:

              【解决方案10】:

              不同的代码如下:

              '

              #include <stdio.h>
              #include <stdlib.h>
              #pragma warning(disable:4996)
              
              struct Node {
                  int data;
                  struct Node* next;
              };
              typedef struct Node node;
              
              node* dogrusıralama(node* r)
              {
                  for (int i = 0; i < 6; i++)
                  {
                      printf("%d", r->data);
                      r = r->next;
                      printf("\n");
                  }
              }
              node *terssıralama(node* r)
              {
                      node* iter;
                      iter = r;
                      node* temp;
                      temp = r;
                      node* temp2;
                      temp2 = r;
                      int a = 4;
                      for (int k = 0; k < 5; k++)
                      {        
                          temp2 = temp2->next;
                      }
                      for (int j = 0; j < 5; j++)
                      {
                          int i = a;
                          for (; i > 0; i--)
                          {
                              temp = temp->next;
                      
                          }
                          a--;
                          iter = temp;
                          iter->next->next = iter  ;
                          temp = r;
                      }
                      temp->next = NULL;
                      return temp2;
              }
              int main() {
                  node* dugum;
                  node* dugum2;
                  node* dugum3;
                  node* dugum4;
                  dugum = (node*)malloc(sizeof(node*));
                  dugum2 = dugum;
                  for (int i = 0; i < 5; i++)
                  {
                      dugum2->next = NULL;
                      dugum2->next = (node*)malloc(sizeof(node*));
                      dugum2->data = i;
                      dugum2 = dugum2->next;
                  }
                  dugum4 = dugum;
                  dogrusıralama(dugum);
                  dugum3 = terssıralama(dugum);
              
                  for (int i = 0; i < 6; i++)
                  {
                      printf("\n");
                      printf("%d", dugum3->data);
                      dugum3 = dugum3->next;
                  }
                   
              } '
              

              【讨论】:

                猜你喜欢
                • 2016-08-29
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2012-06-25
                • 2011-12-19
                • 2013-03-04
                相关资源
                最近更新 更多