在O(1)時間刪除連結串列結點
阿新 • • 發佈:2019-01-01
這道題題目可以描述為:給定單向連結串列的頭指標和一個結點指標,定義一個函式在O(1)時間刪除該結點。
本文中有關連結串列的結構體以及介面定義如下:
typedef int DataType;
typedef struct ListNode{
DataType data;
struct ListNode *next;
} ListNode;
//初始化
void ListInit(ListNode **ppfirst)
{
assert(ppfirst != NULL);
*ppfirst = NULL;
}
這道題的思路可以理解為:如果要刪除結點i,先把i的下一個結點j的內容複製到i,然後把i的指標指向結點j的下一個結點,此時再刪除結點j,其效果剛好是把結點i刪除了。如下圖:
我們應該注意,對於尾結點,從頭結點開始遍歷找到為結點的前一個結點,然後完成刪除操作;如果連結串列中只有一個結點,即刪除頭結點,刪除之後把連結串列的頭結點置為NULL。
程式碼如下:
void DeleteNode(ListNode **phead, ListNode *pdelete) { assert(phead && pdelete); //要刪除的不是尾結點 if (pdelete->next != NULL) { ListNode *pnext = pdelete->next; pdelete->data = pnext->data; pdelete->next = pnext->next; free(pnext); pnext = NULL; } //刪除頭結點 else if (*phead == pdelete) { free(pdelete); pdelete = NULL; *phead = NULL; } //刪除尾結點 else { ListNode * pNode =* phead; while (pNode->next != pdelete) { pNode = pNode->next; } pNode->next = NULL; free(pdelete); pdelete = NULL; } }
對於這種思路的複雜度可以解釋為對於n-1個非尾結點,可以在O(1)時把這個結點刪除;對於尾結點,由於要遍歷查詢,它的時間複雜度為O(n);因此總的平均時間複雜度為[(n-1)*O(1)+O(n)]/n,結果還是O(1),符合題目要求。