一般我们在进行单向链表链表的结点删除操作时,都是通过相应的结构体指针进行链表的遍历,然后找
到需要删除的节点,为了完成删除操作,我们需要在寻找该节点时,不断地记录下这个节点前面的节点
(prev),来保证当特定结点被删除后,我们还可以将断开的链表重新连起来,下面给出一段伪码:
remove_list_entry(entry){prev = NULL;walk = head;// Walk the listwhile (walk != entry){prev = walk;walk = walk -> next;}
// Remove the entry by updating the // head or the previous entryif (!prev)head = entry->next;elseprev->next = entry->next;
}
原理如下图
(该段代码没有考虑待删除节点不在链表中的情况)
另外,这段代码还考虑到一个特殊情况,待删除的节点不是中间节点,而是头结点(head).而这段代码也是大多数学校的老师或者是书上教我们的.
然而,下面的代码也可以完成同样的功能(伪码):
remove_list_entry(entry){// The "indirect" pointer points to the // *address* of the thing we'll updateindirect = &head;// Walk the list, looking for the thing that// poins to the entry we want to remove_list_entrywhile ((*indirect) != entry){indirect = &((*indirect)->next);}// .. and just remove it*indirect = entry -> next;}
看到这段代码我觉得大多数人的第一印象就是很简洁,很骚(帅),没有if-else,不管我们需要删除的头结点还是中间节点,都可以用相同的逻辑来表达.
而这段代码使用的就是我们不经常使用的指针的指针,同过它,消除了if-else,消除了previous,使代码变得更优雅,我喜欢这个词/cy
关键点就是indirect这个指针第一次指向的是head的地址,第二次指向的是节点1.next的地址,第三次指向的是节点2.next的地址.
通过比较,可以知道第一段代码并不好,它需要第一个节点和中间节点,有特例.
而第二段代码展示了一种不同的方式,可以把一个特例当成正常情况来处理,这就是好的代码,优雅的代码.