[英]Implementing Queue using Linked list in C
我正在尝试使用链表实现队列。 这是我的程序
#include <stdio.h>
#include <stdlib.h>
struct queue_struct{
int ele;
struct queue_struct *next;
};
struct Queue{
struct queue_struct *front, *rear;
};
int isEmpty(struct Queue *q){
return (q->front==NULL||q->rear==NULL);
}
void enqueue(struct Queue *q, int x){
struct queue_struct *temp=(struct queue_struct *)malloc(sizeof(struct queue_struct));
temp->ele=x;
temp->next=NULL;
if(isEmpty(q)){
q->front=q->rear=temp;
return;
}
q->rear=temp;
printf("The item %d has been enqueued into the queue\n", x);
}
void dequeue(struct Queue *q){
if(isEmpty(q)){
printf("The queue is already empty. No more elements can be removed!\n");
return;
}
struct queue_struct *temp=q->front;
printf("The item %d has been dequeued from the queue\n", temp->ele);
q->front=q->front->next;
if(q->front=NULL)
q->rear=NULL;
free(temp);
}
void display(struct Queue *q){
struct queue_struct *temp=q->front;
int len;
printf("The contents of the queue are:\n");
if(isEmpty(q)){
printf("Nothing to be shown, the queue is empty.\n");
return;
}
while(temp!=NULL){
temp=temp->next;
len++;
}
temp=q->front;
for(int i=1;i<len-1;i++){
printf("| %d |\n", temp->ele);
printf(" ------ \n");
temp=temp->next;
}
printf("| %d |\n", temp->ele);
}
int main()
{
int choice, element;
printf("LET'S START WITH AN EMPTY QUEUE\n\n");
struct Queue *q=(struct Queue *)malloc(sizeof(struct Queue));
q->front=q->rear=NULL;
while(1){
printf("\nMENU\n");
printf("----\n");
printf("\t1. Enqueue\n");
printf("\t2. Dequeue\n");
printf("\t3. Display queue\n");
printf("\t4. Exit\n");
printf("Enter your choice: ");
scanf("%d", &choice);
switch(choice){
case 1: printf("Enter the element to be enqueued: ");
scanf("%d", &element);
enqueue(q, element);
break;
case 2: dequeue(q);
break;
case 3: display(q);
break;
case 4: printf("Program terminated successfully!\n");
return 0;
default: printf("Invalid input");
}
}
}
但是,当我尝试将元素排入队列时,我遇到了分段错误
经过调试,我发现我的 isEmpty() function 是罪魁祸首,但我似乎找不到问题所在。 考虑到问题的性质,我认为前面或后面应该是 NULL 队列为空。 我的理解错了吗? 任何帮助表示赞赏。
编辑
正如@interjay 所建议的,我对main()
方法的q=NULL
部分进行了更改。 但是,我的display
方法现在出错了。 我不明白为什么。
有一些问题。
在main
中,做q = NULL;
是 memory 泄漏,会产生段错误。 初始化空队列的正确方法是:
q->front = NULL;
q->rear = NULL;
队列显示使用while
循环来查找队列的末尾,从而保证了在随后for
循环(即segfault)中temp
为NULL
。 只需要for
循环
enqueue
无法正确处理附加到非空列表。
dequeue
有一个 if 语句,它使用赋值运算符if (q->front = NULL)
而不是相等运算符if (q->front == NULL)
。 但是,即使进行了该修复,它仍然无法正确处理操作。
isEmpty
function 与其他功能真的没什么用,因为他们可以/应该只检查front
。
不要malloc
的返回值。 请参阅: 我是否会转换 malloc 的结果? 进行演员表可能会引入微妙的、难以发现的错误。
这是修复问题的重构版本。 我对一些struct
名称进行了一些清理/重命名,以便对 function 更具描述性。
在下面的代码中,我使用cpp
条件来显示更改(例如):
#if 0
// old code
#else
// new code
#endif
我已经尽可能地注释了错误:
#include <stdio.h>
#include <stdlib.h>
typedef struct queue_element QElement;
struct queue_element {
int ele;
QElement *next;
};
typedef struct Queue {
QElement *front, *rear;
} Queue;
int
isEmpty(Queue *q)
{
return (q->front == NULL || q->rear == NULL);
}
void
enqueue(Queue *q, int x)
{
QElement *temp = malloc(sizeof(*temp));
temp->ele = x;
temp->next = NULL;
// NOTE/BUG: this does _not_ append correctly to a non-empty list
#if 0
if (isEmpty(q)) {
q->front = q->rear = temp;
return;
}
q->rear = temp;
#else
// link old rear node to new node
if (q->rear != NULL)
q->rear->next = temp;
// set new rear node
q->rear = temp;
// set the front of the list if it was empty
if (q->front == NULL)
q->front = temp;
#endif
printf("The item %d has been enqueued into the queue\n", x);
}
void
dequeue(Queue *q)
{
QElement *temp = q->front;
if (temp == NULL) {
printf("The queue is already empty. No more elements can be removed!\n");
return;
}
printf("The item %d has been dequeued from the queue\n", temp->ele);
q->front = temp->next;
if (q->rear == temp)
q->rear = NULL;
free(temp);
}
void
dequeue_OLD(Queue *q)
{
if (isEmpty(q)) {
printf("The queue is already empty. No more elements can be removed!\n");
return;
}
QElement *temp = q->front;
printf("The item %d has been dequeued from the queue\n", temp->ele);
q->front = q->front->next;
// NOTE/BUG: this if is invalid -- it is using the assignment operator in
// place of the [desired] equality operator
// NOTE/BUG: even with this fix, the dequeue is still broken -- see the fix
// above
#if 0
if (q->front = NULL)
q->rear = NULL;
#else
if (q->front == NULL)
q->rear = NULL;
#endif
free(temp);
}
void
display(Queue *q)
{
QElement *temp = q->front;
printf("The contents of the queue are:\n");
if (temp == NULL) {
printf("Nothing to be shown, the queue is empty.\n");
return;
}
// NOTE/BUG: doing the while loop ensures that temp will be NULL so that the
// for loop will try to dereference temp and it will segfault
#if 0
int len;
while (temp != NULL) {
temp = temp->next;
len++;
}
for (int i = 1; i < len - 1; i++) {
printf("| %d |\n", temp->ele);
printf(" ------ \n");
temp = temp->next;
}
printf("| %d |\n", temp->ele);
#else
int sep = 0;
for (; temp != NULL; temp = temp->next) {
if (sep)
printf(" ------ \n");
sep = 1;
printf("| %d |\n", temp->ele);
}
#endif
}
int
main(void)
{
int choice, element;
printf("LET'S START WITH AN EMPTY QUEUE\n\n");
Queue *q = malloc(sizeof(*q));
// NOTE/BUG: setting q to NULL ensures a segfault and is a memory leak
#if 0
q = NULL;
#else
q->front = NULL;
q->rear = NULL;
#endif
while (1) {
printf("\nMENU\n");
printf("----\n");
printf("\t1. Enqueue\n");
printf("\t2. Dequeue\n");
printf("\t3. Display queue\n");
printf("\t4. Exit\n");
printf("Enter your choice: ");
scanf("%d", &choice);
switch (choice) {
case 1:
printf("Enter the element to be enqueued: ");
scanf("%d", &element);
enqueue(q, element);
break;
case 2:
dequeue(q);
break;
case 3:
display(q);
break;
case 4:
printf("Program terminated successfully!\n");
return 0;
default:
printf("Invalid input");
break;
}
}
return 0;
}
有以下问题:
您不应该将NULL
分配给q
,因为这是指向您刚刚分配的rear
的指针,并且它包含指针front
和 back ,即使队列为空,您也将始终需要它们。 相反,您应该将这些front
指针NULL
rear
q->front = q->rear = NULL;
在dequeue
中,你在if
条件中有一个赋值,你实际上想要一个compare 。 改变这个:
if(q->front=NULL)
至:
if(q->front==NULL)
在display
中,您在第一个循环之后取消引用temp
,您确定它实际上是NULL
。 所以这将引发一个异常。 你应该只有一个循环。 任何尝试使用相同的temp
指针在列表上再次循环都需要将temp
指针重置为front
。 这是您的display
function 的简单替换:
void display(struct Queue *q){ struct queue_struct *temp=q->front; printf("The contents of the queue are:\n"); if(isEmpty(q)){ printf("Nothing to be shown, the queue is empty.\n"); return; } while(temp,=NULL){ printf("%d->"; temp->ele); temp=temp->next; } printf("NULL\n"); }
如果您还希望显示i
计数器,则只需在上面的同一循环中递增它。
通过这些更改,您的代码将起作用。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.