我有一个如下的循环链表,该链表保留了要处理的数据的状态。该状态用于决定从列表的开头,中间或结尾删除。该列表有时甚至根本没有任何数据,或者可能要删除多个节点。
struct data
{
bool status;
char other_info[20];
struct data *next;
};
我尝试了以下代码
struct data* delete_nodes(struct data *head)
{
struct data* first = NULL, *prev = NULL, *temp = NULL;
first = head;
temp = head;
prev = head;
do
{
//prev = temp;
if (temp != NULL && temp->next == head)
{
head->next = NULL;
free(temp);
head = NULL;
return head;
}
if (temp != NULL && temp->status == true)
{
//temp = prev;
prev->next = temp->next;
free(temp);
temp = prev->next;
}
else if(temp != NULL)
temp = temp->next;
if (temp == NULL)
return head;
} while (temp != NULL && first != temp);
head = temp;
return head;
}
现在,将数据推送到其中可以正常工作。如果只有一个节点,则删除也可以正常工作。但是如果要删除的节点不止一个,则会崩溃。
delete_nodes()
函数由线程调用,该线程处理数据(如果有)并调用delete_nodes()
最佳答案
该代码块
if (temp != NULL && temp->status == true)
{
//temp = prev;
prev->next = temp->next;
free(temp);
temp = prev->next;
}
在进行第一次迭代时肯定是错误的。
在第一次迭代中,
prev
和temp
都与head
相同。因此,prev
指向与free
相同的内存。考虑放弃对
NULL
的所有检查,并且仅在开始时进行检查,即struct data* delete_nodes(struct data *head)
{
if (head == NULL) return NULL;
// Hereafter no further checks for NULL is needed
完整的功能可能类似于:
struct data* delete_nodes(struct data *head)
{
if (head == NULL) return NULL;
struct data *prev = NULL;
struct data *temp = head;
struct data *first = head;
do
{
struct data *next = temp->next;
if (temp->status)
{
if (prev == NULL)
{
// Delete head element
head = temp->next;
}
else
{
// Delete middle element
prev->next = temp->next;
}
free(temp);
}
else
{
prev = temp;
}
temp = next;
} while (temp != first);
if (prev == NULL)
{
// List is empty
return NULL;
}
return head;
}