删除链接列表中具有特定值的所有节点

时间:2011-12-23 12:09:42

标签: c memory-management linked-list access-violation

标题非常自我解释。这是我为此目的编写的函数:

void wipeLoneCells()
{
    cell *tmp;

    tail = head;
    while (1)
    {
        if (head == tail && !tail->flag)
        {
            head = head->next;
            free(tail);
            tail = head;
            continue;
        }

        tmp = tail->next;

/***/   if (tmp->next == NULL && !tmp->flag)
        {
            tail->next = NULL;
            free(tmp);
            break;
        }
        else if (!tmp->flag)
        {
            tail->next = tmp->next;
            free(tmp);
            continue;
        }

        tail = tail->next;      
    }
}

列表的头部和尾部是全局的,列表是在调用此函数时构建的,其中头部指向第一个节点,尾部指向最后一个节点(其下一个为NULL)。我几乎可以肯定我的链表是正确构建的,因为我可以打印它们而没有错误。有时此功能可以正常工作,有时会导致标记为星星的线路出现访问冲突。我知道这并不是完全错误的,因为当我没有产生错误时,我得到了我想要的结果,虽然我经常得到错误所以必须有一些我忽略的东西。提前感谢您的帮助。

编辑:这是固定代码:

void wipeLoneCells()
{
    cell *tmp;

    tail = head;
    while (1)
    {
        if (head == tail && !tail->flag)
        {
            head = head->next;
            free(tail);
            tail = head;
            continue;
        }

        tmp = tail->next;

        if (tmp->next == NULL && !tmp->flag)
        {
            tail->next = NULL;
            free(tmp);
            break;
        }
        else if (tmp->next == NULL)
        {
            tail = tmp;
            break;
        }
        else if (!tmp->flag)
        {
            tail->next = tmp->next;
            free(tmp);
            continue;
        }

        tail = tail->next;      
    }
}

2 个答案:

答案 0 :(得分:4)

如果

怎么办?
tmp = tail->next; 

NULL?下一行尝试取消引用NULL指针,这会导致未定义的行为 - 可能导致崩溃。

您应检查此情况并采取适当的措施。

答案 1 :(得分:1)

单链表中的正确deleteitem()应如下所示:

你可以避免递归并提出一个迭代版本(试一试,但如果你需要帮助,请告诉我)。我不会在这种情况下使用while(1)

typedef struct node {
    int data;
    struct node *next;
}NODE;


/*

(1) deleting head 
    delete element and adjust head pointer

(2) deleting tail
    delete element and adjust tail pointer

(3) one element list
    if data is the data for the only element
    then delete the list and set head and tail
    pointers to NULL

(4) all the other cases
    traverse through the list and hold the
    previous pointer. delete element and adjust
    the next pointers. 

(5) if not the above cases, then element not
    present.. do nothing..

*/
void deleteitem(int data)
{
    printf("%s: %d - ", __FUNCTION__, data);
    NODE *cur = head;
    NODE *prev = cur;
    NODE *temp = NULL;

    if (head == NULL) {
        assert (tail == NULL);
        printf("Empty list \n");
        return;
    }

    if (head->data == data) {
        temp = head;

        // one element list
        if (head == tail)
            head = tail = NULL;
        else
            // list has more than one element
            head = head->next;

        printf("%d \n", temp->data);
        free(temp);
        deleteitem(data);
        return;
    }

    while (cur != NULL) {
        if (cur->data == data) {
            if (cur == tail) {
                tail = prev;
            }
            prev->next = cur->next;
            printf(" %d deleted\n", cur->data);
            free(cur);
            assert(tail->next == NULL);
            deleteitem(data);
            return;
        }
        prev =cur;
        cur = cur->next;
    }

    printf(" %d not found\n", data);
    return;
}