如何从链接列表中删除节点

时间:2019-10-31 11:28:39

标签: c struct linked-list singly-linked-list

我想在两个节点之间执行二进制运算,将结果存储在一个节点中,而消除另一个节点。这是我写的:

#include <stdio.h>
#include <ctype.h>
#include <stdlib.h>
#include <math.h>

    struct n{
        double value;
        char op;
        struct n *next;
    };

    void delete(struct n *head);
    void add_item(struct n **ptr, double *data);

    int main(){
        struct n *head = NULL;
        double result;
        add_item(&head, 5);
        add_item(&head, 3);
        head->op = '*';
        result = (head->next)->value * head->value;
        (head->next)->value = result;
        delete(head);
        printf("%lf\n",head->value);
        free(head); 
        return 0;        
    }

    void add_item(struct n **ptr, double *data)
    {
            struct n *item = malloc(sizeof *item);

            item->value = *data;
            item->next = *ptr;
            item->op = '?';
            *ptr = item;
    }

    void delete(struct n *head)
    {
        struct n *temp;
        temp = head->next;
        head->next = temp->next;
        free(temp);
    }

在此示例中,我有一个像这样的列表3 -> 5 -> NUll。我想要这个15 -> NUll。 当我尝试打印剩余节点的值时,得到的是3而不是15

2 个答案:

答案 0 :(得分:3)

两个功能均无效。

对于功能add_item,您不按引用传递数据(按引用传递数据也没有意义。)

    add_item(&head, 5);
    add_item(&head, 3);

因此该函数应像这样声明和定义

void add_item(struct n **ptr, double data)
{
        struct n *item = malloc(sizeof *item);

        item->value = data;
        item->next = *ptr;
        item->op = '?';
        *ptr = item;
}

您还必须通过引用将头节点传递给函数delete

void delete(struct n **head)
{
    if ( *head )
    {
        struct n *temp = *head;
        *head = ( *head )->next;
        free( temp );
    }
}

并称呼它

delete( &head );
  

当我尝试打印剩余节点的值时,得到3而不是   15

这是因为您在头之后的节点中编写了操作结果,因此您删除了头之后的节点,而不是删除头节点。

(head->next)->value = result;

这是您更新的程序

#include <stdio.h>
#include <stdlib.h>

    struct n{
        double value;
        char op;
        struct n *next;
    };

    void delete(struct n **head);
    void add_item(struct n **ptr, double data);

    int main(){
        struct n *head = NULL;
        double result;
        add_item(&head, 5);
        add_item(&head, 3);
        head->op = '*';
        result = (head->next)->value * head->value;
        (head->next)->value = result;
        delete(&head);
        printf("%lf\n",head->value);
        free(head); 
        return 0;        
    }

void add_item(struct n **ptr, double data)
{
        struct n *item = malloc(sizeof *item);

        item->value = data;
        item->next = *ptr;
        item->op = '?';
        *ptr = item;
}

void delete(struct n **head)
{
    if ( *head )
    {
        struct n *temp = *head;
        *head = ( *head )->next;
        free( temp );
    }
}

其输出为

15.000000

答案 1 :(得分:3)

通常与C一样,要使函数有权更改通过参数列表传递给它的对象,必须传递对象的地址,而不是对象本身。 ( read more on this here

在此示例中,如果要以任何方式更改对象head,则要求将其 address &head)传递给函数,不是对象本身。
所以声明:

delete(head); //passing the object will not allow it to be changed

应更改为

delete(&head); //The object's address is passed, allowing the object to be changed

由于要传递的对象是作为指针创建的:struct n *head = NULL;,因此delete函数的原型需要在其参数中容纳指针的地址。这是通过指向指针的指针完成的:

void delete(struct n **head);//accommodates the address of a pointer object

然后在delete函数内部,对对象本身(现在为*head)进行更改。

   void delete(struct n **head)
    {
        if (*head == NULL) return;
        struct n *temp = *head;
        *head = temp->next;//point head to next node
        free(temp);//free old head
    }

相反,在您的void add_item(struct n **ptr, double *data);函数中,data不需要更改,只需要在体内使用即可。确实,在您的代码中调用它的方式是发送数据的正确方式:

add_item(&head, 5);  // 2nd argument passes object directly, i.e. not an address

因此,由于该函数需要数据本身而不是数据指针,因此请更改原型以适应:

void add_item(struct n **ptr, double data);

相应地在代码主体中更改代码。