【问题标题】:C adding node to head of linked listC将节点添加到链表的头部
【发布时间】:2012-09-22 09:09:09
【问题描述】:

我在c中创建了一个链表结构

struct node{
   int value;
   struct node* next;
};

在列表开头添加节点的方法:

void addFirst(struct node *list, int value){
    struct node *new_node = (struct node*) malloc (sizeof (struct node));
    new_node->value = value;
    new_node->next = list;
    list = new_node;
   }

我创建了一个列表(malloc 和所有内容),然后调用此方法,它在方法中添加了新节点,但是当我回到我的主节点时,我的旧列表保持不变。使用 DDD 调试器检查所有内容。这怎么可能?我无法更改方法签名,因此必须这样做。

【问题讨论】:

    标签: c linked-list nodes head


    【解决方案1】:

    无法以这种方式将节点指针更改为函数。在函数中,您可以更改指针的内容,而不是指针的地址。要做到这一点,您必须传递指针struct node **list

    这里是如何做到的:

    void addFirst(struct node **list, int value){
        struct node *new_node = (struct node*) malloc (sizeof (struct node));
        new_node->value = value;
        new_node->next = *list;
        *list = new_node;
    }
    

    或者你可以这样做

    struct node * addFirst(struct node *list, int value){
        struct node *new_node = (struct node*) malloc (sizeof (struct node));
        new_node->value = value;
        new_node->next = list;
        return new_node;
    }
    

    在你的鳕鱼中,你可以在调用这个函数后得到头部

    head = addfirst(head,45);
    

    【讨论】:

    • 必须有一种方法,因为在我旁边的 PC 上这工作 ~X( :(((((
    • 确定?!?这不可以。 excpet:你有一个全局变量“head”,它被用作链表的头,由 addFirst() 调用设置。但是那样会很丑。
    【解决方案2】:

    如果你真的需要这样做,你必须重新投射指针。像这样的:

    struct node *my_list = null;
    addFirst((struct node *)&my_list, 123);
    
    void addFirst(struct node *list, int value){
        struct node **real_list = (struct node **)list;
        struct node *new_node = (struct node*) malloc (sizeof (struct node));
        new_node->value = value;
        new_node->next = *real_list;
        *real_list = new_node;
    }
    

    【讨论】:

    • 极其丑陋且不可维护。 (比如调用“子”变量“父”;或者用“last”而不是“next”指针构建一个链表)
    • 我从没说过它漂亮。我不会这样做的。但它回答了 OP 的问题。
    【解决方案3】:

    在 C 语言中,如果您希望函数能够更改在其参数中接收到的值,则需要传递该值的地址。因此,要更改列表指针的值,您需要传递列表指针的地址。您的 addFirst() 函数应如下所示:

    void addFirst(struct node **list, int value){
         struct node *new_node = (struct node*) malloc (sizeof (struct node));
         new_node->value = value;
         new_node->next = *list;
         *list = new_node;
    }
    

    当调用该函数时,你可以这样调用它:

    addFirst(&list, value);
    

    现在,如果您想保留函数的签名,一种可能是改变您考虑头节点的方式。如果你声明你的头节点的目的只是保存一个指向第一个值的指针,但它本身不包含一个值,你可以这样做:

    struct node *head;
    
    void addFirst(struct node *list, int value){
         struct node *new_node = (struct node*) malloc (sizeof (struct node));
         new_node->value = value;
         new_node->next = list->next;
         list->next = new_node;
    }
    
    addFirst(head, 45);
    

    现在,您只需更改在列表上工作的所有函数,以便它们工作相同,考虑到“head”仅指向列表的真正第一个节点,而不是列表的成员本身。出于所有实际目的,“真正的”头是头->下一个。

    【讨论】:

      【解决方案4】:

      我已经学习了@Vlad Lazarenko 的答案,并且我编写了这样的代码,对吗?

      addFirst((struct node**)head,123);
      
      void addFirst(struct node **list,int value)
      {
          struct node *new_node=malloc(sizeof(struct node));
          new_node->value=value;
          new_node->next=*list;
          list=&new_node;
      }
      

      【讨论】:

        【解决方案5】:
        void addFirst(struct node **list, int value){
            struct node *new_node = (struct node*) malloc (sizeof (struct node));
            new_node->value = value;
            new_node->next = *list;
            *list = new_node;
        }
        

        这是正确的代码。问题是指针struct node *list 您传递的指针无法更改,因为它是一个堆栈变量。如果您将其更改为struct node **list,您将传递一个指向列表第一个节点的指针。现在您可以将其更改为指向列表的新第一个节点。

        【讨论】:

        • 我知道它可以这样做(节点**作为参数)但是没有办法像我写的那样做吗? :(
        【解决方案6】:

        一切都很好,但在void addFirst(struct node *list, int value) 函数中,list 是按值传递的。这意味着正在复制一个指针,并且在addFirst 函数内为该指针分配一个新地址对于addFirst 的调用者是不可见的。要解决它,您必须逐个传递指针 (struct node **) 或将其作为返回值并要求调用者将其用作新的“头”。

        在结构声明之后不要忘记;

        【讨论】:

        • +1 建议返回新头地址
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2021-06-28
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多