双向链表的插入删除操

对于不是循环的双向链表:

写成程序时画图示意一下:几个特殊点注意一下尤其注意空指针

插入结点分为: 双向链表为空, 和双向链表表非空两种情况

删除结点分为 删除头结点和删除其他结点两种情况 在删除头结点时需注意: 双向链表只含一个头结点的情况和含有多个结点删除头结点的情况

删除其他结点时需注意 删除尾结点时,指针的特殊情况

双向非循环链表的操作和单链的操作基本一致:


双向非循环链表的插入和删除操作参考代码:

#include<iostream>
#include<cstdio>
#include<cstdlib>
using namespace std;
//以下为双向链表的操作
typedef struct DoubleListNode
{
     int data;
	 DoubleListNode *prior,*next;
}DoubleListNode;
//尾插法建立双向链表 
void AddNodeToTail(DoubleListNode**pHead,int value)//插入结点分为: 双向链表为空, 和双向链表表非空两种情况
{
    DoubleListNode *pNew=new DoubleListNode;
	pNew->data=value;
	pNew->prior=pNew->next=NULL;
	if(*pHead==NULL)
	{
	     *pHead=pNew;
	}
	else
	{
	     DoubleListNode* pNode=*pHead;
		 while(pNode->next!=NULL)//找到尾结点
		 {
			 pNode=pNode->next;
		 }
		 pNode->next=pNew;
		 pNew->prior=pNode;
	}
}
//删除结点分为:  删除头结点和删除其他结点两种情况, 在删除头结点时需注意: 双向链表只含一个头结点的情况和含有多个结点删除头结点的情况
//删除其他结点时需注意 删除尾结点的是指针的特殊情况
void RemoveNode(DoubleListNode**pHead,int value)
{
     if(pHead==NULL||*pHead==NULL)
	 {
	    return ;
	 }
	 DoubleListNode *pToBeDelete=NULL;
	 if((*pHead)->data==value)//删除双向链表的头结点
	 {
	      pToBeDelete=*pHead;
		  *pHead=(*pHead)->next;
		  if(*pHead!=NULL)//此种情况为删除只有一个头结点的情况
		  {
			(*pHead)->prior=NULL;
		  }
	 }
	 else//删除双向链表中的其它结点
	 {
	     DoubleListNode *pNode=*pHead;
		 while(pNode->next!=NULL&&pNode->next->data!=value)//找到删除结点的前驱结点
		 {
		     pNode=pNode->next;
		 }
		 if(pNode->next!=NULL&&pNode->next->data==value)
		 {
		      pToBeDelete=pNode->next;
			  pNode->next=pToBeDelete->next;
			  if(pToBeDelete->next!=NULL)//考虑删除尾结点的情况
			  {
			  pToBeDelete->next->prior=pNode;
			  }
		 }
	 }
	 if(pToBeDelete!=NULL)
	 {
	     delete pToBeDelete;
		 pToBeDelete->prior=pToBeDelete->next=NULL;
	 }
}
void PrintList(DoubleListNode*pHead)
{
     if(pHead==NULL)
	 {
	     return;
	 }
	 DoubleListNode *pNode=pHead;
	 while(pNode!=NULL)//对于单链表的判断此处while(pNode!=NULL)
	 {
	      cout<<pNode->data<<" -->";
		  pNode=pNode->next;
	 }
	 cout<<"NULL"<<endl;
}
int main()
{
   DoubleListNode *pHead=NULL;
   for(int i=1;i<=10;i++)
   {
        AddNodeToTail(&pHead,i);
   }
   PrintList(pHead);
    RemoveNode(&pHead,7);//删除中间结点
	 PrintList(pHead);

    for(int i=1;i<=10;i++)//一直删除头结点
   {
       RemoveNode(&pHead,i);
	  PrintList(pHead);
   }
    for(int i=1;i<=10;i++)
   {
        AddNodeToTail(&pHead,i);
   }
   PrintList(pHead);
   for(int i=10;i>=0;i--)//一直删除尾结点
   {
      RemoveNode(&pHead,i);
	  PrintList(pHead);
   }
   
   return 0;
}

双向循环操作的考虑的东西要稍微多一点点:


基本也一样:


#include<iostream>
#include<cstdio>
#include<cstdlib>
using namespace std;
//以下为双向循环链表的操作
typedef struct DoubleListNode
{
     int data;
	 DoubleListNode *prior,*next;
}DoubleListNode;
//尾插法建立循环双向链表   对于非空双向循环链表先找到尾结点pNode=(*Phead)->prior;
void AddNodeToTail(DoubleListNode**pHead,int value)
{
    DoubleListNode *pNew=new DoubleListNode;
	pNew->data=value;
	pNew->prior=pNew->next=NULL;
	if(*pHead==NULL)//注意对于尾插法的循环双向链表来说,(*pHead)->prior 即为尾节点 插入很容易
	{
	     *pHead=pNew;
		 pNew->next=pNew->prior=pNew;
	}
	else
	{
	     DoubleListNode *pNode= (*pHead)->prior;//pNode 指向了原来的尾结点
		 pNew->next=*pHead;//尾插法新节点的后继为头结点
		 pNew->prior=pNode;
		 pNode->next=pNew;
		 (*pHead)->prior=pNew;
		 
	}
}
void RemoveNode(DoubleListNode**pHead,int value)
{
     if(pHead==NULL||*pHead==NULL)
	 {
	    return ;
	 }
	 DoubleListNode *pToBeDelete=NULL;
	 if((*pHead)->data==value&&(*pHead)->next==(*pHead))//删除只含一个结点循环双向链表 此处的条件一定不能错
	 {
	      pToBeDelete=*pHead;
		  *pHead=NULL;
	 }
	 else if((*pHead)->data==value)//删除含多个元素的头结点
	 {
	      pToBeDelete=*pHead;
		  *pHead=(*pHead)->next;//原先头结点的的下个结点更新为新的头指针
		  (*pHead)->prior=pToBeDelete->prior;//头结点的前驱指向尾结点
		  pToBeDelete->prior->next=*pHead;//尾结点的后继指向头结点
	 }
	 else//删除双向链表中的其它结点
	 {
	     DoubleListNode *pNode=*pHead;
		 while(pNode->next!=(*pHead)&&(pNode->next->data!=value))//找到删除结点的前驱结点
		 {
		     pNode=pNode->next;
		 }
		 if(pNode->next!=(*pHead)&&(pNode->next->data==value))
		 {
		      pToBeDelete=pNode->next;
			  pNode->next=pToBeDelete->next;//这里绝对不能搞错。
			  pToBeDelete->next->prior=pNode;
		 }
	 }
	 if(pToBeDelete!=NULL)
	 {
	     delete pToBeDelete;
		 //pToBeDelete->prior=pToBeDelete->next=NULL;
	 }
}
void PrintList(DoubleListNode*pHead)
{
     if(pHead==NULL)
	 {
	     return;
	 }
	 DoubleListNode *pNode=pHead;
	 while(pNode->next!=pHead)//对于单链表的判断此处while(pNode!=NULL)
	 {
	      cout<<pNode->data<<" -->";
		  pNode=pNode->next;
	 }
	 cout<<pHead->prior->data<<" -->";//打印最后一个结点
	 cout<<"NULL"<<endl;
}
int main()
{
   DoubleListNode *pHead=NULL;
   for(int i=1;i<=10;i++)
   {
        AddNodeToTail(&pHead,i);
   }
   PrintList(pHead);
    RemoveNode(&pHead,7);//删除中间结点
	 PrintList(pHead);

    for(int i=1;i<=10;i++)//一直删除头结点
   {
       RemoveNode(&pHead,i);
	  PrintList(pHead);
   }
    for(int i=1;i<=10;i++)
   {
        AddNodeToTail(&pHead,i);
   }
   PrintList(pHead);
   for(int i=10;i>=0;i--)//一直删除尾结点
   {
      RemoveNode(&pHead,i);
	  PrintList(pHead);
   }
   
   
   return 0;
}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值