как удалить узел из связанного списка - PullRequest
3 голосов
/ 31 октября 2019

Я хочу выполнить двоичную операцию между двумя узлами, сохранить результат в одном узле и исключить другой. Вот что я написал:

#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 ]

3 голосов
/ 31 октября 2019

Как и в случае с C, для функции, имеющей право изменять объект, переданный ей через список аргументов, необходимо передать адрес объекта, а не сам объект. ( подробнее об этом здесь )

В этом примере объект head, если он должен быть изменен каким-либо образом, требует, чтобы его адрес (&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);

Измените код в теле кода соответственно.

3 голосов
/ 31 октября 2019

Обе функции недействительны.

В функцию 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
...