今天看到linus曾经提到的一个指针的指针操作单链表的技巧,挺有意思的,记录一下。
原文:
http://meta.slashdot.org/story/12/10/11/0030249/linus-torvalds-answers-your-questions
I've seen too many people whodelete a singly-linked list entry by keeping track of the "prev"entry, and then to delete the entry, doing something like
if (prev)prev->next = entry->next;
else
list_head = entry->next;
and whenever I see code like that, I just go "This person doesn'tunderstand pointers". And it's sadly quite common.
People who understand pointers just use a "pointer to the entrypointer", and initialize that with the address of the list_head. Andthen as they traverse the list, they can remove the entry withoutusing any conditionals, by just doing a "*pp = entry->next".
即,在单链表中删除元素时,通常的做法是判断待删除元素的prev是否存在,如果存在则让该元素的prev的next指向该元素的next,如果prev不存在,则让list_head指向该元素的next:
Node* entry = list_head;
Node* prev = NULL;
while(entry){
if(entry->needRemove()){
if(prev)
prev->next = entry->next;
else
list_head = entry->next;
Node *next = entry->next;
free(entry);
entry = next;
}
else{
prev = entry;
entry = entry->next;
}
}
linus说,这么做的人不懂指针。。。高手就是高手,霸气。
好吧,看看linus的做法:
Node** pp = &list_head;
while(*pp){
if((*pp)->needRemove()){
Node* entry = *pp;
*pp = entry->next;
free(entry);
}
else{
pp = &(*pp)->next;
}
}
用指针的指针去遍历单链表,如果不去删除元素,当然是没有必要,但是如果要删除元素,简单的一句:*pp = entry->next 就可以达到prev->next=entry->next的效果,而且不用判断prev是否存在,因为pp永远指向prev->next,当没有prev时, pp指向list_head。且不用在删除前保存prev这个指针。
不得不说,确实精妙。