Что не так с этим списком удаления функции хвостового узла? - PullRequest
4 голосов
/ 16 октября 2010

Я написал эту функцию для удаления последнего узла односвязного списка.

Проблема в том, что он может удалить все узлы, кроме первого / начального узла.

Чего не хватает в этом фрагменте кода?

Пожалуйста, ответьте на мою конкретную проблему.

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

struct Node
{
    char CharContent;
    struct Node * NextNodePointer;
};
typedef struct Node Node;

#pragma region Prototypes
Node * CreateNewNode(char ch);
Node * AddNode(Node * start, Node * newNode);
void DeleteTailNode(Node * start);
void PrintAllNodes(const Node * start);
#pragma endregion Comments

main()
{
    Node * start = NULL;
    Node * newNode = NULL;

    start = AddNode(start, CreateNewNode('A'));
    start = AddNode(start, CreateNewNode('B'));
    start = AddNode(start, CreateNewNode('C'));
    start = AddNode(start, CreateNewNode('D'));
    PrintAllNodes(start);

    DeleteTailNode(start);
    PrintAllNodes(start);
    DeleteTailNode(start);
    PrintAllNodes(start);
    DeleteTailNode(start);
    PrintAllNodes(start);
    DeleteTailNode(start);
    PrintAllNodes(start);
    DeleteTailNode(start);
    PrintAllNodes(start);

    getch();
}

#pragma region Node * CreateNewNode(char ch)
Node * CreateNewNode(char ch)
{
    struct Node * newNode = (struct Node *) malloc(sizeof(struct Node *));

    newNode->CharContent = ch;
    newNode->NextNodePointer = NULL;

    return newNode;
}
#pragma endregion Comment

#pragma region UnifiedAddNode()
Node * AddNode(Node * start, Node * newNode)
{
    Node * copyOfStart = start;

    if(start == NULL)
    {
        return newNode;
    }
    else
    {
        while(copyOfStart->NextNodePointer != NULL)
        {
            copyOfStart = copyOfStart->NextNodePointer;
        }

        copyOfStart->NextNodePointer = newNode;

        return start;
    }
}
#pragma endregion Comment


void DeleteTailNode(Node * start)
{
    Node * prev = NULL;
    Node * current = start;

    while(current->NextNodePointer != NULL)
    {
        prev = current;
        current = current->NextNodePointer;
    }

    free (current);

    if (prev != NULL)
    {
        prev->NextNodePointer = NULL;
    }
}


#pragma region PrintAllNodes()
void PrintAllNodes(const Node * start)
{
    struct Node * tempRoot = start;

    while(tempRoot != NULL)
    {
        printf("%c, ", tempRoot->CharContent);

        tempRoot = tempRoot->NextNodePointer;
    }

    printf("\n");
}
#pragma endregion Comment

Ответы [ 3 ]

3 голосов
/ 16 октября 2010

Вы не обнаруживаете случай, когда start равен NULL, т. Е. Список пуст.

Разве вы не хотите освободить следующий узел до того, как установит его в NULL?

Если начальный узел является последним узлом, prev будет равен NULL, когда обход списка завершен, но когда это происходит, вы удаляете (NULL) start->NextNodePointer, когда хотите удалить сам старт.

Попробуйте:

void DeleteTailNode(Node *& start)
{
    Node * prev = NULL;
    Node * current = start;

    if (start == NULL)
        return;

    while(current->NextNodePointer != NULL)
    {
        prev = current;
        current = current->NextNodePointer;
    }

    if(current != NULL)
        free(current);

    if(current == start)
        start = NULL;

    if(prev != NULL)
        prev->NextNodePointer = NULL;
}
2 голосов
/ 16 октября 2010

Внутри CreateNewNode()

struct Node * newNode = (struct Node *) malloc(sizeof(struct Node *));  
                                                                  ^
                                                                  |  

                                                                 Ouch!!

Измените его на: struct Node * newNode = (struct Node *) malloc(sizeof(struct Node));

РЕДАКТИРОВАТЬ 2

Тестовый прогон ЗДЕСЬ

1 голос
/ 16 октября 2010

Как вы понимаете, удалено оно или нет?Как я вижу, здесь ничего не удалено ... это утечка памяти на 100% .. вы не используете free в DeleteTailNode ... вы просто делаете выделенную память недоступной ..

Редактировать: вызов бесплатно (текущий) после цикла.И нет необходимости в проверке, если current равен NULL, можно безопасно удалить указатель NULL.

...