html

数据结构:双向循环链表的创建·插入·删除

数据结构:双向循环链表的创建·插入·删除

/**
  * @file name : 数据结构:双向循环链表的创建·插入·删除
  * @brief     : 实现双向循环链表的创建·插入·删除
  * @author	   : liuliu@163.com
  * @date 	   :2024/04/24
  * @version   :2.0
  * @note      :none
  * CopyRight(c):  2023-2024   liuliu@163.com   All Right Reseverd
  */
  #include <stdio.h>
  #include <stdlib.h>
  #include <string.h>
  #include <stdbool.h>
  //定义节点中的数据域类型
  typedef int Data_t;
  //定义一个节点类型
  typedef struct CircularDoul_LList{
  	Data_t data;
  	struct CircularDoul_LList *next;
  	struct CircularDoul_LList *prev;
  }CirDou_LList_t;
  //创建一个空链表
/**
  * @function: CirDou_LList_Creat
  * @brief   : 创建一个空链表
  * @param   : 空
  * @retval  : @CirDou_LList_t,返回该链表的地址
  * @date    : 2024/04/24
  * @version : 1.0 
  * @note    : none
  * author   : liuliu@163.com
  */
  CirDou_LList_t *CirDou_LList_Creat()
  {
  	CirDou_LList_t *Head=(CirDou_LList_t *)calloc(1,sizeof(  CirDou_LList_t ));//申请一个内存
  	//判断内存是否申请成功
  	if(NULL==Head)
  	{
  		perror("calloc memory for Head is failed");
  		return NULL;
  	}
  	//初始化成员变量
  	Head->next=Head;//连着自身
	Head->prev=NULL;
  	return Head;
  }
 //创建一个新节点
  /**
  * @function: CirDou_LListNode_Creat
  * @brief   : 创建一个新节点
  * @param   : @Data_t data:接收数据域的值
  * @retval  : @CirDou_LList_t:返回该节点的地址
  * @date    : 2024/04/24
  * @version : 1.0 
  * @note    : none
  * author   : liuliu@163.com
  */
 CirDou_LList_t* CirDou_LListNode_Creat(Data_t data)
  {
  	CirDou_LList_t *New=(CirDou_LList_t *)calloc(1,sizeof( CirDou_LList_t ));//定义节点并申请内存
  	//判断内存是否申请成功
  	if(NULL==New)
  	{
  		perror("calloc memory for New is failed");
  		return NULL;
  	}
  	//初始化成员变量
  	New->next=NULL;
	New->prev=NULL;
  	New->data=data;
  	return New;
  }
  //判断链表是否为空
  /**
  * @function: CirDou_LList_IsEmpoty
  * @brief   : 判断链表是否为空
  * @param   : @CirDou_LList_t *Head:需要判断的链表
  * @retval  : @bool:已满返回ture,未满返回false
  * @date    : 2024/04/24
  * @version : 1.0 
  * @note    : none
  * author   : liuliu@163.com
  */
  bool CirDou_LList_IsEmpoty(CirDou_LList_t *Head)
  {
  	if(Head->next==Head)
  	{
  		return true;
  	}
  	return false;
  }
  //1.尾部插入节点
  /**
  * @function: CirDou_LList_TailInsert
  * @brief   : 尾部插入节点
  * @param   : @ CirDou_LList_t *Head:需要被插入的链表
  			 : @ Data_t data:要插入节点的数据域
  * @retval  : @bool:插入返回ture,未插入返回false
  * @date    : 2024/04/24
  * @version : 1.0 
  * @note    : none
  * author   : liuliu@163.com
  */
 bool  CirDou_LList_TailInsert(CirDou_LList_t *Head,Data_t data)
 {
 	CirDou_LList_t* New=CirDou_LListNode_Creat( data);//得到要插入的节点
 	if(NULL==New)
 	{
 		return false;
 	}
 	//链表为空的情况
 	if(CirDou_LList_IsEmpoty(Head))
 	{
 		New->prev=New;//前驱和后继都连本身
 		Head->next=New;
 		New->next=New;
 		return true;
 	}
 	//若不为空时
 	New->prev=Head->next->prev;
 	New->next=Head->next;
 	Head->next->prev->next=New;
 	Head->next->prev=New;
 	return true;
 }
 //2.头部插入节点
  /**
  * @function: CirDou_LList_HeadInsert
  * @brief   : 尾部插入节点
  * @param   : @ CirDou_LList_t *Head:需要被插入的链表
             : @ Data_t data:要插入节点的数据域
  * @retval  : @bool:插入返回ture,未插入返回false
  * @date    : 2024/04/24
  * @version : 1.0 
  * @note    : none
  * author   : liuliu@163.com
  */
 bool  CirDou_LList_HeadInsert(CirDou_LList_t *Head,Data_t data)
 {
 	CirDou_LList_t* New=CirDou_LListNode_Creat( data);//得到要插入的节点
 	if(NULL==New)
 	{
 		return false;
 	}
 	//链表为空的情况
 	if(CirDou_LList_IsEmpoty(Head))
 	{
 		New->prev=New;//前驱和后继都连本身
 		Head->next=New;
 		New->next=New;
 		return true;
 	}
 	//若不为空时
 	New->next=Head->next;
 	New->prev=Head->next->prev;
 	Head->next->prev->next=New;
 	Head->next->prev=New;
 	Head->next=New;
 	return true;
 }
 //3.指定位置插入节点
  /**
  * @function: CirDou_LList_DestInsert
  * @brief   : 尾部插入节点
  * @param   : @ CirDou_LList_t *Head:需要被插入的链表
  			 : @Data_t data1:指定要插入位置的节点数据域
  			 : @ Data_t data:要插入节点的数据域
  * @retval  : @bool:插入返回ture,未插入返回false
  * @date    : 2024/04/24
  * @version : 1.0 
  * @note    : none
  * author   : liuliu@163.com
  */
 bool  CirDou_LList_DestInsert(CirDou_LList_t *Head,Data_t data1,Data_t data)
 {
 	CirDou_LList_t *Dest=CirDou_LListNode_Creat ( data1);//要被删除的节点
 	CirDou_LList_t * New=CirDou_LListNode_Creat( data);//得到要插入的节点
 	CirDou_LList_t* current=Head->next;//备份首节点的地址
 	if(NULL==New)
 	{
 		return false;
 	}
 	//链表为空的情况
 	if(CirDou_LList_IsEmpoty(Head))
 	{
 		New->prev=New;//前驱和后继都连本身
 		Head->next=New;
 		New->next=New;
 		return true;
 	}
 	//若不为空时
 	while(current)
 	{		
 	//当刚好插到尾部时
 		if(current->next==Head->next)
 		{
            if(current->data==Dest->data)
            {
 			    current->next=New;
 			    New->next=Head->next;
 			    Head->prev=New;
 			    return true;
            }
            break;
 		}
 	//插在中间
 		if(current->data==Dest->data)
 		{	New->next=current->next;
 			New->prev=current;
 			current->next->prev=New;
 			current->next=New;
            return true;
 		}
        //如果没有找到要插的位置
        else
        {
            printf("no find");
            return false;
        }
 		current=current->next;
 	}
    
 	
 }
 //从头部删除节点
/**
  * @function: CirDou_LList_HeadDel
  * @brief   : 从头部删除节点
  * @param   : @ CirDou_LList_t *Head:需要被删的链表
  * @retval  : @bool:删除返回ture,未删除返回false
  * @date    : 2024/04/24
  * @version : 1.0 
  * @note    : none
  * author   : liuliu@163.com
  */
 bool CirDou_LList_HeadDel(CirDou_LList_t *Head)
 {
 	CirDou_LList_t *current=Head->next;//备份首节点
  //如果链表为空
 	if(CirDou_LList_IsEmpoty(Head))
 	{
 		printf("link is empoty\n");
 		return false;
 	}
 	//如果链表不为空
 	current->prev->next=current->next;
 	current->next->prev=current->prev;
 	Head->next=current->next;
 	current->next=NULL;
 	current->prev=NULL;
 	free(current);
 	return true;
 }
  //从尾部删除节点
/**
  * @function: CirDou_LList_TailDel
  * @brief   : 从尾部删除节点
  * @param   : @ CirDou_LList_t *Head:需要被删的链表
  * @retval  : @bool:删除返回ture,未删除返回false
  * @date    : 2024/04/24
  * @version : 1.0 
  * @note    : none
  * author   : liuliu@163.com
  */
 bool CirDou_LList_TailDel(CirDou_LList_t *Head)
 {
 	CirDou_LList_t *Tail=Head->next->prev;//备份尾节点地址
  //如果链表为空
 	if(CirDou_LList_IsEmpoty(Head))
 	{
 		printf("link is empoty\n");
 		return false;
 	}
 //如果链表不为空
 	Tail->next=NULL;
 	Tail->prev->next=Head->next;
 	Head->next->prev=Tail->prev;
 	Tail->prev=	NULL;
 	free(Tail);
 	return true;
 }
 //删除指定节点
/**
  * @function: CirDou_LList_DestDel
  * @brief   : 删除指定节点
  * @param   : @ CirDou_LList_t *Head:需要被删的链表
  			 : @ Data_t data: 要被删除的节点数据域
  * @retval  : @bool:删除返回ture,未删除返回false
  * @date    : 2024/04/24
  * @version : 1.0 
  * @note    : none
  * author   : liuliu@163.com
  */
 bool CirDou_LList_DestDel(CirDou_LList_t *Head,Data_t data)
 {
 	CirDou_LList_t *Dest=CirDou_LListNode_Creat( data);//创建要删除的节点
 	CirDou_LList_t *current=Head->next;//记录当前节点
  //如果链表为空  
 	if(CirDou_LList_IsEmpoty(Head))
 	{
 		printf("link is empoty\n");
 		return false;
 	}
 //如果链表不为空
 	while(current)
 	{
 		//1.删除的恰好是首节点
 		if(Head->next==current&&current->data==Dest->data)
 		{
 		 	//链表有多个节点的情况
 			if(current->next!=current)
 			{
 				current->prev->next=current->next;
 				current->next->prev=current->prev;
 				Head->next=current->next;
 				current->next=NULL;
 				current->prev=NULL;
 				free(current);
 				return true;
 			}
 			//链表只有一个首节点的情况
 			current->next=NULL;
 			current->prev=NULL;
 			Head->next=Head;
 			free(current);
 			return true;		
 		}
 		//2.删除的恰好是尾节点
 		if(current->next==Head->next&&current->data==Dest->data)
 		{
 			current->next=NULL;
 			current->prev->next=Head->next;
 			Head->next->prev=current->prev;
 			current->prev=NULL;
 			free(current);
 			return true;
 		}
 		//3.删除中间的节点
 		else if(current->data==Dest->data&&current->data==Dest->data)
 		{
 			current->prev->next=current->next;
 			current->next->prev=current->prev;
 			current->prev=NULL;
 			current->next=NULL;
 			free(current);
 			return true;
 		}
        //都不满足
        if(current->next==Head->next)
        {
            printf("no find\n");
            break;
        }
 	  current=current->next; 	
   }
 }
 /**
  * @function: CirDou_LList_Print
  * @brief   : 打印链表
  * @param   : @ CirDou_LList_t *Head:需要被打印的链表
  			 
  * @retval  : 空
  * @date    : 2024/04/24
  * @version : 1.0 
  * @note    : none
  * author   : liuliu@163.com
  */
 void CirDou_LList_Print(CirDou_LList_t *Head)
 {
 	CirDou_LList_t *current=Head->next;//记录当前节点
    //链表为空的情况
 	if(CirDou_LList_IsEmpoty(Head))
 	{
 		printf("link is empoty\n");
 		return ;
 	}
 	while(current)
 	{
 		printf("%d",current->data);
        printf(" ");
        if(Head->next==current->next)
        {
            printf("\n");
            break;
        }
 		current=current->next;
 	}
 }
 //进行测试,验证代码是否正确
 int main()
 {
 //创建一个空链表
 	CirDou_LList_t *Head=CirDou_LList_Creat();
 //从尾部插入节点
 	CirDou_LList_TailInsert(Head,10);
 	CirDou_LList_TailInsert(Head,20);
 	CirDou_LList_TailInsert(Head,30);
 	CirDou_LList_TailInsert(Head,40);
 //遍历一遍并打印出来
 	CirDou_LList_Print(Head);
 //从头部插入节点
 	CirDou_LList_HeadInsert(Head,1);
 	CirDou_LList_HeadInsert(Head,2);
 	CirDou_LList_HeadInsert(Head,3);
 	CirDou_LList_HeadInsert(Head,4);
 //遍历一遍并打印出来
 	CirDou_LList_Print(Head);
 //从指定位置插入节点
 	CirDou_LList_DestInsert(Head,1,6);
 	CirDou_LList_DestInsert(Head,2,7);
 	CirDou_LList_DestInsert(Head,3,8);
 	CirDou_LList_DestInsert(Head,4,9);
 //遍历一遍并打印出来
 	CirDou_LList_Print(Head);
 //从头部删除节点
     CirDou_LList_HeadDel(Head);
	 CirDou_LList_HeadDel(Head);
 //遍历一遍并打印出来
 	CirDou_LList_Print(Head);
 //从尾部删除节点
     CirDou_LList_TailDel(Head);
     CirDou_LList_TailDel(Head);
 //遍历一遍并打印出来
 	CirDou_LList_Print(Head);
  //从指定位置删除节点
 	 CirDou_LList_DestDel(Head,3);//头删
 	 CirDou_LList_DestDel(Head,20);//尾删
     CirDou_LList_DestDel(Head,7);//中间删
  //遍历一遍并打印出来
 	CirDou_LList_Print(Head);
 	return 0 ;
 }
posted @ 2024-04-25 13:52  大螺丝贼六  阅读(27)  评论(0)    收藏  举报
html