设计双向链表的插入、删除和遍历接口

/**********************************************************************************
*

  •      file name:  004_双向链表.c
    
  •      author   :  A13326981379@163.com
    
  •      date     :  2024/04/24
    
  •      function :  设计双向链表的接口
    
  •      note     :  None
    
  •      CopyRight (c) 2024-2024  A13326981379@163.com    All Right Reseverd
    
  • *******************************************************************************/
#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>


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

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

}DoubleLList_t;
/* *********************************************************************************
 *
 *          
 *     @function name:	DoubleLList_Create
 *     @brief        :  创建一个空双向链表,空链表应该有一个头结点,对链表进行初始化
 *     @param        :  无
 *     @retval       :
 *              @head:  返回头节点
 *     @date         :  2024/04/24
 *     @version      : 1.0 
 *     @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;
}
/* *********************************************************************************
 *
 *          
 *     @function name:	DoubleLList_NewNode
 *     @brief        :  创建新的结点,并对新结点进行初始化(数据域 + 指针域)
 *     @param        :  
 *                      @data:传将来的数据
 *     @retval       :
 *                      @New : 返回新数据的节点
 *     @date         : 2024/04/24
 *     @version      :1.0 
 *     @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;
}```

/* *********************************************************************************
*
*

  • @function name:	DoubleHeadInsert
    
  • @brief        :  将数据插入链表的头部
    
  • @param        :  
    
  •                  @data:传将来的数据
    
  •                  @head:头节点
    
  • @retval       :
    
  •                  @New:布尔类型的真或假
    
  • @date         : 2024/04/24
    
  • @version1.0 
    
  • @note         :
  • *******************************************************************************/```
//头插
bool DoubleHeadInsert(DoubleLList_t *head,DataType_t data)
{
    DoubleLList_t * New = DoubleLList_NewNode(data);
    //1.判断是否为空链表
    if (head->next == NULL)
    {
        
        head->next = New;
        return true;
    }
    //不为空直接插入
    New->next = head->next;
    head->next->prev = New;
    head->next = New;
    return true;
}```

/* *********************************************************************************
*
*

  • @function name:	DoubleTailInsert
    
  • @brief        :  将数据插入链表的尾部
    
  • @param        :  
    
  •                  @data:传将来的数据
    
  •                  @head:头节点
    
  • @retval       :
    
  •                  @New:布尔类型的真或假
    
  • @date         : 2024/04/24
    
  • @version1.0 
    
  • @note         :
  • *******************************************************************************/```
//尾插
bool DoubleTailInsert(DoubleLList_t *head,DataType_t data)
{
    DoubleLList_t * New = DoubleLList_NewNode(data);
    //1.判断是否为空链表
    if (head->next == NULL)
    {
        
        head->next = New;
        return true;
    }
    DoubleLList_t *tmp = head;
    //遍历
    while (tmp->next)
    {
        tmp = tmp->next;
    }
    New->prev = tmp;
    tmp->next = New;
    return true;

}```

/* *********************************************************************************
*
*

  • @function name:	DoubleDesInsert
    
  • @brief        :  将数据插入链表指定数据后的位置
    
  • @param        :  
    
  •                  @data   :传将来的数据
    
  •                  @destval:指定数据
    
  •                  @head   :头节点
    
  • @retval       :
    
  • @date         : 2024/04/24
    
  • @version1.0 
    
  • @note         : 该函数是将数据插入指定数据的直接后继节点
    
  • *******************************************************************************/```
//指定插
void DoubleDesInsert(DoubleLList_t *head,DataType_t destval,DataType_t data)
{
    DoubleLList_t * New = DoubleLList_NewNode(data);
    //1.判断是否为空链表
    if (head->next == NULL)
    {
        head->next = New;
        return;
    }
    DoubleLList_t *tmp = head;
    //遍历
    while (tmp->data != destval)
    {
        tmp = tmp->next;
        //插在尾部
        if (tmp->next == NULL)
        {
            New->prev = tmp;
            tmp->next = New;
            return;
        }
        
    }
    New->next = tmp->next;
    New->prev = tmp;
    tmp->next->prev = New;
    tmp->next = New;
    return;
}
/* *********************************************************************************
 *
 *          
 *     @function name:	DoubleHeadDel
 *     @brief        :  将数据从头部删除
 *     @param        :  
 *                      @head   :头节点
 *     @retval       :
 * *     @date         : 2024/04/24
 *     @version      :1.0 
 *     @note         : 无
 * 
 *
 * *******************************************************************************/

//头删
void DoubleHeadDel(DoubleLList_t *head)
{
    //1.判断是否为空链表
    if (head->next == NULL)
    {
        printf("该链表为空!没有数据可以删除\n");
        return;
    }
    //2.判断是否只有一个节点
    if (head->next->next == NULL)
    {
        head->next = NULL;
        free(head->next);
        return;
    }
    //3.有多个数据的头删
    DoubleLList_t *tmp = head->next;//临时节点备份首节点
    head->next = tmp->next;
    tmp->next->prev = NULL;
    tmp->next = NULL;
    free(tmp);
    return;
}
/* *********************************************************************************
 *
 *          
 *     @function name:	DoubleTailDel
 *     @brief        :  将数据从尾部删除
 *     @param        :  
 *                      @head   :头节点
 *     @retval       :
 * *     @date         : 2024/04/24
 *     @version      :1.0 
 *     @note         : 无
 * 
 *
 * *******************************************************************************/

//尾删
void DoubleTailDel(DoubleLList_t *head)
{
    //1.判断是否为空链表
    if (head->next == NULL)
    {
        printf("该链表为空!没有数据可以删除\n");
        return;
    }
    //2.判断是否只有一个节点
    if (head->next->next == NULL)
    {
        head->next = NULL;
        free(head->next);
        return;
    }
    //3.多个数据尾删
    DoubleLList_t *tmp = head->next;//临时节点备份首节点
    while (tmp->next != NULL)
    {
        tmp = tmp->next;
    }
    tmp->prev->next = NULL;
    tmp->prev = NULL;
    free(tmp);
    return;
    
}```

/* *********************************************************************************
*
*

  • @function name:	DoubleDestDel
    
  • @brief        :  将数据从指定位置删除
    
  • @param        :  
    
  •                  @head   :头节点
    
  •                  @destval:指定的数据
    
  • @retval       :
    
  • @date         : 2024/04/24
    
  • @version1.0 
    
  • @note         : 该函数是将指定删除数据的节点删除,如果输入的节点数据在链表中没有,那么会出del error信息
    
  • *******************************************************************************/```
//指定删
void DoubleDestDel(DoubleLList_t *head,DataType_t destval)
{
    //1.判断是否为空链表
    if (head->next == NULL)
    {
        printf("该链表为空!没有数据可以删除\n");
        return;
    }
    //2.判断是否只有一个节点
    if (head->next->next == NULL&& head->next->data == destval)
    {
        head->next = NULL;
        free(head->next);
        return;
    }
    
    DoubleLList_t *tmp = head->next;//临时节点备份首节点
    //3.判断条件改成对比数据是否相等,不相等进去循环,往后遍历
    while (tmp->data != destval)
    {
        tmp = tmp->next;
        // 需要删除的节点刚好在尾节点
        if (tmp->next == NULL)
        {
            if (tmp->data == destval)
            {
                tmp->prev->next = NULL;
                tmp->prev = NULL;
                free(tmp);
            }
            else
            {
                printf("del error!\n");
            }
            return;
        }
    }
    // 想要删除的节点刚好在首节点
    if (tmp->data == destval && tmp->prev == NULL)
    {
        head->next = tmp->next;
        tmp->next->prev = NULL;
        tmp->next = NULL;
        free(tmp);
        return;
    }
    tmp->prev->next = tmp->next;
    tmp->next->prev = tmp->prev;
    tmp->next = NULL;
    tmp->prev = NULL;
    free(tmp);
    return;
}
/* *********************************************************************************
 *
 *          
 *     @function name:	DoubleLList_printf
 *     @brief        :  将数据从链表中打印出来
 *     @param        :  
 *                      @head   :头节点
 *     @retval       :
 *                      无
 *     @date         : 2024/04/24
 *     @version      :1.0 
 *     @note         : 无
 * 
 *
 * *******************************************************************************/
//遍历链表
void DoubleLList_printf(DoubleLList_t *head)
{
    //判断是否为空链表
    if (head->next == NULL)
    {
        printf("The Link is empty!\n");
        return;
    }
    DoubleLList_t *tmp = head;
    while (tmp->next)
    {
        //把头结点的直接后继作为新的头结点
		tmp = tmp->next;

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

		//判断是否到达尾结点,尾结点的next指针是指向首结点的地址
		if (tmp->next == NULL)
			return;
    }
    
    
    
    
}
int main(int argc, char const *argv[])
{
	DoubleLList_t *head = DoubleLList_Create();

    DoubleHeadInsert(head,1);
    DoubleHeadInsert(head,2);
    DoubleHeadInsert(head,6);
    DoubleHeadInsert(head,7);
    DoubleHeadInsert(head,8);
    DoubleHeadInsert(head,9);
    DoubleHeadInsert(head,100);
    DoubleLList_printf(head);
    printf("\n");
    //尾插
    printf("尾插法:\n");
    DoubleTailInsert(head,10);
    DoubleLList_printf(head);

    printf("\n");
    //指定插
    printf("指定插法:\n");
    DoubleDesInsert(head,10,5);
    DoubleDesInsert(head,1,50);
    DoubleLList_printf(head);

    printf("\n");
    //头删
    printf("头删法:\n");
    DoubleHeadDel(head);
    DoubleLList_printf(head);

    printf("\n");
    //尾删
    printf("尾删法:\n");
    DoubleTailDel(head);
    DoubleLList_printf(head);

    printf("\n");
    //指定删
    printf("指定删法:\n");
    DoubleDestDel(head,9);
    DoubleDestDel(head,6);
    DoubleDestDel(head,10);
    DoubleDestDel(head,55);
    DoubleLList_printf(head);
	return 0;
}```
posted @   A-A-A-Ariana  阅读(11)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
点击右上角即可分享
微信分享提示