如何理解二级指针删除单向链表
利用二级指针删除单向链表的代码如下:
1 void remove_if(node ** head, remove_fn rm)
2 {
3 for (node** curr = head; *curr; )
4 {
5 node * entry = *curr;
6 if (rm(entry))
7 {
8 *curr = entry->next;
9 free(entry);
10 }
11 else
12 curr = &entry->next;
13 }
14 }
顺便看了这篇文章的评论,每个人都提出了自己对这段代码的理解,但我还是觉得没有说到点上。如不嫌弃,不妨试试跟我的思路来理解一下:
首先,我们做这样两个假设:
1. 操作系统为链表分配内存的时候,链表中的各项恰好是紧挨着的;
2. 除非链表被完全删除,否则,链表中的各项所在的内存不会被占用,我们仍然可以安全的访问到它们;
那么上面的代码等价于这样:
void remove_if(node **arr, remove_fn rm)
{
node **curr = arr;
for (int i = 0; i < 10; i++)
{
node *entry = cur[i];
if (entry == NULL)
{
continue
}
if (rm(entry))
{
free(entry);
entry = NULL;
}
}}
大致解释一下上面的实现:由于假设1,访问链表中的下一个元素可以不再通过next指针,而是“表头+偏移量”的方式,由于假设2,我们总是能安全的访问已删除表项的内存。
通过上面的例子,利用二级指针删除单向链表的节点就很好理解了:其实就是从一个指针数组中删除指定的项目,只不过,这个数组是匿名的,引入的二级指针正好充当了这个数组的名称;另外,这个数组在内存中并不是连续的,所以我们在每个节点处需要维护一个指向下一个数组项的next指针。当这个指针是NULL的时候,表示这是数组的最后一项了,我们可以改变这个NULL为非NULL,这是后就是添加了一个新的链表节点,然后重新设置数组的长度,也就是把新的节点的next域设置为NULL托福答案 www.tfjy386.com