为什么我的代码在显示队列一次后打印 "The queue is empy"

Why is my code printing "The queue is empy" after displaying the queue once

我忘记在 display() 方法的开头添加一个临时节点,但后来我添加了它,但我仍然面临同样的问题。我无法在我的代码中找到问题。

我已经在下面添加了完整的代码:

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

struct Node
{
    int key;
    struct Node* next;
};

struct Queue
{
    struct Node *front, *rear;
};

struct Node* newNode(int k)
{
    struct Node* temp = (struct Node*)malloc(sizeof(struct Node));
    temp->key = k;
    temp->next = NULL;
    return temp;
}

struct Queue* createQueue()
{
    struct Queue* q = (struct Queue*)malloc(sizeof(struct Queue));
    q->front = q->rear = NULL;
    return q;
}

void enQueue(struct Queue* q, int k)
{
    struct Node* temp = newNode(k); 
    if (q->rear == NULL)
    {
        q->front = q->rear = temp;
        return;
    }
    q->rear->next = temp;
    q->rear = temp;
}
void deQueue(struct Queue* q)
{
    if (q->front == NULL)
    {
        printf("The Queue is empty.\n");
        return;
    }
    struct Node* temp = q->front;
    printf("Deleted Element: %d\n",q->front->key);
    q->front = q->front->next;
    if (q->front == NULL)
        q->rear = NULL;
    free(temp);
}
void display(struct Queue* q)  
{  
    struct Queue* temp=q;
    if(temp->front == NULL)  
    {  
        printf("The Queue is Empty.\n");  
    }  
    else  
    {   
        printf("Queue contains the following elements:\n");  
        while(temp->front != NULL)
        {  
            printf("%d\t",temp->front -> key);  
            temp->front = temp->front -> next;  
        }
        printf("\n");
    }  
}  

int main()
{
    struct Queue* q = createQueue();
    int choice=0;     
    while(choice != 4)  
    {  
        printf("Choose from the following by entering the index number:\n1.Insert an element\n2.Delete an element\n3.Display the elements in queue\n4.Exit\n");  
        scanf("%d",&choice);  
        switch(choice)  
        {  
            case 1:  
            {   
                int k;
                printf("Enter the element you want to insert: ");
                scanf("%d",&k);  
                enQueue(q,k);
                break;  
            }  
            case 2:  
            {  
                deQueue(q); 
                break;  
            }  
            case 3:  
            {  
                display(q);  
                break;  
            }  
            case 4:   
            {  
                printf("\nThe program has ended."); 
                exit(0); 
                break;   
            }  
            default:  
            {  
                printf("\nInvalid Input! Please try again.");  
            }
        }
    }
}

在您的 display 函数中,您认为这行代码的作用是什么?

temp->front = temp->front -> next;

它将队列的前端向前移动,直到它最终指向 NULL。因为您没有通过将 q 分配给 temp 来制作队列的另一个副本 - 它们都指向同一个队列。

相反,您要做的是将 temp 设为 struct Node 并将其沿队列移动 - 类似这样

void display(struct Queue* q)  
{  
    struct Node* temp=q->front;
    if(temp == NULL)  
    {  
        printf("The Queue is Empty.\n");  
    }  
    else  
    {   
        printf("Queue contains the following elements:\n");  
        while(temp != NULL)
        {  
            printf("%d\t",temp -> key);  
            temp = temp -> next;  
        }
        printf("\n");
    }  
} 

对于初学者来说,为新模式分配内存可能会失败。在这种情况下,您的代码将调用未定义的行为。将函数 newNode 重写为以下方式

struct Node * newNode( int k )
{
    struct Node *temp = malloc( sizeof( struct Node ) );

    if ( temp != NULL )
    {
        temp->key = k;
        temp->next = NULL;
    }

    return temp;
}

相应的函数enQueue应该改写如下

int enQueue( struct Queue *q, int k )
{
    struct Node *temp = newNode( k );
    int success = temp != NULL;
 
    if ( success )
    {
        if ( q->front == NULL)
        {
            q->front = temp;
        }
        else
        {
            q->rear->next = temp;
        }

        q->rear = temp;
    }

    return success;
}

函数deQueue 不应发出任何消息。由函数的调用者决定是否发出消息。 您可以再编写一个函数来报告队列是否为空。例如

int isEmpty( const struct Queue *q )
{
    return q->front == NULL;
}

函数deQueue可以这样定义

void deQueue( struct Queue *q )
{
    if ( !isEmpty( q )
    {
        struct Node *temp = q->front;

        q->front = q->front->next;
        if ( q->front == NULL ) q->rear = NULL;

        free( temp );
    }
}

而且函数可以这样调用

case 2:
{
    if ( isEmpty( q ) )
    {
        printf("The Queue is empty.\n");
    }
    else
    {
        printf("Deleted Element: %d\n",q->front->key);
        deQueue( q );
    }
}

在这个赋值后display函数内

struct Queue* temp=q;

指针temp指向与指针q相同的struct Queue类型的对象。也就是说,您正在使用两个不同的指针访问同一个对象。所以使用指针 temp 你正在改变类型 struct Queue

的原始对象
temp->front = temp->front -> next;  

所以在这个循环之后

while(temp->front != NULL)

类型struct Queue的原始对象的指针front将等于NULL。

函数可以这样定义

void display( const struct Queue *q )  
{  
    printf("Queue contains the following elements:\n");  

    for ( const struct Node *current = q->front; current != NULL; current = current->next;)
    {  
        printf( "%d\t", current->key);  
    }
    printf("\n");
}  

而且函数可以这样调用

case 3:
{
    if ( isEmpty( q ) )
    {
        printf( "The Queue is Empty.\n" );
    }
    else
    {
        display( q );
    }
}