在單向鏈表中刪除一個結點,最常規的方法是從鏈表的頭結點開始,順序遍歷,查找要刪除的結點。如果該結點在鏈表中,則刪除該結點。這種情況通常是指明要刪除的值,我們要通過比較鏈表中結點的值與給定的值是否相等來判斷鏈表是否存在該結點。這種方法的時間複雜度是O(n)。
具體分析方法:當要刪除的結點是鏈表的尾結點時,無法用後一結點來覆蓋,所以只能採用從頭遍歷;當要刪除的結點不是尾結點時,可以用後一結點的值及指向再後一結點的指針來覆蓋要刪除的結點,然後再把要刪除結點的後一結點刪除,也就相當於把要刪除的結點刪除了。當然這個前提是要刪除的結點得在鏈表中。
如果給定的是鏈表中的結點,而不是值,則進行刪除時可以用後一結點的值來覆蓋要刪除的結點,然後再把要刪除的結點的後一結點刪除即可。這種方法的時間複雜度是O(1)。
下面是具體的代碼:
鏈表結點.h
struct ListNode
{
int mvalue;
ListNode *next;
};
#include <iostream>
#include "鏈表結點.h"
using namespace std;
ListNode *creatList();
ListNode *DeleteNode(ListNode *pHead,ListNode *pToBeDeleted);//直接指明要刪除的結點
ListNode *DeleteNode1(ListNode *pHead,int vtobedelete);//指明要刪除的值
int main()
{
ListNode* pHead=creatList();
ListNode *pnode=pHead;
cout <<"創建的鏈表爲:" <<endl;
while(pnode!=NULL)
{
cout <<pnode->mvalue <<" ";
pnode=pnode->next;
}
cout <<endl;
ListNode *pnode1=pHead;
ListNode *ptbd=pnode1->next;
ListNode *pnode2=pHead;
//判斷要刪除的結點是否在鏈表中
while(pnode1!=NULL)
{
if (pnode1==ptbd)
{
cout <<"要刪除的結點在該鏈表中!" <<endl;
pnode2=DeleteNode(pHead,ptbd);
break;
}
else
{
pnode1=pnode1->next;
if (pnode1==NULL)
{
cout <<"要刪除的結點不在該鏈表中!" <<endl;
}
}
}
if (pnode2!=NULL)
{
cout<<"新的鏈表爲:" <<endl;
while(pnode2!=NULL)
{
cout <<pnode2->mvalue <<" ";
pnode2=pnode2->next;
}
cout <<endl;
}
else
cout <<"新鏈表爲空!" <<endl;
// pnode1=DeleteNode1(pHead,-1);
return 0;
}
ListNode *creatList()
{
int mvalue=0;
ListNode* pHead=new ListNode();
ListNode* pNode=pHead;
while((mvalue+1) != 0)
{
cin>>mvalue;
ListNode *pNew=new ListNode();
pNew->mvalue=mvalue;
pNew->next=NULL;
pNode->next=pNew;
pNode=pNew;
}
pHead=pHead->next;
return pHead;
}
ListNode* DeleteNode(ListNode *pHead,ListNode *ptobedeleted)
{
if (pHead==NULL || ptobedeleted==NULL)
{
cout <<"ERROR!" <<endl;
return NULL;
}
//刪除的不是尾結點,此時可以讓後一結點覆蓋要刪除的節點,再刪除後一結點(降低時間複雜度)
if (ptobedeleted->next!=NULL)
{
ListNode *pnext = ptobedeleted->next;
ptobedeleted->mvalue = pnext->mvalue;
ptobedeleted->next = pnext->next;
delete pnext;
pnext=NULL;
}
//只有一個結點
else if(pHead==ptobedeleted && pHead->next==NULL)
{
delete ptobedeleted;
ptobedeleted=NULL;
pHead=NULL;
}
//不是隻有一個結點,刪除的是尾結點,此時只能從鏈表頭結點開始遍歷,找到刪除結點的前一個結點,再進行刪除
else if (pHead!=ptobedeleted && ptobedeleted->next==NULL)
{
ListNode *p=pHead;
while(p->next!=ptobedeleted)
{
p=p->next;
}
p->next=NULL;
delete ptobedeleted;
ptobedeleted=NULL;
}
return pHead;
}
//從頭結點開始遍歷,找到要刪除的結點和它的前一結點
ListNode* DeleteNode1(ListNode *pHead,int vtobedelete)
{
ListNode *pre=NULL,*cur=pHead;
//頭結點是要刪除的結點
if (cur->mvalue==vtobedelete)
{
pre=cur;
cur=cur->next;
pHead=cur;
delete pre;
pre=NULL;
if(pHead!=NULL)
cout <<"新的鏈表爲:" <<endl;
else
cout <<"新的鏈表爲空!" <<endl;
}
else
{
while(cur!=NULL && cur->mvalue!=vtobedelete)
{
pre=cur;
cur=cur->next;
}
//鏈表中有要刪除的值
if (cur!=NULL && cur->mvalue==vtobedelete)
{
ListNode *p=cur;
pre->next=cur->next;
delete p;
p=NULL;
cout <<"新的鏈表爲:" <<endl;
}
//鏈表中沒有要刪除的值
else if(cur==NULL)
cout<<"NO THIS NODE!" <<endl;
}
return pHead;
}