O 1 時間刪除鍊錶結點

2021-07-11 15:22:56 字數 1665 閱讀 4351

題目:給定單向鍊錶的頭指標和乙個結點指標,定義乙個函式在o(1)時間刪除該結點。鍊錶結點與函式的定義如下:

typedef struct listnode

node, *pnode;

void delete_node(pnode *plisthead, pnode ptodeleted);
一般來說,我們拿到乙個刪除鍊錶的某個結點的題目,最常規的解法無疑是從鍊錶的頭結點開始順序遍歷,依次查詢要刪除的結點,找到被刪除結點的前乙個結點後,就可以在鍊錶中刪除結點。就像下面這樣:

假設要刪除的結點是b,那就先找到b的前乙個結點a,然後使a的下乙個結點變為c,最後釋放b。當然如果整個鍊錶中只有乙個結點為b結點,那麼b就是頭結點了,算是一種特殊情況。

顯而易見,因為這個演算法需要遍歷整個鍊錶,所以它的時間複雜度是o(n)。並不是我們想要的結果。那就只好另闢蹊徑了。

圖示如下:

這種思路的做法是,因為我們要刪的結點是b,而且已經給了指向b結點的指標,那麼我們可以在o(1)時間內直接找到的結點就是它了。找到了b結點,那麼b的下乙個結點c肯定也找到了,我們用c的值覆蓋掉b,然後在刪掉最後的c結點。這樣不也相當於刪除了結點b嗎?而且時間複雜度自然是o(1)了。

這個思路還有乙個問題,就是如果要刪除的結點是尾結點怎麼辦,那它就沒有下乙個結點了,這種情況下我們只好採用第一種思路了。

最後需要注意的是,如果鍊錶中只有乙個結點,而我們刪除的就是頭結點,那麼在刪除結點之後,還需要把頭結點置為null。

下面就是這種思路的具體實現了:

void delete_node(pnode *plisthead, pnode ptodeleted)

else if (null != ptodeleted->p_next && (*plisthead)->val != ptodeleted->val) //待刪結點不是尾指標也不是頭指標

else //是尾指標但不是頭指標,需要遍歷整個鍊錶

free(ptodeleted);

ptodeleted = null;

tmp->p_next = null; }}

void print(pnode head)

printf("\n");

}int main()

再來分析一下這個思路的時間複雜度,對(n-1)個非尾結點而言,時間複雜度為o(1);而對於尾結點而言,由於仍然需要遍歷查詢,所以時間複雜度是o(n)。

所以總的平均時間複雜度是[(n - 1) * o(1) + 1 * o(n)] / n ,結果仍然是o(1)。

還要注意的是,上邊我們寫的**並不是完整的**。仔細想想,我們就可以發現,這個程式是建立在要刪除的結點一定在鍊錶上存在的基礎上。但是要判斷乙個1結點是否在鍊錶上,需要o(n)的時間複雜度。所以保證鍊錶上存在要刪除的結點這一責任就拋給了這個函式的呼叫者。這是不得已而為之。

O 1 時間刪除鍊錶結點

題目 給定鍊錶的頭指標和乙個結點指標,在 o 1 時間刪除該結點。鍊錶結點的定義如下 struct listnode 函式的宣告如下 void deletenode listnode plisthead listnode ptobedeleted 分析 這是一道廣為流傳的 google 面試題,能有...

在O 1 時間刪除鍊錶結點

題目 給定單向鍊錶的頭指標和乙個結點指標,定義乙個函式在o 1 時間刪除該結點。鍊錶結點與函式的定義如下 struct listnode void deletenode listnode plisthead,listnode ptobedeleted 刪除結點的操作我們經常碰到,比如乙個鍊錶a b ...

在O 1 時間刪除鍊錶結點

問題描述 給定單向鍊錶的頭指標和乙個結點指標 定義乙個函式在o 1 時間刪除鍊錶結點。鍊錶結點與函式的定義如下 struct listnode void deletenode listnode plisthead listnode ptobedeleted 思路 在單向鍊錶中刪除乙個結點,最常用的做...