关于从链接列表中删除节点时释放节点

时间:2014-02-25 00:08:30

标签: c linked-list free

以下是删除链接列表中重复元素的功能

void deleteDup(Node *head)
{
    Node *ptr1, *ptr2, *prev;

    for (ptr1 = head; ptr1 != NULL; ptr1 = ptr1->next){

        prev = ptr1;

        for (ptr2 = ptr1->next; ptr2 != NULL; prev = ptr2, ptr2 = ptr2->next){
            if (ptr1->value == ptr2->value){
                prev->next = ptr2->next;
                free(ptr2);    // Question 1
            }
        }
    }    
}

问题1:以上代码适用于(1->1->2->3->1)。但在完成之后,我自己也感到困惑。

困惑:当它释放ptr2时它是如何在循环中向前移动的?释放ptr2后,prev = ptr2, ptr2 = ptr2->next不应该出现seg错误吗?

问题2:此代码可以优化吗? (即节省资源或提高绩效)

2 个答案:

答案 0 :(得分:1)

问题1:
确实存在问题。一般来说,你必须期望未定义的行为 (可以,但不一定是段错误 也可以没有错误地运行,但只能“可以”,不会。

for (ptr2 = ptr1->next; ptr2 != NULL;){
    if (ptr1->value == ptr2->value){
        prev->next = ptr2->next;
        free(ptr2);    // Question 1
    }
    else prev = ptr2;
    ptr2 = prev->next;
}

这样的事情应该做(也许。我累了。)

问题2:最佳内存优化:
用指针删除列表并使用数组:p
时间选择:太。其他数据结构更适合这样的东西。
如果您在此过程中愿意留下更多记忆, 迭代列表并将每个元素插入到不同的数据中,例如某种树 在那里你可以很容易地检查元素是否在之前发生过 (并且在此仅一次迭代期间将其从列表中删除)

答案 1 :(得分:0)

绘制一个(部分)结构图,就像它在开头看一样。也许需要几个覆盖案例,如有趣的节点是第一个/最后一个/唯一一个。现在仔细考虑图表代码中的每个操作,在每个步骤之后检查没有出错。

同样的策略在确定如何进行操作时有效:图表之前/之后,以及如何从开始到结束。