/**********************************************************************************
*
-
file name: 004_双向链表.c
-
author : [email protected]
-
date : 2024/04/24
-
function : 设计双向循环链表的接口
-
note : None
-
CopyRight (c) 2024-2024 [email protected] 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
-
@version :1.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
-
@version :1.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
-
@version :1.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
-
@version :1.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;
}```
标签:tmp,head,DoubleLList,接口,next,链表,双向,NULL
From: https://www.cnblogs.com/wwwwariana/p/18156376