【问题标题】:Linked List Head Dynamic Allocation -- C链表头动态分配——C
【发布时间】:2016-05-22 06:18:18
【问题描述】:

我正在使用 C 语言进行一个小型学习项目,但在实现将保存数据集的第一个数据值的头节点时遇到了麻烦。我应该采用一个未排序的链表并使用它来实现一个排序的链表。它应该像下面的例子那样分成两个函数。

为堆上的头指针节点分配内存时出现了我的问题。使用 malloc 时,它似乎总是创建一个数据值为 0 的额外头节点(0 不在数据集中,但可能在)。

    struct node* create_sorted_list(struct node *head)
    {
       struct node * curr = head;
       struct node * sorted_head = malloc(sizeof(struct node));

       while(curr != NULL){
          add_item_sorted(sorted_head, curr->data);
          curr=curr->next;
       }   
       return sorted_head;
    }



    struct node* add_item_sorted(struct node *sorted_head, int data)
    {
       struct node * curr = sorted_head;
       struct node * newN;    
       while(curr->next != NULL){

          if(data > curr->next->data){
             curr=curr->next;
          }
          else{
             newN = malloc(sizeof(struct node));
             newN->data = data;
             newN->next = curr->next;
             curr->next = newN;
             return sorted_head; 
          }
       }   
       newN = malloc(sizeof(struct node));
       curr->next = newN;
       newN->data = data;
       return sorted_head;
    }



    int main(int argc, char *argv[])
    { 
        ......
        struct node * sorted_head = create_sorted_list(head);

        //head in this case comes from an unsorted linked list with the 
        //same data values. Using head linked list to make sorted_head.
    }

我的输出是这样的:0 -> 56 -> 35 -> 98 -> end
什么时候应该是:56 -> 35 -> 98 -> 结束

我有理由相信额外的节点是一对多调用 malloc 的结果,但是我找不到正确的解决方案。

感谢任何帮助。多谢你们。

【问题讨论】:

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


    【解决方案1】:

    函数create_sorted_list已经错了。

    一般head 可以等于NULL。但是函数中创建的sorted_head不等于NULL。

    struct node* create_sorted_list(struct node *head)
        {
           struct node * curr = head;
           struct node * sorted_head = malloc(sizeof(struct node));
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
           while(curr != NULL){
               //...
           }   
           return sorted_head;
        }
    

    此外,它的数据成员没有被初始化。因此,如果函数 add_item_sorted 将被调用该节点,那么访问数据成员 next 将导致程序的未定义行为。

      struct node* add_item_sorted(struct node *sorted_head, int data)
        {
           struct node * curr = sorted_head;
           struct node * newN;    
           while(curr->next != NULL){
                 ^^^^^^^^^^^
    

    至少你必须写

      while(curr != NULL){
          sorted_head = add_item_sorted(sorted_head, curr->data);
          ^^^^^^^^^^^^^^^ 
    

    函数可以写成如下演示程序所示

    #include <stdio.h>
    #include <stdlib.h>
    
    struct node
    {
        int data;
        struct node *next;
    };  
    
    struct node* add_item( struct node *head, int data )
    {
        struct node *tmp = malloc( sizeof( struct node ) );
        tmp->data = data;
        tmp->next = head;
    
        return tmp;
    }
    
    struct node* add_item_sorted( struct node *sorted_head, int data );
    
    struct node * create_sorted_list( struct node *head )
    {
        struct node *sorted_head = NULL;
    
        for ( ; head != NULL; head = head->next )
        {
            sorted_head = add_item_sorted( sorted_head, head->data );
        }   
    
        return sorted_head;
    }
    
    struct node* add_item_sorted( struct node *sorted_head, int data )
    {
        if ( sorted_head == NULL || !( sorted_head->data < data ) )
        {
            struct node *tmp = malloc( sizeof( struct node ) );
    
            tmp->data = data;
            tmp->next = sorted_head;
            sorted_head = tmp;
        }
        else
        {
           struct node *current = sorted_head;
    
            while ( current->next != NULL && current->data < data )
            {
                current = current->next;
            }
    
            struct node *tmp = malloc( sizeof( struct node ) );
            tmp->data = data;
            tmp->next = current->next;
            current->next = tmp;
        }
    
        return sorted_head;
    }
    
    void display( struct node *head )
    {
        for ( ; head != NULL; head = head->next )
        {
            printf( "%d ", head->data );
        }
        printf( "\n" );
    }
    
    #define N   10
    
    int main( void ) 
    {
        struct node *head = NULL;
    
        for ( int i = 1; i <= N; i++ ) head = add_item( head, i );
    
        display( head );
    
        struct node *sorted_head = create_sorted_list( head );
        display( sorted_head );
    
        return 0;
    }
    

    Rge 程序输出为

    10 9 8 7 6 5 4 3 2 1 
    1 2 3 4 5 6 7 8 9 10 
    

    【讨论】:

    • 非常感谢!在发布此内容之前,我尝试在 create_sorted_list 中将 sortedList 头设置为 NULL,但发现总是遇到 seg 错误。您是否有机会详细说明我的示例代码遇到的“未定义行为”?
    • @Lamar 由于数据成员 next 未初始化,因此循环中的条件 while(curr->next != NULL){ 可以具有随机值。
    • 我明白了!感谢您的澄清
    【解决方案2】:

    我相信它正在发生,因为在您的 add_item_sorted 函数中,您正在访问列表,就好像有一个虚拟头节点(您从检查 cur-&gt;next-&gt;data 开始,实际上应该检查 cur-&gt;data)。

    当您malloc 一个节点时,它可能在其数据字段中保存0 或任何其他值。因此,在您的情况下,sorted_head 在其数据字段中持有0。现在,根据您的示例,您尝试插入值56。在add_item_sorted 函数中,您首先尝试访问cur-&gt;next-&gt;data,它为NULL。因此,在这个 sorted_head 之后插入了一个新节点。

    【讨论】:

      猜你喜欢
      • 2013-07-18
      • 1970-01-01
      • 2021-02-12
      • 2021-12-27
      • 1970-01-01
      • 2015-07-24
      • 2016-08-30
      • 2020-12-05
      • 1970-01-01
      相关资源
      最近更新 更多