双向链表的插入、删除

双向链表

双向链表(Doubly Linked List)是一种更复杂的链表结构,它允许链表中的节点在两个方向上链接。在双向链表中,每个节点包含两个链接:一个指向前一个节点(如果它不是第一个节点的话),另一个指向下一个节点(如果它不是最后一个节点的话)。此外,每个节点还包含一个数据元素。

这种结构提供了更高的灵活性,因为它允许我们从链表的任何一端开始遍历,或者在链表中的任何位置进行插入和删除操作。然而,这种灵活性也带来了更高的复杂性,因为每个节点都需要存储两个链接而不是一个。

双向链表的主要优点是它可以向前和向后遍历。这使得双向链表在需要频繁进行插入和删除操作的情况下非常有用,特别是在链表的中间部分。然而,由于每个节点都需要额外的空间来存储链接,所以双向链表在内存使用上可能不如单向链表高效。

在实际应用中,双向链表常用于实现一些需要双向遍历的数据结构,如撤销/重做操作、双向队列等。

本文将展示双向链表的插入与删除(最后附上完整代码)。

双向链表头部插入

/*******************************************************************
*
*	函数名称:	DoubleLList_HeadInsert
*	函数功能:   在链表头部插入新的结点
* 	函数参数:
*  				@a :DoubleLList_t *Head  头结点 
*  				@b :DataType_t data 新结点的数据域
*   返回结果:   
* 	注意事项:   None
* 	函数作者:  m17872844806@163.com
*	创建日期:   2024/04/25
*	修改历史:
*	函数版本:	V1.0
* *****************************************************************/
bool DoubleLList_HeadInsert(DoubleLList_t *Head,DataType_t data)
{
	DoubleLList_t *New = DoubleLList_NewNode(data);
	DoubleLList_t *Phead = Head;

	if (Head->next == NULL)
	{
		Head->next=New;
		return true;
	}
  	while(Phead->next)
 	{
		Phead=Phead->next;

	}
	New->next=Head->next;
	Head->next->prev=New;
	Head->next=New;
	return true;
}

双向链表尾部插入

/*******************************************************************
*
*	函数名称:	 DoubleLList_TailInsert
*	函数功能:   在链表尾部插入新的结点
* 	函数参数:
*  				@a :DoubleLList_t *Head  头结点 
*  				@b :DataType_t data 新结点的数据域
*   返回结果:   
* 	注意事项:   None
* 	函数作者:  m17872844806@163.com
*	创建日期:   2024/04/25
*	修改历史:
*	函数版本:	V1.0
* *****************************************************************/
bool DoubleLList_TailInsert(DoubleLList_t *Head,DataType_t data)
{
	DoubleLList_t *New = DoubleLList_NewNode(data);
	DoubleLList_t *Phead = Head;

	if (Head->next == NULL)
	{
		Head->next=New;
		return true;
	}
  	while(Phead->next)
 	{
		Phead=Phead->next;

	}
	Phead->next=New;
	New->prev=Phead;
	return true;
}

双向链表指定部位插入

/*******************************************************************
*
*	函数名称:	 DoubleLList_DestInsert
*	函数功能:   在链表指定部位后面插入新的结点
* 	函数参数:
*  				@a :DoubleLList_t *Head  头结点 
*  				@b :DataType_t data 新结点的数据域
*   返回结果:   
* 	注意事项:   None
* 	函数作者:  m17872844806@163.com
*	创建日期:   2024/04/25
*	修改历史:
*	函数版本:	V1.0
* *****************************************************************/
bool DoubleLList_DestInsert(DoubleLList_t *Head,DataType_t dest,DataType_t data)
{
	DoubleLList_t *New = DoubleLList_NewNode(data);
	DoubleLList_t *Phead = Head;
	if (Head->next == NULL)
	{
		Head->next=New;
		return true;
	}
  	while(Phead->next)
 	{
		Phead=Phead->next;
		if(Phead->data==dest && Phead->next!=NULL)
		{
             break;
		}

	}
	New->next=Phead->next;
	Phead->next->prev=New;
	New->prev=Phead;
	Phead->next=New;
	return true;
}

双向链表头部删除

/*******************************************************************
*
*	函数名称:	 DoubleLList_HeadDel
*	函数功能:   删除双向链表头部结点
* 	函数参数:
*  				@a :DoubleLList_t *Head  头结点 
*  			
*   返回结果:   
* 	注意事项:   None
* 	函数作者:  m17872844806@163.com
*	创建日期:   2024/04/25
*	修改历史:
*	函数版本:	V1.0
* *****************************************************************/
bool DoubleLList_HeadDel(DoubleLList_t *Head)
{
	DoubleLList_t *Temp = Head->next;
	if (Head->next == NULL)
	{
		printf("DoubleLList_t empty!\n");
		return false;
	}
  	Head->next=Head->next->next;
	Temp->next->prev=NULL;
	Temp->next=NULL;
	free(Temp);
	return true;
}

双向链表尾部删除

/*******************************************************************
*
*	函数名称:	 DoubleLList_TailDel
*	函数功能:   删除双向链表尾部结点
* 	函数参数:
*  				@a :DoubleLList_t *Head  头结点 
*  			
*   返回结果:   
* 	注意事项:   None
* 	函数作者:  m17872844806@163.com
*	创建日期:   2024/04/25
*	修改历史:
*	函数版本:	V1.0
* *****************************************************************/
bool DoubleLList_TailDel(DoubleLList_t *Head)
{
	DoubleLList_t *Phead = Head;
	if (Head->next == NULL)
	{
		printf("DoubleLList_t empty!\n");
		return false;
	}
  while(Phead->next)
  {
	Phead=Phead->next;

  }
  Phead->prev->next=NULL;
  Phead->prev=NULL;
  free(Phead);
	return true;
}

双向链表指定部位删除

/*******************************************************************
*
*	函数名称:	 DoubleLList_DestDel
*	函数功能:   删除双向链表指定部位结点
* 	函数参数:
*  				@a :DoubleLList_t *Head  头结点 
*  				@b :DataType_t dest 目标结点的数据域
*   返回结果:   
* 	注意事项:   None
* 	函数作者:  m17872844806@163.com
*	创建日期:   2024/04/25
*	修改历史:
*	函数版本:	V1.0
* *****************************************************************/
bool DoubleLList_DestDel(DoubleLList_t *Head,DataType_t dest)
{
	DoubleLList_t *Phead = Head;
	if (Head->next == NULL)
	{
		printf("DoubleLList_t empty!\n");
		return false;
	}
  while(Phead->next)
  {
	Phead=Phead->next;
	if(Phead->data==dest && Phead->next!=NULL)
	{
		break;
	}
	
  }
  Phead->prev->next=Phead->next;
  Phead->next->prev=Phead->prev;
  Phead->next=NULL;
  Phead->prev=NULL;
	return true;
}

完整代码

/*******************************************************************
*
*	file name:	DoubleLinke.c
*	author	 :  m17872844806@163.com
*	date	 :  2024/04/25
*	function :  双向链表的插入,删除
* 	note	 :  None
*
*	CopyRight (c)  2023-2024   m17872844806@163.com  All Right Reseverd 
*
* *****************************************************************/
#include<stdio.h>
#include <stdlib.h>
#include <stdbool.h>

//指的是双向链表中的结点有效数据类型,用户可以根据需要进行修改
typedef int  DataType_t;

//构造双向链表的结点,链表中所有结点的数据类型应该是相同的
typedef struct DoubleLinkedList
{
	DataType_t  		     data; //结点的数据域
	struct DoubleLinkedList	*prev; //直接前驱的指针域
	struct DoubleLinkedList	*next; //直接后继的指针域

}DoubleLList_t;


//创建一个空双向链表,空链表应该有一个头结点,对链表进行初始化
DoubleLList_t * DoubleLList_Create(void)
{
	//1.创建一个头结点并对头结点申请内存
	DoubleLList_t *Head = (DoubleLList_t *)calloc(1,sizeof(DoubleLList_t));
	if (NULL == Head)
	{
		perror("Calloc memory for Head is Failed");
		exit(-1);
	}

	//2.对头结点进行初始化,头结点是不存储数据域,指针域指向NULL
	Head->prev = NULL;
	Head->next = NULL;

	//3.把头结点的地址返回即可
	return Head;
}

//创建新的结点,并对新结点进行初始化(数据域 + 指针域)


DoubleLList_t * DoubleLList_NewNode(DataType_t data)
{
	//1.创建一个新结点并对新结点申请内存
	DoubleLList_t *New = (DoubleLList_t *)calloc(1,sizeof(DoubleLList_t));
	if (NULL == New)
	{
		perror("Calloc memory for NewNode is Failed");
		return NULL;
	}

	//2.对新结点的数据域和指针域(2个)进行初始化
	New->data = data;
	New->prev = NULL;
	New->next = NULL;

	return New;
}

/*******************************************************************
*
*	函数名称:	DoubleLList_HeadInsert
*	函数功能:   在链表头部插入新的结点
* 	函数参数:
*  				@a :DoubleLList_t *Head  头结点 
*  				@b :DataType_t data 新结点的数据域
*   返回结果:   
* 	注意事项:   None
* 	函数作者:  m17872844806@163.com
*	创建日期:   2024/04/25
*	修改历史:
*	函数版本:	V1.0
* *****************************************************************/
bool DoubleLList_HeadInsert(DoubleLList_t *Head,DataType_t data)
{
	DoubleLList_t *New = DoubleLList_NewNode(data);
	DoubleLList_t *Phead = Head;

	if (Head->next == NULL)
	{
		Head->next=New;
		return true;
	}
  	while(Phead->next)
 	{
		Phead=Phead->next;

	}
	New->next=Head->next;
	Head->next->prev=New;
	Head->next=New;
	return true;
}

/*******************************************************************
*
*	函数名称:	 DoubleLList_TailInsert
*	函数功能:   在链表尾部插入新的结点
* 	函数参数:
*  				@a :DoubleLList_t *Head  头结点 
*  				@b :DataType_t data 新结点的数据域
*   返回结果:   
* 	注意事项:   None
* 	函数作者:  m17872844806@163.com
*	创建日期:   2024/04/22
*	修改历史:
*	函数版本:	V1.0
* *****************************************************************/
bool DoubleLList_TailInsert(DoubleLList_t *Head,DataType_t data)
{
	DoubleLList_t *New = DoubleLList_NewNode(data);
	DoubleLList_t *Phead = Head;

	if (Head->next == NULL)
	{
		Head->next=New;
		return true;
	}
  	while(Phead->next)
 	{
		Phead=Phead->next;

	}
	Phead->next=New;
	New->prev=Phead;
	return true;
}



/*******************************************************************
*
*	函数名称:	 DoubleLList_DestInsert
*	函数功能:   在链表指定部位后面插入新的结点
* 	函数参数:
*  				@a :DoubleLList_t *Head  头结点 
*  				@b :DataType_t data 新结点的数据域
*   返回结果:   
* 	注意事项:   None
* 	函数作者:  m17872844806@163.com
*	创建日期:   2024/04/22
*	修改历史:
*	函数版本:	V1.0
* *****************************************************************/
bool DoubleLList_DestInsert(DoubleLList_t *Head,DataType_t dest,DataType_t data)
{
	DoubleLList_t *New = DoubleLList_NewNode(data);
	DoubleLList_t *Phead = Head;
	if (Head->next == NULL)
	{
		Head->next=New;
		return true;
	}
  	while(Phead->next)
 	{
		Phead=Phead->next;
		if(Phead->data==dest && Phead->next!=NULL)
		{
             break;
		}

	}
	New->next=Phead->next;
	Phead->next->prev=New;
	New->prev=Phead;
	Phead->next=New;
	return true;
}

/*******************************************************************
*
*	函数名称:	 DoubleLList_HeadDel
*	函数功能:   删除双向链表头部结点
* 	函数参数:
*  				@a :DoubleLList_t *Head  头结点 
*  			
*   返回结果:   
* 	注意事项:   None
* 	函数作者:  m17872844806@163.com
*	创建日期:   2024/04/25
*	修改历史:
*	函数版本:	V1.0
* *****************************************************************/
bool DoubleLList_HeadDel(DoubleLList_t *Head)
{
	DoubleLList_t *Temp = Head->next;
	if (Head->next == NULL)
	{
		printf("DoubleLList_t empty!\n");
		return false;
	}
  	Head->next=Head->next->next;
	Temp->next->prev=NULL;
	Temp->next=NULL;
	free(Temp);
	return true;
}

/*******************************************************************
*
*	函数名称:	 DoubleLList_TailDel
*	函数功能:   删除双向链表尾部结点
* 	函数参数:
*  				@a :DoubleLList_t *Head  头结点 
*  			
*   返回结果:   
* 	注意事项:   None
* 	函数作者:  m17872844806@163.com
*	创建日期:   2024/04/25
*	修改历史:
*	函数版本:	V1.0
* *****************************************************************/
bool DoubleLList_TailDel(DoubleLList_t *Head)
{
	DoubleLList_t *Phead = Head;
	if (Head->next == NULL)
	{
		printf("DoubleLList_t empty!\n");
		return false;
	}
  while(Phead->next)
  {
	Phead=Phead->next;

  }
  Phead->prev->next=NULL;
  Phead->prev=NULL;
  free(Phead);
	return true;
}



/*******************************************************************
*
*	函数名称:	 DoubleLList_DestDel
*	函数功能:   删除双向链表指定部位结点
* 	函数参数:
*  				@a :DoubleLList_t *Head  头结点 
*  				@b :DataType_t dest 目标结点的数据域
*   返回结果:   
* 	注意事项:   None
* 	函数作者:  m17872844806@163.com
*	创建日期:   2024/04/25
*	修改历史:
*	函数版本:	V1.0
* *****************************************************************/
bool DoubleLList_DestDel(DoubleLList_t *Head,DataType_t dest)
{
	DoubleLList_t *Phead = Head;
	if (Head->next == NULL)
	{
		printf("DoubleLList_t empty!\n");
		return false;
	}
  while(Phead->next)
  {
	Phead=Phead->next;
	if(Phead->data==dest && Phead->next!=NULL)
	{
		break;
	}
	
  }
  Phead->prev->next=Phead->next;
  Phead->next->prev=Phead->prev;
  Phead->next=NULL;
  Phead->prev=NULL;
	return true;
}


//遍历链表
bool DoubleLList_Print(DoubleLList_t *Head)
{
	//对单向循环链表的头结点的地址进行备份
	DoubleLList_t *Phead = Head;
	
	//判断当前链表是否为空,为空则直接退出
	if (Head->next == NULL)
	{
		printf("current linkeflist is empty!\n");
		return false;
	}

	//从首结点开始遍历
	while(Phead->next)
	{
		//把头结点的直接后继作为新的头结点
		Phead = Phead->next;

		//输出头结点的直接后继的数据域
		printf("data = %d\n",Phead->data);

	}

	return true;
}

int main(int argc, char const *argv[])
{
	   DoubleLList_t *phe=DoubleLList_Create();
	   DoubleLList_HeadInsert(phe,20);
	   DoubleLList_HeadInsert(phe,10);
	   DoubleLList_TailInsert(phe,40);
	   DoubleLList_TailInsert(phe,50);
	   DoubleLList_DestInsert(phe,20,30);
	   DoubleLList_HeadDel(phe);
	   DoubleLList_TailDel(phe);
	   DoubleLList_DestDel(phe,30);
	   DoubleLList_Print(phe);


	return 0;
}

该代码成功运行后,可以在终端肯定data的值为20,40
image

如果代码双向链表的代码有什么问题,请将问题发至网易邮箱 m17872844806@163.com,作者将及时改正,欢迎各位老爷提出意见。

麻烦三连加关注!!!!

比心!

posted @   琨为玉也  阅读(636)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 终于写完轮子一部分:tcp代理 了,记录一下
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
点击右上角即可分享
微信分享提示