優雅地移除節點

先來看一個不優雅的寫法:

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訪談時作的比較。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章