首页 > 其他分享 >数据结构:双向循环链表的创建·插入·删除

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

时间:2024-04-25 13:56:40浏览次数:15  
标签:current Head next 链表 LList 双向 CirDou New 数据结构

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

/**
  * @file name : 数据结构:双向循环链表的创建·插入·删除
  * @brief     : 实现双向循环链表的创建·插入·删除
  * @author	   : [email protected]
  * @date 	   :2024/04/24
  * @version   :2.0
  * @note      :none
  * CopyRight(c):  2023-2024   [email protected]   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   : [email protected]
  */
  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   : [email protected]
  */
 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   : [email protected]
  */
  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   : [email protected]
  */
 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   : [email protected]
  */
 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   : [email protected]
  */
 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   : [email protected]
  */
 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   : [email protected]
  */
 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   : [email protected]
  */
 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   : [email protected]
  */
 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 ;
 }

标签:current,Head,next,链表,LList,双向,CirDou,New,数据结构
From: https://www.cnblogs.com/liuliuye/p/18157580

相关文章

  • 双向循环链表的创建练习
    include<stdio.h>include<stdlib.h>/**@filename: Untitled-1.c@brief双向链表@[email protected]@date2024/04/[email protected]:版本@property:属性介绍@noteCopyRight(c)[email protected]*/typedefstru......
  • 数据结构——单向循环链表
    一、单向循环链表(一)单向循环链表的构造单向循环链表的尾结点的指针域中必须指向链表的首结点的地址1)构造单向循环链表的结点//单向循环链表中的结点有效数据类型,用户可以根据需要进行修改typedefintDataType_t;//构造单向循环链表的结点,链表中所有结点的数据类型应该......
  • 双向循环链表的增删改查
    数据结构双向循环链表双向循环链表的增删改查/***************************************************************************************filename:1.c*author: [email protected]*date:2024/04/24*function: 双向循环链表的增删......
  • C语言数据结构:链式栈及其出入栈
    /***********************************************************************************************************实现链式栈一般是以链表作为基础,一般是把链表头部作为栈顶,方便数据的插入和删除,链式栈相当于是一个单向不循环的链表。****Copyright(c)2023-2......
  • C语言数据结构:双向循环链表的增删操作
    /***********************************************************************************************************设计双向循环链表的接口****Copyright(c)[email protected]**********************************************......
  • 双向循环链表的接口
    双向循环链表的接口头文件#include<stdbool.h>#include<stdio.h>#include<string.h>#include<stdlib.h>​```创建链表、节点//指的是双向循环链表中的结点有效数据类型,用户可以根据需要进行修改hjtypedefintDataType_t;//构造双向循环链表的结点,链表中所有结......
  • 数据结构:双向循环链表的创建·插入·删除
    数据结构:双向循环链表的创建·插入·删除/***@filename:数据结构:双向循环链表的创建·插入·删除*@brief:实现双向循环链表的创建·插入·删除*@author :[email protected]*@date :2024/04/24*@version:1.0*@note:none*CopyRig......
  • 双向循环链表
    双向循环链表原理与应用双向循环链表与双向链表的区别:指的是双向循环链表的首结点中的prev指针成员指向链表的尾结点,并且双向循环链表的尾结点里的next指针成员指向链表的首结点,所以双向循环链表也属于环形结构。双向循环链表各功能实现(1)为了管理双向循环链表,需要构造头结点......
  • 数据结构:双向链表的创建·插入·删除
    数据结构:双向链表的创建·插入·删除/***@filename:数据结构:双向链表的创建·插入·删除*@brief:实现双向链表的创建·插入·删除*@author :[email protected]*@date :2024/04/23*@version:1.0*@note:none*CopyRight(c......
  • 反转链表
    packagemainimport"fmt"typeListNodestruct{ValintNext*ListNode}funcreverseList(head*ListNode)*ListNode{ifhead==nil||head.Next==nil{returnhead}newHead:=reverseList(head.Next)he......