Удаление узла при условии ввода строки - PullRequest
0 голосов
/ 09 марта 2020

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

void popMiddle(struct data **head, struct data **tail, char name[])
{
    if(*head == NULL)
    {
        printf("No Data to Delete\n");
    }

    else if(*head == *tail)
    {
        if (strcmp((*head)->name, name)==0)
        {
            free(*head);
            *head = *tail = NULL;
        }

        else
        {
            printf("No Data to Delete\n");
        }
    }

    else if (strcmp((*head)->name, name)==0)
    {
        struct data *curr = *head;
        *head = (*head)->next;
        free(curr);
        curr = NULL;
    }
    else
    {
        struct data *curr1 = *head;
        struct data *curr2;

        while (strcmp(curr1->next->name, name)!=0 && curr1 !=NULL)
        {

            printf("%d\n", curr1);
            curr1 = curr1->next;
        }

        if ( curr1->next != *tail )
        {
            curr2 = curr1->next;
            curr1->next = curr2->next;
            free(curr2);
            curr2 = NULL;

        }

        else if (curr1->next == *tail)
        {
            free(*tail);
            *tail = curr1;          
            (*tail)->next= NULL;
        }

        else  
        {
            printf("No Data to Delete\n");
        }
    }

}

Это список, с которым я работал:

Сара-> Джон-> Гордон

Я хотел удалить узел, содержащий «Джек». Однако, как вы знаете, он не существует в связанном списке. Следовательно, вывод должен был быть «Нет данных для удаления». К сожалению, консоль ничего не печатает ... Я подозревал, что это был l oop. Но мне нужно знать, где он сделал go неправильно ... Спасибо за ваше внимание.

1 Ответ

2 голосов
/ 09 марта 2020

Весьма вероятно, что ваша программа вылетает , и это из-за l oop

while (strcmp(curr1->next->name, name)!=0 && curr1 !=NULL)

Здесь есть две ошибки:

  1. Порядок, в котором вы делаете сравнения. Логический оператор AND && всегда будет сначала вычислять левую часть, что означает, что вы будете разыменовывать указатель curr1, когда он NULL. Вам нужно изменить порядок двух сравнений, чтобы сначала проверить curr1 != NULL.

  2. Вторая проблема заключается в том, что вы не проверяете, является ли curr1->next нулевым указателем, что означает, что уже на последнем узле в списке вы будете разыменовывать указатель NULL.

Я предлагаю вам изменить значение l oop на , начинающееся с второй узел в списке, и во время итерации вместо этого проверьте «текущий» узел:

struct data *curr1 = (*head)->next;

while (curr1 != NULL && strcmp(curr1->name, name) != 0)
{
    printf("%p\n", (void *) curr1);  // Changed to the format specifier %p, to print pointers
    curr1 = curr1->next;
}

После этого l oop curr1 будет указателем NULL, если имя не было нашел. Или указатель на узел, содержащий имя:

if (curr1 == NULL)
{
    printf("No Data to Delete\n");
}
else
{
    // Node found, remove it
}

Теперь, чтобы помочь вам с самим удалением, для этого вам нужно отследить предыдущий узел, который это можно сделать, изменив l oop как

struct data *curr = (*head)->next;
struct data *prev;
while (curr != NULL && strcmp(curr->name, name) != 0)
{
    prev = curr;  // Keep track of the previous node
    curr = curr->next;
}

Теперь легко отсоединить узел curr от списка:

prev->next = curr->next;

И, конечно, добавить специальный случай чтобы увидеть, удаляем ли мы хвост:

if (prev->next == NULL)
    *tail = prev;

С некоторыми дополнительными изменениями вам не нужно иметь чеки на *head == *tail или strcmp((*head)->name, name)==0. Эти случаи можно поместить в более общий случай c с l oop на самом деле.

Собрав все это вместе, ваша функция может выглядеть примерно так:

void popMiddle(struct data **head, struct data **tail, char *name)
{
    struct data *curr = *head;  // Start iterating at the head
    struct data *prev = NULL;

    while (curr != NULL && strcmp(curr->name, name) != 0)
    {
        prev = curr;  // Keep track of the previous node
        curr = curr->next;
    }

    if (curr == NULL)
    {
        printf("No Data to Delete\n");
    }
    else
    {
        // Unlink node
        if (prev == NULL)
        {
            // Removed node was the head
            *head = curr->next;

            if (*head == NULL)
            {
                // We removed the last node in the list, it's now empty
                *tail = NULL;
            }
        }
        else
        {
            prev->next = curr->next;

            if (prev->next == NULL)
                *tail = prev;  // Removed the tail
        }

        // Free the found node
        free(curr);
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...