在 O(1) 時間刪除單鏈表結點

題目:給定單鏈表的頭指針和一個結點指針,定義一個函數,在 O(1) 時間刪除該節點。ios

分析:在單向鏈表中刪除一個節點,最常規的作法無疑是從鏈表的頭結點開始,順序遍歷查找要刪除的節點並在鏈表中刪除該節點。以下圖,這種思路因爲須要順序查找,時間複雜度天然是 O(N)。函數

    之因此須要從頭開始查找,是由於須要找到被刪除節點的前一個節點,在單向鏈表中,因爲沒有指向前一個節點的指針,只好從鏈表的頭結點開始順序查找。spa

    然而是否是必定要獲得被刪除的節點的前一個節點呢?答案是否認的。咱們能夠方便的獲得要刪除節點的下一個節點,若是將下一個節點的內容複製到須要刪除的節點上,覆蓋原有的內容,再把下一個節點刪除,就至關於把當前須要刪除的節點刪除了。指針

  這個思路有一個問題,若是要刪除的節點位於鏈表的尾部,那麼它就沒有下一個節點。此時,咱們仍然須要從鏈表的頭結點開始,順序遍歷獲得該節點的前序節點,並完成刪除操做。內存

    最後注意的是:若是鏈表中只有一個節點,而又要刪除鏈表的頭結點(也就是尾節點),此時在刪除節點以後,須要把鏈表的頭指針設置爲 NULL。ci

 

//在O(1) 的時間內,刪除單鏈表節點
#include<iostream>
using namespace std;
路由

typedef int ElemType;
typedef struct LNode
{
 ElemType data;
 struct LNode *next;
}ListNode, *LinkList;
it

LinkList InitializeLinkList(LNode *L)
{
 if(L == NULL)
 {
  L = new LNode();
  L->next = NULL;
 }
io

 return L;
}
stream

void InsertLinkList(LinkList L, ElemType value)
{
 if(L == NULL)
  return;
 LNode *p, *tmp;
 tmp = L;
 p = new LNode();
 p->data = value;
 p->next = tmp->next;
 tmp->next = p;
}

void PrintLinkList(LinkList L)
{
 if(L->next == NULL)
  return;
 LNode *p;
 p = L->next;
 while(p != NULL)
 {
  cout << p->data << " ";
  p = p->next;
 }
 cout << endl;
}

void DeleteNode(ListNode *pListHead, ListNode *pToDeleted)
{
 if(!pToDeleted || !pListHead)
  return;
 //要刪除的節點不是尾節點
 if(pToDeleted->next != NULL)
 {
  ListNode *pNext = pToDeleted->next;
  pToDeleted->data = pNext->data;
  pToDeleted->next = pNext->next;

  delete pNext;
  pNext = NULL;
 }
 //鏈表只有一個節點,刪除頭結點(也就是尾節點)
 else if(pListHead == pToDeleted)
 {
  delete pToDeleted;
  pToDeleted = NULL;
  pListHead = NULL;
 }
 //鏈表中有多個節點,刪除尾節點(此時要遍歷單鏈表)
 else
 {
  ListNode *pNode = pListHead;
  while(pNode->next != pToDeleted)
  {
   pNode = pNode->next;
  }
  pNode ->next = pToDeleted->next;
  delete pToDeleted;
  pToDeleted = NULL;
 }
}

int main()
{
 LNode *L;
 L = NULL;
 L = InitializeLinkList(L);
 int value;
 while(cin >> value)
 {
  InsertLinkList(L, value);
 }
 PrintLinkList(L);

 ListNode *pToDeleted = L->next;
 for(int i = 0; i < 4; i++)
 {
  pToDeleted = pToDeleted->next;
 }
 DeleteNode(L, pToDeleted);
 PrintLinkList(L);

 system("pause");
 return 0;
}

分析時間複雜度:對於 n - 1 個非尾節點而言,能夠在 O(1) 時把下一個節點的內存複製附帶要刪除的節點,並刪除下一節點;對於尾節點而言,因爲仍然須要順序查找,時間複雜度是 O(N),所以,總的時間複雜度爲 [(n - 1) * O(1) + O(N)] / N, 結果仍是O(1)。

可是,該方法是基於一個假設:要刪除的節點的確存在於鏈表中。

相關文章
相關標籤/搜索