双向链表和双向循环链表的(创建、插入、删除、遍历)

V1.0 2024年4月24日 发布于博客园


目录

双向链表和双向循环链表的(创建、插入、删除、遍历)

设计双向链表的接口

/********************************************************************************************************
*
*
* 设计双向链表的接口
*
* 
*
* Copyright (c)  2023-2024   17666589210@136.com   All right Reserved
* ******************************************************************************************************/
//指的是双向链表中的结点有效数据类型,用户可以根据需要进行修改
typedef int  DataType_t;

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

}DoubleLList_t;

创建一个空的双向链表,空链表应该有一个头结点,对链表进行初始化

/*
  * @name  : DoubleLList_Create
  * @brief : 创建一个空的双向链表,空链表应该有一个头结点,对链表进行初始化
  * @param : None
  * @retval: DoubleLList_t * (结构体类型的地址)
  * @date  : 2024/04/24
  * @note  : 无
*/
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;
}

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

/*
  * @name  : DoubleLList_NewNode
  * @brief : 创建新的结点,并对新结点进行初始化(数据域 + 指针域)
  * @param : DataType_t data(初始化赋值)
  * @retval: DoubleLList_t * (结构体类型的地址)
  * @date  : 2024/04/24
  * @note  : 无
*/
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;
}

创建一个新的结点进行头部插入

/*
  * @name  : DoubleLList_HeadInsert
  * @brief : 将创建一个新的结点进行头部插入
  * @param : DoubleLList_t *Head(头结点的地址),DataType_t data(初始化赋值)
  * @retval: bool (判断插入是否成功)
  * @date  : 2024/04/23
  * @note  : 无
*/
//头插
bool DoubleLList_HeadInsert(DoubleLList_t* Head, DataType_t data)
{
	//1.创建新的结点,并对新结点进行初始化
	DoubleLList_t* New = DoubleLList_NewNode(data);
	if (NULL == New)
	{
		printf("can not insert new node\n");
		return false;
	}

	//2.判断链表是否为空,如果为空,则直接插入即可
	if (NULL == Head->next)
	{
		Head->next = New;
		return true;
	}

	//3.如果链表为非空,则把新结点插入到链表的头部
	New->next = Head->next;
	Head->next->prev = New;
	Head->next = New;
	return true;
}

创建一个新的结点进行尾部插入

/*
  * @name  : DoubleLList_TailInsert
  * @brief : 将创建一个新的结点进行尾部插入
  * @param : DoubleLList_t *Head(头结点的地址),DataType_t data(初始化赋值)
  * @retval: bool (判断插入是否成功)
  * @date  : 2024/04/24
  * @note  : 无
*/
//尾插
bool DoubleLList_TailInsert(DoubleLList_t* Head, DataType_t data)
{
	//1.创建新的结点,并对新结点进行初始化
	DoubleLList_t* New = DoubleLList_NewNode(data);
	if (NULL == New)
	{
		printf("can not insert new node\n");
		return false;
	}

	//2.判断链表是否为空,如果为空,则直接插入即可
	if (NULL == Head->next)
	{
		Head->next = New; //让头结点的next指向新结点
		return true;
	}

	//3.如果链表为非空,则把新结点插入到链表的尾部

	while (Phead->next)//遍历找到尾结点
	{
		Phead = Phead->next;
	}
	Phead->next = New; //尾结点的next指针指向新结点地址
	New->prev = Phead //新结点的prev指针指向原本的尾结点地址
	return true;
}

创建一个新的结点进行任意位置插入

/*
  * @name  : DoubleLList_DestInsert
  * @brief : 将创建一个新的结点进行任意位置插入
  * @param : DoubleLList_t *Head(头结点的地址),DataType_t destval(插入的位置数据),DataType_t data(初始化赋值)
  * @retval: bool (判断插入是否成功)
  * @date  : 2024/04/24
  * @note  : 无
*/
//指定位置插入
bool DoubleLList_DestInsert(DoubleLList_t* Head, DataType_t destval, DataType_t data)
{
	//对链表的头文件的地址进行备份
	DoubleLList_t* Phead = Head;

	//1.创建新的结点,并对新结点进行初始化
	DoubleLList_t* New = DoubleLList_NewNode(data);
	if (NULL == New)
	{
		printf("can not insert new node\n");
		return false;
	}

	//2.判断链表是否为空,如果为空,则直接插入即可
	if (NULL == Head->next)
	{
		Head->next = New;
		return true;
	}

	//3.如果链表为非空,则把新结点插入到链表的头部
	while (Phead->next)//遍历找到目标结点进行后插
	{
		Phead = Phead->next;
		if (Phead->data == destval)
		{
			break;
		}
	}

	//如果遍历链表找不到目标结点,则退出即可
	if (Phead->next == NULL && Phead->data != destval)
	{
		printf("dest node is not found\n");
		return false;
	}

	//如果遍历链表找到目标结点,则有三种情况(头部插入 尾部插入 中间插入)
	if (Phead->next == NULL) //进行尾插
	{
		New->prev = Phead;
		Phead->next = New;
	}
	else
	{
		New->next = Phead->next;   //新结点的next指向目标结点的直接后继结点的地址
		New->prev = Phead;	   	   //新结点的prev指向目标结点的地址
		Phead->next->prev = New;   //目标结点的直接后继结点的prev指针指向新结点
		Phead->next = New;         //目标结点的next指针指向新结点
	}

	return true;
}

对双向链表删除首结点

/*
  * @name  : DoubleLList_HeadDel
  * @brief : 对双向链表删除首结点
  * @param : DoubleLList_t *Head(头结点的地址)
  * @retval: bool (判断插入是否成功)
  * @date  : 2024/04/24
  * @note  : 无
*/
//头删
bool DoubleLList_HeadDel(DoubleLList_t* Head)
{
	//1.判断单向循环链表是否为空,如果为空,无法删除
	if (NULL == Head->next)
	{
		printf("DoubleLList is empty , can not dele");
		return false;
	}

	//对双向链表的头结点的地址进行备份
	DoubleLList_t* Phead1 = Head;
	DoubleLList_t* Phead2 = Head->next;

	//2.如果链表为非空,则进行首结点删除
	Phead1->next = Head->next->next;
	Phead2->next->prev = NULL;
	Head->next->prev = NULL;
	free(Phead2);

	return true;
}

对双向链表删除尾结点

/*
  * @name  : DoubleLList_TailDele
  * @brief : 对双向链表删除尾结点
  * @param : DoubleLList_t *Head(头结点的地址)
  * @retval: bool (判断插入是否成功)
  * @date  : 2024/04/23
  * @note  : 无
*/
//尾删
bool DoubleLList_TailDele(DoubleLList* Head)
{
	//1.判断链表是否为空,如果为空,无法删除
	if (NULL == Head->next)
	{
		printf("DoubleLList is empty , can not dele");
		return false;
	}
	//对双向链表的头结点的地址进行备份
	DoubleLList_t* Phead = Head;
	//2.如果链表为非空,则进行首结点删除
	while (Phead->next)//遍历找到尾结点
	{
		Phead = Phead->next;
	}
	Phead->prev->next = NULL;
	Phead->prev = NULL;
	Phead->next = NULL; 
	free(Phead);

	return true;
}

对双向链表任意位置删除结点

/*
  * @name  : DoubleLList_DestDele
  * @brief : 对双向链表任意位置删除结点
  * @param : DoubleLList_t *Head(头结点的地址),DataType_t destval(指定删除位置的数据)
  * @retval: bool (判断插入是否成功)
  * @date  : 2024/04/23
  * @note  : 无
*/
//任意删
bool DoubleLList_t_DestDele(DoubleLList_t* Head, DataType_t destval)
{	
	//对双向链表的头结点的地址进行备份
	DoubleLList_t * Phead = Head;

	//1.判断链表是否为空,如果为空,无法删除
	if (NULL == Head->next)
	{
		printf("DoubleLList is empty , can not dele");
		return false;
	}

	//2.如果双向链表为非空,则进行遍历查找是否有目标结点
	while (Phead1->next)//遍历找到目标结点
	{
		Phead1 = Phead1->next;	

		if (destval == Phead->data)
		{
			break;
		}	
	}
	//如果遍历链表找不到目标结点,则退出即可
	if (Phead->next == NULL && Phead->data != destval)
	{
		printf("dest node is not found\n");
		return false;
	}

	//3.如果找到了目标结点,则进行指定结点删除,共有三种情况(头部删除 尾部删除 中间删除)		
	if (Phead == Head->next)         //头删
	{
		Head->next = Phead->next;    //更新头结点,让头结点的next指针指向首结点的直接后继
		if (Phead->next != NULL)     //当只有一个首结点的时候
		{
			Phead->next->prev = NULL;//将首结点的直接后继结点的prev指向NULL
			Phead->next = NULL;      //将首结点的next指向NULL
		}
		free(Phead);
	}
	else if (Phead->next == NULL)    //尾删
	{
		Phead->prev->next = NULL;	 //尾结点的直接前驱结点的next指向NULL
		Phead->prev = NULL;          //尾结点的prev指针指向NULL
		free(Phead);				 /释放待删除点的内存
	}
	else
	{	
		Phead->prev->next = Phead->next;     //让待删除结点的直接前驱结点的next指针指向待删除结点的直接后继地址
		Phead->next->prev = Phead->prev;     //让待删除结点的直接后继结点的prev指针指向待删除结点的直接前驱地址
		Phead->prev = NULL;		     		 //让待删除结点的prev指针指向NULL
		Phead->next = NULL;                  //让待删除结点的next指针指向NULL
		free(Phead);                        //释放待删除点的内存
	}

	return true;
}
int main(int argc, char const *argv[])
{
	return 0;
}

设计双向循环链表的接口

/********************************************************************************************************
*
*
* 设计双向循环链表的接口
*
* 
*
* Copyright (c)  2023-2024   cececlmx@126.com   All right Reserved
* ******************************************************************************************************/

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

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

}DoubleCirLList_t;

创建一个空双向循环链表,空链表应该有一个头结点,对链表进行初始化

/*
  * @name  :DoubleCirLList_Create
  * @brief : 创建一个空的双向循环链表,空链表应该有一个头结点,对链表进行初始化
  * @param : None
  * @retval: DoubleCirLList_t * (结构体类型的地址)
  * @date  : 2024/04/24
  * @note  : 无
*/
DoubleCirLList_t * DoubleCirLList_Create(void)
{
	//1.创建一个头结点并对头结点申请内存
	DoubleCirLList_t * Head = (DoubleCirLList_t*)calloc(1, sizeof(DoubleCirLList_t));
	if (NULL == Head)
	{
		perror("Calloc memory for Head is Failed");
		exit(-1);
	}

	//2.对头结点进行初始化,头结点是不存储数据域,指针域指向自身即可,体现“循环”
	Head->prev = Head;
	Head->next = Head;

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

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

/*
  * @name  : DoubleCirLList_NewNode
  * @brief : 创建新的结点,并对新结点进行初始化(数据域 + 指针域)
  * @param : DataType_t data(初始化赋值)
  * @retval: DoubleCirLList_t * (结构体类型的地址)
  * @date  : 2024/04/24
  * @note  : 无
*/
DoubleCirLList_t * DoubleCirLList_NewNode(DataType_t data)
{
	//1.创建一个新结点并对新结点申请内存
	DoubleCirLList_t * New = (DoubleCirLList_t*)calloc(1, sizeof(DoubleCirLList_t));
	if (NULL == New)
	{
		perror("Calloc memory for NewNode is Failed");
		return NULL;
	}

	//2.对新结点的数据域和指针域(2个)进行初始化,指针域指向结点自身,体现“循环”
	New->data = data;
	New->prev = New;
	New->next = New;

	return New;
}

将创建一个新的结点进行头部插入

/*
  * @name  : DoubleCirLList_HeadInsert
  * @brief : 将创建一个新的结点进行头部插入
  * @param : DoubleCirLList_t *Head(头结点的地址),DataType_t data(初始化赋值)
  * @retval: bool (判断插入是否成功)
  * @date  : 2024/04/24
  * @note  : 无
*/
//头插
bool DoubleCirLList_HeadInsert(DoubleCirLList_t * Head, DataType_t data)
{
	//对链表的头文件的地址进行备份
	DoubleCirLList_t * Phead = Head->next;

	//1.创建新的结点,并对新结点进行初始化
	DoubleCirLList_t * New = DoubleCirLList_NewNode(data);
	if (NULL == New)
	{
		printf("can not insert new node\n");
		return false;
	}

	//2.判断链表是否为空,如果为空,则直接插入即可
	if (Head == Head->next)
	{
		Head->next = New;
		New->next = New;

		return true;
	}

	//3.如果链表为非空,则把新结点插入到链表的头部
	New->prev = Phead->prev;		 //新结点的prev指针指向尾结点的地址
	Phead->prev->next = New;         //尾结点的next指针指向新结点的地址
	New->next = Head->next;          //新结点的next指针指向原首结点的地址
	Head->next->prev->next = New;    //原首结点的prev指针指向新结点的地址
	Head->next = New;		         //头结点的next指向新结点的地址

	return true;
}

将创建一个新的结点进行尾部插入

/*
  * @name  : DoubleCirLList_TailInsert
  * @brief : 将创建一个新的结点进行尾部插入
  * @param : DoubleCirLList_t *Head(头结点的地址),DataType_t data(初始化赋值)
  * @retval: bool (判断插入是否成功)
  * @date  : 2024/04/24
  * @note  : 无
*/
//尾插
bool DoubleCirLList_TailInsert(DoubleCirLList_t * Head, DataType_t data)
{
	//对链表的头文件的地址进行备份
	DoubleCirLList_t * Phead = Head->next;

	//1.创建新的结点,并对新结点进行初始化
	DoubleCirLList_t * New = DoubleCirLList_NewNode(data);
	if (NULL == New)
	{
		printf("can not insert new node\n");
		return false;
	}

	//2.判断链表是否为空,如果为空,则直接插入即可
	if (Head == Head->next)
	{
		Head->next = New;
		New->next = New;

		return true;
	}

	//3.如果链表为非空,则把新结点插入到链表的尾部
	New->next = Phead;		 //新结点的next指针指向首结点地址
	Phead->prev->next = New; //原尾结点的next指针指向New
	New->prev = Phead->prev; //新结点的prev指针指向原尾结点的地址
	Phead->prev = New;		 //首结点的prev指针指向新结点地址

	return true;
}

将创建一个新的结点进行尾部插入

/*
  * @name  : DoubleCirLList_DestInsert
  * @brief : 将创建一个新的结点进行尾部插入
  * @param : DoubleCirLList_t *Head(头结点的地址),DataType_t destval(插入的位置数据),DataType_t data(初始化赋值)
  * @retval: bool (判断插入是否成功)
  * @date  : 2024/04/24
  * @note  : 无
*/
//指定位置插入
bool DoubleCirLList_DestInsert(DoubleCirLList_t* Head, DataType_t destval, DataType_t data)
{
	//对链表的头文件的地址进行备份
	DoubleCirLList_t* Phead = Head;

	//1.创建新的结点,并对新结点进行初始化
	DoubleCirLList_t* New = DoubleCirLList_NewNode(data);
	if (NULL == New)
	{
		printf("can not insert new node\n");
		return false;
	}

	//2.判断链表是否为空,如果为空,则直接插入即可
	if (NULL == Head->next)
	{
		Head->next = New;
		return true;
	}

	//3.如果链表为非空,则把新结点插入到双向链表的指定位置
	while (Phead->next)//遍历找到目标结点进行后插
	{
		Phead = Phead->next;

		if (Head->next == Phead->next || Phead->data == destval)
		{
			break;
		}
	}

	//如果遍历链表找不到目标结点,则退出即可
	if (Phead->next == Head->next && Phead->data != destval)
	{
		printf("dest node is not found\n");
		return false;
	}

	//如果遍历链表找到目标结点,则有三种情况(头部插入 尾部插入 中间插入)
	if (Phead->next == Head->next) //进行尾插
	{
		New->prev = Phead;		//新结点的prev指针指向原尾结点地址
		Phead->next = New;		//尾结点的next指针指向新结点地址
		New->next = Head->next; //新结点的next指针指向首结点的地址
		Head->next->prev = New;	//首结点的prev指针指向新结点的地址
	}
	else
	{
		New->next = Phead->next;   //新结点的next指向目标结点的直接后继结点的地址
		Phead->next->prev = New;   //目标结点的直接后继结点的prev指针指向新结点
		New->prev = Phead;		   //新结点的prev指向目标结点的地址
		Phead->next = New;         //目标结点的next指针指向新结点
	}

	return true;
}

对双向链表删除首结点

/*
  * @name  : DoubleCirLList_HeadDel
  * @brief : 对双向链表删除首结点
  * @param : DoubleCirLList_t * Head(头结点的地址)
  * @retval: bool (判断插入是否成功)
  * @date  : 2024/04/24
  * @note  : 无
*/
//头删
bool DoubleCirLList_HeadDel(DoubleCirLList_t * Head)
{
	//对双向链表的首结点的地址进行备份
	DoubleCirLList_t * Phead = Head->next;

	//1.判断单向循环链表是否为空,如果为空,无法删除
	if (NULL == Head->next)
	{
		printf("DoubleCirLList is empty , can not dele");
		return false;
	}

	//2.如果链表为非空,则进行首结点删除
	Phead->next->prev = Phead->prev;   //首结点的直接后继的prev指针指向尾结点的地址
	Phead->prev->next = Phead->next;   //尾结点的next指针指向首结点直接后继的地址
	Head->next = Phead->next;		   //头结点的next指针指向首结点直接后继的地址
	Phead->next = NULL;				   //首结点的next指针指向NULL
	Phead->prev = NULL;				   //首结点的prev指针指向NULL
	free(Phead);                       //释放首结点的内存

	return true;
}

对双向链表删除尾结点

/*
  * @name  : DoubleLList_TailDele
  * @brief : 对双向链表删除尾结点
  * @param : DoubleLList_t *Head(头结点的地址)
  * @retval: bool (判断插入是否成功)
  * @date  : 2024/04/24
  * @note  : 无
*/
//尾删
bool DoubleCirLList_TailDele(DoubleCirLList_t * Head)
{
	//对双向链表的尾结点的地址进行备份
	DoubleCirLList_t * Phead = Head->next->prev;
	DoubleCirLList_t * Temp = Head->next;
	//1.判断单向循环链表是否为空,如果为空,无法删除
	if (Head->next == Head)
	{
		printf("DoubleCirLList is empty ,can not dele");
		return false;
	}

	//2.如果链表为非空,则进行尾结点删除
	Phead->prev->next = Head->next;	//尾结点的直接前驱的next指针指向首结点的地址
	Temp->prev = Phead->prev;	//首结点的prev指针指向尾结点直接前驱的地址
	Phead->next = NULL;				//尾结点的next指针指向NULL
	Phead->prev = NULL;				//尾结点的prev指针指向NULL
	free(Phead);					//释放尾结点的内存

	return true;
}

对双向链表任意位置删除结点

/*
  * @name  : DoubleCirLList_DestDele
  * @brief : 对双向链表任意位置删除结点
  * @param : DoubleLList_t *Head(头结点的地址),DataType_t destval(指定删除位置的数据)
  * @retval: bool (判断插入是否成功)
  * @date  : 2024/04/23
  * @note  : 无
*/
//任意删
//任意删
bool DoubleCirLList_t_DestDele(DoubleCirLList_t* Head, DataType_t destval)
{
	//对双向链表的头结点的地址进行备份
	DoubleCirLList_t * Phead = Head;

	//1.判断链表是否为空,如果为空,无法删除
	if (Phead == Head->next)
	{
		printf("DoubleLList is empty , can not dele");
		return false;
	}

	//2.如果双向链表为非空,则进行遍历查找是否有目标结点
	while (Phead->next)//遍历找到目标结点
	{
		Phead = Phead->next;

		if (destval == Phead->data)
		{
			break;
		}
		if(Phead->next == Head->next)
		{
			break; 
		}
}
	//如果遍历链表找不到目标结点,则退出即可
	if (Phead->data != destval)
	{
		printf("dest node is not found\n");
		return false;
	}

	//3.如果找到了目标结点,则进行指定结点删除,共有三种情况(头部删除 尾部删除 中间删除)
	if (Phead == Head->next)	//头删
	{
		if (Phead->next != NULL)//当链表不止一个结点时
		{
			Phead->next->prev = Phead->prev;   //首结点的直接后继的prev指针指向尾结点的地址
			Phead->prev->next = Phead->next;   //尾结点的next指针指向首结点直接后继的地址
			Head->next = Phead->next;		   //头结点的next指针指向首结点的直接后继
		}
		else								   //只有链表仅有首结点时
		{
			Head->next = NULL;
		}
		Phead->next = NULL;				       //首结点的next指针指向NULL
		Phead->prev = NULL;				       //首结点的prev指针指向NULL
		free(Phead);						   //释放首结点的内存
	}
	else if (Phead->next == Head->next) //尾删
	{
		Phead->prev->next = Head->next;	//尾结点的直接前驱的next指针指向首结点的地址
		Head->next->prev = Phead->prev;	//首结点的prev指针指向尾结点直接前驱的地址
		Phead->next = NULL;				//尾结点的next指针指向NULL
		Phead->prev = NULL;				//尾结点的prev指针指向NULL
		free(Phead);					//释放尾结点的内存
	}
	else
	{
		Phead->prev->next = Phead->next;     //让待删除结点的直接前驱结点的next指针指向待删除结点的直接后继地址
		Phead->next->prev = Phead->prev;     //让待删除结点的直接后继结点的prev指针指向待删除结点的直接前驱地址
		Phead->prev = NULL;					 //让待删除结点的prev指针指向NULL
		Phead->next = NULL;                  //让待删除结点的next指针指向NULL
		free(Phead);                         //释放待删除点的内存
	}
	return true;
}

遍历链表

/*
  * @name  : DoubleCirLList_Print
  * @brief : 对双向链表任意位置删除结点
  * @param : DoubleLList_t * Head(头结点的地址),DataType_t destval(指定删除位置的数据)
  * @retval: bool (判断遍历是否成功)
  * @date  : 2024/04/23
  * @note  : 无
*/
bool DoubleCirLList_Print(DoubleCirLList_t * Head)
{
	//对单向循环链表的头结点的地址进行备份
	DoubleCirLList_t * Temp = Head;

	//判断当前链表是否为空,为空则直接退出
	if (Head->next == Head)
	{
		printf("current DoubleCirLList is empty!\n");
		return false;
	}

	//从首结点开始遍历
	while (1)
	{
		//把头结点的直接后继作为新的头结点
		Temp = Temp->next;
		//输出头结点的直接后继的数据域
		printf("data = %d\n", Temp->data);
		//判断是否到达尾结点,尾结点的next指针是指向首结点的地址
		if (Temp->next == Head->next)
		{
			break;
		}
	}
	printf("\n");
	return true;
}

主函数验证

	int main(int argc, char const* argv[])
	{
		DoubleCirLList_t* manager = DoubleCirLList_Create();
		DoubleCirLList_HeadInsert(manager, 4); //验证头插
		DoubleCirLList_HeadInsert(manager, 5);
		DoubleCirLList_HeadInsert(manager, 6);
		DoubleCirLList_Print(manager);

		DoubleCirLList_TailInsert(manager, 9);//验证尾插
		DoubleCirLList_TailInsert(manager, 2);
		DoubleCirLList_Print(manager);

		DoubleCirLList_DestInsert(manager, 4, 8);//验证任意插
		DoubleCirLList_Print(manager);

		DoubleCirLList_HeadDel(manager);//验证头删
		DoubleCirLList_Print(manager);

		DoubleCirLList_TailDele(manager);//验证尾删
		DoubleCirLList_Print(manager);

		DoubleCirLList_t_DestDele(manager, 8); //任意删中的头删
		DoubleCirLList_Print(manager);

		DoubleCirLList_t_DestDele(manager, 2); //删除没有的验证判断是否有错
		DoubleCirLList_Print(manager);

		DoubleCirLList_t_DestDele(manager,9); //任意删中的尾删
		DoubleCirLList_Print(manager);
		return 0;
	}
posted @   52017  阅读(32)  评论(2编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
点击右上角即可分享
微信分享提示