先來看一個不優雅的寫法:
remove_list_entry(entry)
{
prev = NULL;
walk = head;
while (walk != entry) {
prev = walk;
walk = walk->next;
}
if (!prev)
head = entry->next;
else
prev->next = entry->next;
}
之所以說上面的代碼不夠優雅,相信大家肯定能感覺出來,主要就是需要對是否是頭結點進行額外的判斷,
因爲使用了prev這個變量來輔助,那麼怎麼寫纔算是優雅呢?如下:
remove_list_entry(entry)
{
indirect = &head;
while ((*indirect) != entry)
indirect = &((*indirect)->next);
*indirect = entry->next;
}
這個代碼是不是比上面的更簡潔呢。不需要進行額外的處理,同樣可以移除節點。
下面簡單解釋一下,
可以把indirect作爲一個指向每個元素next成員的地址,注意不是下一個元素的地址!
(next成員也是元素的一部分,它也佔有空間,也有地址)
下一個成員的地址是(*indirect)->next.
那麼刪除下一個元素節點,直接修改*indirect = new_elem就好了。(最後一行代碼)
就是修改了當前節點next的指向。
當要移除head時,indirect爲&head, *indirect = entry->next,就讓head指向了下一個節點(移除了head).
不從進行額外的處理。
無論是在開始時,還是中間某個結點,indirect都是有意義的,不爲NULL, 所以最後一行纔可直接修改。
當然,indirect不論指向head還是next域,都是一個二級指針(類型一定)
如下圖:
head是個指針,並非鏈表中的數據內容。
上面的兩個代碼片段是Linus大神在TED訪談時作的比較。