【问题标题】:Removing all nodes with a certain value in a linked list删除链表中具有特定值的所有节点
【发布时间】:2012-01-26 19:19:19
【问题描述】:

标题很容易解释。这是我为此目的编写的函数:

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;      
    }
}

【问题讨论】:

  • 你能告诉我们cell的定义吗?
  • 提示:如果您使用笔和纸并在此基础上手写要执行的步骤并编写代码,则链接列表问题会更容易解决。

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


【解决方案1】:

如果

tmp = tail->next; 

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

您应该检查这种情况并采取适当的措施。

【讨论】:

  • +1,我认为实际上他只需要tmp = tail(或者根本没有tmp),否则他正在跳过第二个元素。
  • 你让我意识到我没有条件何时 'tmp' 指向最后一个节点并且该节点不会被删除。在这种情况下,'tail' 移动到最后一个节点,'tmp' 确实变为 'NULL',并且当我尝试读取 'tmp->next' 时发生访问冲突。我已在我的原始帖子中添加了修复程序,感谢您发人深省的评论。
【解决方案2】:

单链表中正确的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;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-09-02
    • 1970-01-01
    • 2020-11-12
    • 2022-01-05
    • 2023-02-14
    相关资源
    最近更新 更多