简体   繁体   中英

how to remove a node from a linked list

I want to perform a binary operation between two nodes, store the result in one node and eliminate the other. This is what I've written:

#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);
    }

In this example I have a list like this 3 -> 5 -> NUll . I'd like to get this 15 -> NUll . When I try to print the value of the node remaining I get 3 instead of 15

The both functions are invalid.

To the function add_item you do not pass data by reference (and it does not make sense to pass data by reference).

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

So the function should be declared and defined like

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

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

You have to pass the head node to the function delete also by reference.

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

and call it like

delete( &head );

When I try to print the value of the node remaining I get 3 instead of 15

It is because you deleted the node after the head instead of deleting the head node though the result of the operation you wrote in the node after the head.

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

Here is your updated program

#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 );
    }
}

Its output is

15.000000

As is in general with C, for a function to have the power to change an object passed to it via the argument list, the address of the object must be passed, not the object itself. ( read more on this here )

In this example, the object, head , if it is to be changed in any way, requires that its address ( &head ) be passed to the function, not the object itself.
So the statement:

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

Should be changed to

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

And because the object being passed was created as a pointer: struct n *head = NULL; , the prototype for the delete function needs to accommodate the address of a pointer in its argument. This is done with a pointer to a pointer:

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

Then, inside the delete function, work on the object itself, (which is now *head ) to make the changes.

   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
    }

Conversely, in your void add_item(struct n **ptr, double *data); function, data does not need to be changed, only used within the body. Indeed the way it has been called in your code is the correct way to send the data:

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

Therefore, because the function needs the data itself, and not a pointer to the data, change the prototype to accommodate:

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

Change the code in the body of the code accordingly.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM