【问题标题】:Why does the following code to insert a node at the end of a singly linked list does not work?为什么以下在单链表末尾插入节点的代码不起作用?
【发布时间】:2016-06-27 10:57:34
【问题描述】:

下面是C语言代码:

函数调用:

insert(&head,value);

void insert(struct node** headref,int value)
{
    struct node* head = (*headref); 

    while( head!=NULL )
     {

        head= head->link;
     }

    struct node* new_node=(struct node*)malloc( sizeof(struct node) );

    new_node->data=value;
    new_node->link=NULL;

    head=new_node;  
}

【问题讨论】:

  • 列表应该如何知道新元素?您必须将列表中最后一项的link 成员设置为指向新元素。一旦head 变为NULL,您就失去了需要设置link 成员的元素。更好的循环终止条件是while (head->link != NULL)
  • 我建议你永远不要移动你的head,因为不推荐!它是一个引用指针,应该始终指向链表中的起始节点。请改用其他指针。

标签: c data-structures linked-list singly-linked-list


【解决方案1】:

您需要将列表的最后一个元素链接到new_node,否则您将失去列表的链接性(如果有这样的词:))。您需要在循环中存储 2 个指针 - head,您已经拥有这些指针和一个指向前一个元素(头部之前的元素)的指针。请特别注意您有空列表的情况!

【讨论】:

    【解决方案2】:
      while( head!=NULL )
     {
        head= head->link;
     }
    

    在这个循环结束时head 将是NULL。您可能想在最后一个节点停止

      while( head->link!=NULL )
     {
        head= head->link;
     }
    

    然后做类似的事情

    head->link = new_node;
    

    现在,如果列表为空,您必须格外小心,因为如果 head=NULLhead->link 将抛出错误。 您可以像这样在开头打勾

    //allocate new_node here
    if(head==NULL)
    {
       *headref = new_node; //Note only in this case would headref ever change
    }
    

    【讨论】:

      【解决方案3】:

      您正在用 new_node 替换最后一个节点 head,这不是预期的。循环到最后一个节点,使head->link指向new_node,如下图:

      insert(&head,value);
      
      void insert(struct node** headref,int value)
      {
          struct node* head = (*headref); 
      
          while( head->link !=NULL )
           {
      
              head= head->link;
           }
      
          struct node* new_node=(struct node*)malloc( sizeof(struct node) );
      
          new_node->data=value;
          new_node->link=NULL;
      
          head->link=new_node;  
      }
      

      【讨论】:

      • 所以您要在head 节点之后插入该元素?我说的对吗?
      • yes.. 在while 循环结束时,head 节点将指向链表的最后一个节点。而new_node 将插入到head 节点之后。
      • 好的!让我们假设有 5 个元素,head 指向第一个元素。在插入new_node 之后(根据你的逻辑在head 之后),new_node 将指向哪个节点?我看到你的new_node->link=NULL。我想会有一些效果!
      • 在我的示例中有一个while 循环,我通过执行head=head->link; 遍历到列表末尾,然后只插入new_node
      • 如果列表为空head->link 将是NULL->link。这将失败
      【解决方案4】:

      逻辑错误。试试这个。

      struct node* new_node=(struct node*)malloc( sizeof(struct node) );
      new_node->data=value;
      new_node->link=NULL;
      
      if (!head)
      {
         head = new_node;
         return;
      }
      
      // Use for or while loop as below.
      // 1. for(;head->link;head=head->link); 
      // or  
      /* 2. */
      while (head->link)
      {
          head = head->link;
      }
      head->link = new_node;
      

      最好用一些有意义的名字重命名头部!

      【讨论】:

      • 你没有反映headref的变化
      【解决方案5】:

      在函数中局部变量head被赋值给新创建的节点。退出函数后,该局部变量将被销毁,原始列表不会改变。

      还有这个循环

      while ( head != NULL )
      {
          head = head->link;
      }
      

      没有意义。其实可以代替

      head = NULL;
      

      该功能可以如下面的演示程序所示。

      #include <stdio.h>
      #include <stdlib.h>
      
      struct node
      {
          int data;
          struct node *link;
      };
      
      int insert( struct node **head, int value )
      {
          struct node *tmp = malloc( sizeof( struct node ) );
          int success = tmp != NULL;
      
          if ( success )
          {
              tmp->data = value;
              tmp->link = NULL;
      
              while ( *head ) head = &( *head )->link;
      
              *head = tmp;
          }
      
          return success;
      }
      
      void display( struct node*head )
      {
          for ( ; head != NULL; head = head->link ) printf( " %d", head->data );
      }
      
      int main( void ) 
      {
          const int N = 10;
          struct node *head = NULL;
      
          int i = 0;
          while ( i < N && insert( &head, i ) ) i++;
      
          display( head );
      
          return 0;
      }
      

      它的输出是

       0 1 2 3 4 5 6 7 8 9
      

      【讨论】:

        猜你喜欢
        • 2015-12-14
        • 2011-08-13
        • 2020-11-15
        • 2021-05-23
        • 2015-02-08
        • 1970-01-01
        相关资源
        最近更新 更多