在C中,添加到FIFO队列后部时遇到问题,请参考最后一个元素
我很难理解C语言。我正在尝试实现一个FIFO链表,在这个链表中我有一个对列表末尾的引用,以便在添加元素时轻松访问。在头部和后部为同一节点的情况下,排队到空列表可以很好地工作。但是,当我第二次排队时,后面是正确的新节点,但头部也会更新,应该保持不变。有没有想过我可能做错了什么?如果它很难阅读,我为一行条件提前道歉在C中,添加到FIFO队列后部时遇到问题,请参考最后一个元素,c,linked-list,fifo,C,Linked List,Fifo,我很难理解C语言。我正在尝试实现一个FIFO链表,在这个链表中我有一个对列表末尾的引用,以便在添加元素时轻松访问。在头部和后部为同一节点的情况下,排队到空列表可以很好地工作。但是,当我第二次排队时,后面是正确的新节点,但头部也会更新,应该保持不变。有没有想过我可能做错了什么?如果它很难阅读,我为一行条件提前道歉 typedef struct node { PCB *pcb; struct node *next; }Node; typedef struct queue {
typedef struct node {
PCB *pcb;
struct node *next;
}Node;
typedef struct queue {
Node *head, *rear;
int size;
}Queue;
Queue * enqueue (Queue *queue, PCB *pcb) {
// Ready a new node to add to list:
Node node = {pcb, NULL};
// Node becomes head in empty list, otherwise appended to rear.
queue->size == 0 ? (queue->head = queue->rear = &node) : (queue->rear = &node);
// Keep track of list size
queue->size++;
return queue;
}
更新:
Queue * enqueue (Queue *queue, PCB *pcb) {
// Ready a new node to add to list:
Node *node = malloc(sizeof(Node));
node->pcb = pcb;
node->next = NULL;
// Node becomes head in empty list, otherwise appended to rear.
queue->size == 0 ? (queue->head = queue->rear = node) : (queue->rear->next = node);
// New node always becomes the new rear node
queue->rear = node;
// Keep track of list size
queue->size++;
return queue;
}
试试这个
#include <stdlib.h>
typedef struct node {
PCB *pcb;
struct node *next;
} Node;
typedef struct queue {
Node *head, *rear;
int size;
} Queue;
Queue *enqueue ( Queue *queue, PCB *pcb ) {
if ( queue->size == 0 ) {
queue->head = queue->rear = malloc( sizeof( Node ) );
}
else {
queue->rear->next = malloc( sizeof( Node ) );
queue->rear = queue->rear->next;
}
queue->rear->pcb = pcb;
queue->rear->next = NULL;
queue->size++;
return queue;
}
#包括
类型定义结构节点{
PCB*PCB;
结构节点*下一步;
}节点;
typedef结构队列{
节点*头部,*后部;
整数大小;
}排队;
队列*排队(队列*队列,PCB*PCB){
如果(队列->大小==0){
队列->头部=队列->后部=malloc(节点大小);
}
否则{
队列->后方->下一步=malloc(sizeof(节点));
队列->后方=队列->后方->下一步;
}
队列->后部->pcb=pcb;
队列->后方->下一步=NULL;
队列->大小++;
返回队列;
}
但是使用C++会更安全、更容易。记住以后要free()
你的笔记
对于文档(参见注释):问题中第一种方法的错误是保留了局部变量的指针。它位于堆栈上,但仅在函数终止之前有效。终止后,它是指向堆栈上某个位置的指针。使用足够的局部变量调用下一个函数时,将立即覆盖此位置。解决方案是在堆上分配。将第一个节点添加到队列时,更新的代码不太正确,因为行
队列->头部->下一个=队列->后部
设置node->next=node
,而不是将其设置为NULL
。另外,新的rear
始终是新节点,可以在if/else
语句之外设置
Queue * enqueue (Queue *queue, PCB *pcb) {
// Ready a new node to add to list:
Node *node = calloc(1, sizeof(Node));
node->pcb = pcb;
node->next = NULL;
// Node becomes head in empty list, otherwise appended to rear.
if (queue->size == 0) {
queue->head = node;
} else {
queue->rear->next = node;
}
queue->rear = node;
// Keep track of list size
queue->size++;
return queue;
}
在队列中存储局部变量的地址<代码>节点从
排队
返回后将超出范围,并将队列指针指向无效内存。请显示对M Oehm注释的.complete:如果声明静态节点={pcb,NULL}代码>您的代码可能会工作,因为在整个程序执行过程中,节点
将存在,而不仅仅是在排队
函数`@MichaelWalz:中,队列将由相同的节点组成。我不认为你可以在这里轻松地在堆上分配内存(或创建一个节点池)。@MOehm-true实际上是这样。在我看到这篇文章之前,我在意识到我的代码实际上没有正确分配下一个节点后,对我的代码进行了修复。但实际上我更喜欢你的。谢谢但是看看C++和STL容器。这使得动态数据结构变得简单。补充:我犯了错误,用C++编译器编写这个C示例。因此,如果不强制转换,您将得到从“void*”到“node*”的无效转换。但是如果你写C,你应该使用C编译器。在这种情况下,不铸造是更好的做法,也更安全(例如,看看为什么)。因此,我更新了答案。那么应该改为queue->head=queue->rear=node
?