在单向链表中删除一个结点,最常规的方法是从链表的头结点开始,顺序遍历,查找要删除的结点。如果该结点在链表中,则删除该结点。这种情况通常是指明要删除的值,我们要通过比较链表中结点的值与给定的值是否相等来判断链表是否存在该结点。这种方法的时间复杂度是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;
}