struct Node {
char gender;
int turns_in_bathroom;
struct Node *next;
};
struct Queue {
struct Node *front, *back;
};
int QueueDeleteNext(Queue *myQueue, char value) {
Node *current_node, *previous_node;
previous_node = NULL;
int found = 0;
for (current_node = myQueue->front; current_node != NULL;
previous_node = current_node, current_node = current_node->next) {
if (current_node->gender == value) {
if (previous_node == NULL) {
myQueue->front = myQueue->back = NULL;
}
else {
previous_node->next = current_node->next;
if(previous_node->next == NULL){
myQueue->back = previous_node;
}
}
free(current_node);
found = 1;
}
}
return found;
}
我在线上得到了分割故障
if (current_node->gender == value) {
我一生都不能弄清楚原因。这里发生了什么?更不用说尽管我的调试器出现故障错误,该代码仍将一直通过。不过,我认为有些错误可能与此有关,我想确保我已经涵盖了所有基础。
显然已经解决了问题,但代码仍然存在问题:
-
条件
(previous_node == NULL)
测试当前节点是否是队列的头部。在这种情况下,必须将头部涂抹,而不是先前的节点的next
,但是代码在不正确删除可能的尾随eNodes的情况下将整个队列提示。 -
当删除队列中的最后一个节点时,应更新队列的背部,以便随后的推动可以附加到结尾。
最后,看起来OP的意图是删除具有相应值的所有节点的意图,因为执行在第一个删除后没有停止。因此,让我们这样做并返回已删除的节点的数量:
int QueueDeleteNext(struct Queue *q, char value)
{
struct Node *prev = NULL;
struct Node *curr = q->front;
int count = 0;
while (curr) {
if (curr->gender == value) {
struct Node *nn = curr;
if (prev == NULL) {
q->front = curr->next;
} else {
prev->next = curr->next;
}
if (curr == q->back) q->back = prev;
curr = curr->next;
free(nn);
count++;
} else {
prev = curr;
curr = curr->next;
}
}
return count;
}
主循环现在是while
循环,可以以不同的方式对待删除和跳过节点。在两种情况下,下一个节点是curr->next
,但是当删除节点时,prev
节点保持不变!此代码还保留了队列的背面。
实现此目的的另一种方法是使用用于节点指针的指针,而不是使用prev
指针。这消除了区分头和其他节点的需求。nd
首先是队列头的地址,也是上一个节点的'next field after that. The code updates the pointer that points to the current node via
nd`:
int QueueDeleteNext(struct Queue *q, char value)
{
struct Node **nd = &q->front;
int count = 0;
q->back = NULL;
while (*nd) {
if ((*nd)->gender == value) {
struct Node *nn = *nd;
(*nd) = (*nd)->next;
free(nn);
count++;
} else {
q->back = *nd;
nd = &(*nd)->next;
}
}
return count;
}
此代码可以扩展到仅删除第一个节点或第一个_n_nodes。
for (current_node = myQueue->front; current_node != NULL;
previous_node = current_node, current_node = current_node->next)
在循环的每次迭代结束时,您要求Current_Node指向其下一个元素。但是,下面的一些行:
free(current_node);
您释放了此节点。因此,它不再指向任何分配的东西,从而导致您以后会遇到的细分错误。只需在找到要删除的元素时退出功能:
int QueueDeleteNext(Queue *myQueue, char value) {
Node *current_node, *previous_node;
previous_node = NULL;
for (current_node = myQueue->front; current_node != NULL;
previous_node = current_node, current_node = current_node->next) {
if (current_node->gender == value) {
if (previous_node == NULL) {
myQueue->front = myQueue->back = NULL;
}
else {
previous_node->next = current_node->next;
if(previous_node->next == NULL){
myQueue->back = previous_node;
}
}
free(current_node);
return 1;
}
}
return 0;
}
uth = 1后添加返回语句;阻止了调试器丢弃错误。