我有一个如下的循环链表,该链表保留了要处理的数据的状态。该状态用于决定从列表的开头,中间或结尾删除。该列表有时甚至根本没有任何数据,或者可能要删除多个节点。

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;

    }


在进行第一次迭代时肯定是错误的。

在第一次迭代中,prevtemp都与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;
}

07-24 09:46
查看更多