Проблема с обнаружением NULL в указателе головного узла структуры данных очереди в isEmpty()

Я написал структуру данных очереди и тестовый код для нее. Все тесты ПРОЙДЕНЫ, пока программа не дойдет до последнего теста. IF STATEMENT для проверки того, была ли очередь пустой, должен был вернуть FALSE, потому что была вызвана enqueue и данные были вставлены в очередь.

Тест FAILED, когда я тестирую с помощью link->head == NULL. Однако, если бы я сравнивал с использованием переменной count, тест был ПРОЙДЕН. Это означает, что очередь была успешно поставлена ​​в очередь, и счетчик равен «1», а не «0», когда он распечатывался.

Мой вопрос в том, почему тест FAILED, когда я тестирую его с помощью указателя, и PASSED, когда я тестирую его с помощью count. Есть ли для этого причина? Поскольку я ожидаю, что они будут вести себя так же.

Тестовый код

#include <stdio.h>
#include "queue.h"
#include "header.h"
#define RED "\033[0;31m"
#define GREEN "\033[0;32m"
#define RESET "\033[0m"

int main()
{
    int n1 = 10, n2 = 20;
    int *retData = NULL;
    LinkedList *queue = createQueue();

    /* First Test when nothing was enqueued */
    printf("TEST Empty: ");
    if ( isQueueEmpty( queue ) == TRUE )
        printf("%sPASSED%s\n\n", GREEN, RESET);
    else
        printf("%sFAILED%s\n\n", RED, RESET); 

    /* Second Test when enqueue was called */
    enqueue( queue, &n1, 'i' );
    printf("TEST Empty (Enqueue): ");
    if ( isQueueEmpty( queue ) == FALSE )
        printf("%sPASSED%s\n\n", GREEN, RESET);
    else
        printf("%sFAILED%s\n\n", RED, RESET); 

    /* Third test when dequeue was called */
    printf("TEST Dequeue: ");
    retData = (int *)(dequeue( queue ));
    if ( *retData == 10 )
        printf("%sPASSED%s\n\n", GREEN, RESET);
    else
        printf("%sFAILED%s\n\n", RED, RESET); 
        
    printf("TEST Empty (Dequeue): ");
    if ( isQueueEmpty( queue ) == TRUE )
        printf("%sPASSED%s\n\n", GREEN, RESET);
    else
        printf("%sFAILED%s\n\n", RED, RESET); 

    /* Fourth test when enqueue is called after dequeue */
    enqueue( queue, &n2, 'i' );
    printf("TEST Empty (Enqueue): ");
    if ( isQueueEmpty( queue ) == FALSE )
        printf("%sPASSED%s\n\n", GREEN, RESET);
    else
        printf("%sFAILED%s\n\n", RED, RESET); 

    return 0;
}

Функция очереди

LinkedList* createQueue()
{
    LinkedList *queue = createLinkedList();
    return queue;
}

void enqueue( LinkedList *queue, void *data, char dataType )
{
    if( queue != NULL )
        insertLast( queue, data, dataType );
}

void* dequeue( LinkedList *queue )
{
    void *retData = NULL;
    if( queue != NULL )
        retData = removeStart( queue );

    return retData;
}

int isQueueEmpty( LinkedList *queue )
{
    int empty = FALSE;
    if( queue->head == NULL )
        empty = TRUE;
/*
    
    **                                                      **
    When the checking was done in such manner, the test PASSED 
    **                                                      **  
    if( queue->count == 0 )
        empty = TRUE;
    printf("%d\n", queue->count);
*/
    return empty;
}

Связанный список

LinkedList* createLinkedList()
{
    LinkedList *list = malloc(sizeof(LinkedList));
    list->head = NULL;
    list->tail = NULL;
    list->count = 0;
    return list;
}

void insertStart( LinkedList* list, void* inData, char valueType )
{
    /* Creating the node first */
    LinkedListNode *newNd = malloc(sizeof(LinkedListNode));
    newNd->data = inData;
    newNd->type = valueType;
    newNd->next = NULL;

    /* If head and tail is NULL, then allocate the newNd as head and tail */
    if ( list->head == NULL && list->tail == NULL )
    {
        list->head = newNd;
        list->tail = newNd;
    }
    else
    {
        /* newNd will be head, so it has new next pointer */
        newNd->next = list->head;
        list->head = newNd;
    }
    list->count++;
}

void insertLast( LinkedList* list, void *inData, char valueType )
{
    /* Creating the node first */
    LinkedListNode *newNd = malloc(sizeof(LinkedListNode));
    newNd->data = inData;
    newNd->type = valueType;
    newNd->next = NULL;

    /* If head and tail is NULL, then allocate the newNd as head and tail */
    if ( list->head == NULL && list->tail == NULL )
    {
        list->head = newNd;
        list->tail = newNd;
    }
    else
    {
        list->tail->next = newNd;   /* Current tail has new connection */
        list->tail = newNd;         /* new tail is updated */
    }
    list->count++;
}

void* removeStart( LinkedList *list )
{
    LinkedListNode *delNd = NULL;
    void *delData = NULL;

    /* Make sure the list is not empty */
    if ( list->head != NULL && list->tail != NULL )
    {
        delNd = list->head;         /* Remove start is removing from head */
        list->head = delNd->next;   /* Move to next pointer */

        delData = delNd->data;
        free(delNd); delNd = NULL;
        list->count--;
    }
    return delData;
}

void* removeLast( LinkedList *list )
{
    LinkedListNode *delNd = NULL, *travelNd = NULL;
    void *delData = NULL;

    /* Make sure the list is not empty */
    if ( list->head != NULL && list->tail != NULL )
    {
        delNd = list->tail; /* Remove last is removing from tail */

        travelNd = list->head; /* Traversal starts from head */

        /* Loop stops at the node before the tail */
        while( travelNd->next != delNd )
            travelNd = travelNd->next;  /* Move to next pointer */

        travelNd->next = NULL;
        list->tail = travelNd;

        delData = delNd->data;
        free(delNd); delNd = NULL;
        list->count--;
    }
    return delData;
}

LinkedList.h

typedef struct LinkedListNode
{
    struct LinkedListNode *next;
    void *data;
    char type;
} LinkedListNode;

typedef struct LinkedList
{
    struct LinkedListNode *head;
    struct LinkedListNode *tail;
    int count;
} LinkedList;

заголовок.h

#ifndef BOOLEAN
#define BOOLEAN
    #define FALSE 0
    #define TRUE !FALSE
#endif

person Calmen Chia    schedule 25.01.2021    source источник


Ответы (1)


isEmptyQueue проверяет только queue->head, enqueue использует insertLast, который проверяет оба queue->head и queue->tail для проверки наличия пустой очереди.

а затем настоящая ошибка: removeStart никогда не обновляет queue->tail и removeLast никогда не обновляет queue->head при удалении последнего элемента в очереди.

Короче говоря, вы неправильно сохраняете свои инварианты.

person koder    schedule 25.01.2021