[Happy DSA] 刪除單鏈表中任意一個節點的方法

在閱讀c-algorithms代碼時,又看到如下的代碼(刪除單鏈表中任意一個節點)

/* A singly-linked list */

struct _SListEntry {
     SListValue data;
     SListEntry *next;
};

int slist_remove_data(SListEntry **list, SListEqualFunc callback, SListValue data)
{
     SListEntry **rover;
     SListEntry *next;
     int entries_removed;

     entries_removed = 0;

     /* Iterate over the list.  'rover' points at the entrypoint into the
     * current entry, ie. the list variable for the first entry in the
     * list, or the "next" field of the preceding entry. */
    
     rover = list;

     while (*rover != NULL) {
         
          /* Should this entry be removed? */
         
          if (callback((*rover)->data, data) != 0) {               
               /* Data found, so remove this entry and free */
               next = (*rover)->next;
               free(*rover);
               *rover = next;
              
               /* Count the number of entries removed */
               ++entries_removed;
          } else {               
               /* Advance to the next entry */
               rover = &((*rover)->next);
          }
     }

     return entries_removed;
}

上面的函數實現不僅可以去除頭節點,也可以去除中間的任意節點。它依賴的技巧就是節點指針的指針:用節點指針的指針來保存前面一個節點的next域的指針,從而在去除當前節點之前,可以將當前節點的下一個節點link/assign到那個保存的next指針域中。

我們通常的做法可能會區分對待頭節點,並維護一個prev節點指針。

上面的方法巧妙並且通用的解決了上面的問題。
找到一張以前畫的示意圖(跟上面的代碼變量定義有些出入):


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