/**********************************************************************************
*
* file name: 004_双向循环链表.c
* author : A13326981379@163.com
* date : 2024/04/25
* 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: DoubleCirLList_Create
* @brief : 创建一个空双向循环链表,空链表应该有一个头结点,对链表进行初始化
* @param : 无
* @retval :
* @head: 返回头节点
* @date : 2024/04/25
* @version : 1.0
* @note : 该函数定义头节点并初始化头节点,再返回头节点
*
*
*
* *******************************************************************************/
DoubleLList_t * DoubleCirLList_Create(void)
{
DoubleLList_t *Head = (DoubleLList_t *)calloc(1,sizeof(DoubleLList_t));
if (NULL == Head)
{
perror("Calloc memory for Head is Failed");
exit(-1);
}
Head->prev = Head;
Head->next = Head;
return Head;
}
/* *********************************************************************************
*
*
* @function name: DoubleCirLList_NewNode
* @brief : 创建新的结点,并对新结点进行初始化(数据域 + 指针域)
* @param :
* @data:传将来的数据
* @retval :
* @New : 返回新数据的节点
* @date : 2024/04/25
* @version :1.0
* @note : 该函数将传进来的数据创建新节点并初始化,返回新节点
*
*
* *******************************************************************************/
DoubleLList_t * DoubleCirLList_NewNode(DataType_t data)
{
DoubleLList_t *New = (DoubleLList_t *)calloc(1,sizeof(DoubleLList_t));
if (NULL == New)
{
perror("Calloc memory for NewNode is Failed");
return NULL;
}
New->data = data;
New->prev = New;
New->next = New;
return New;
}
/* *********************************************************************************
*
*
* @function name: DoubleCirHeadInsert
* @brief : 将数据插入链表的头部
* @param :
* @data:传将来的数据
* @head:头节点
* @retval :无
* @date : 2024/04/25
* @version :1.0
* @note : 无
*
*
* *******************************************************************************/
void DoubleCirHeadInsert(DoubleLList_t *head,DataType_t data)
{
DoubleLList_t *New = DoubleCirLList_NewNode(data);
if (NULL == New)
{
printf("can not insert new node\n");
return;
}
if (head->next == head)
{
head->next = New;
New->next = New;
New->prev = New;
return;
}
DoubleLList_t *tmp = head->next;
while (tmp->next != head->next)
{
tmp = tmp->next;
}
New->prev = tmp;
New->next = head->next;
tmp->next = New;
head->next->prev = New;
head->next = New;
return;
}
/* *********************************************************************************
*
*
* @function name: DoubleCirTailInsert
* @brief : 将数据插入链表的尾部
* @param :
* @data:传将来的数据
* @head:头节点
* @retval :无
* @date : 2024/04/25
* @version :1.0
* @note : 无
*
*
* *******************************************************************************/
void DoubleCirTailInsert(DoubleLList_t *head,DataType_t data)
{
DoubleLList_t *New = DoubleCirLList_NewNode(data);
if (NULL == New)
{
printf("can not insert new node\n");
return;
}
if (head->next == head)
{
head->next = New;
New->next = New;
New->prev = New;
return;
}
DoubleLList_t *tmp = head->next;
while (tmp->next != head->next)
{
tmp = tmp->next;
}
New->next = tmp->next;
New->prev = tmp;
tmp->next = New;
head->next->prev = New;
return;
}
/* *********************************************************************************
*
*
* @function name: DoubleCirDestvalInsert
* @brief : 将数据插入链表指定数据后的位置
* @param :
* @data :传将来的数据
* @destval:指定数据
* @head :头节点
* @retval :无
* @date : 2024/04/25
* @version :1.0
* @note : 该函数是将数据插入指定数据的直接后继节点
*
*
* *******************************************************************************/
void DoubleCirDestvalInsert(DoubleLList_t *head,DataType_t destval,DataType_t data)
{
DoubleLList_t *New = DoubleCirLList_NewNode(data);
if (NULL == New)
{
printf("can not insert new node\n");
return;
}
if (head->next == head)
{
printf("链表为空!找不到指定数据!\n");
return;
}
DoubleLList_t *tmp = head;
while (head->next->prev != tmp)
{
tmp = tmp->next;
if (tmp->data == destval)
{
New->next = tmp->next;
New->prev = tmp;
tmp->next->prev = New;
tmp->next = New;
return;
}
}
if (tmp->data == destval)
{
New->next = head->next;
New->prev = tmp;
head->prev = New;
tmp->next = New;
}
else
printf("该链表中没有指定的数据!\n");
return ;
}
/* *********************************************************************************
*
*
* @function name: DoubleCirHeadDel
* @brief : 将数据从头部删除
* @param :
* @head:头节点
* @retval :无
* @date : 2024/04/25
* @version :1.0
* @note : 当链表删除掉为最后一个元素时需要重新对头节点做初始化,所以链表删掉只剩一个元素时做特殊处理
*
*
* *******************************************************************************/
void DoubleCirHeadDel(DoubleLList_t *head)
{
if (head->next == head)
{
printf("The Link is empty! can not delete!");
return;
}
DoubleLList_t *tmp = head->next;
DoubleLList_t *phead = head;
if (tmp->next == head->next)
{
head->next = head;
head->prev = head;
tmp->next = NULL;
tmp->next = NULL;
free(tmp);
return;
}
while (head->next->prev != phead)
{
phead = phead->next;
}
phead->next = tmp->next;
tmp->next->prev = phead;
head->next = tmp->next;
tmp->next = NULL;
tmp->prev = NULL;
free(tmp);
return ;
}
/* *********************************************************************************
*
*
* @function name: DoubleCirTailDel
* @brief : 将数据从尾部删除
* @param :
* @head :头节点
* @retval :无
* @date : 2024/04/25
* @version :1.0
* @note : 当链表删除掉为最后一个元素时需要重新对头节点做初始化,所以链表删掉只剩一个元素时做特殊处理
*
*
* *******************************************************************************/
void DoubleCirTailDel(DoubleLList_t *head)
{
if (head->next == head)
{
printf("The Link is empty! can not delete!");
return;
}
DoubleLList_t *tmp = head->next;
DoubleLList_t *phead = head;
if (tmp->next == head->next)
{
head->next = head;
head->prev = head;
tmp->next = NULL;
tmp->next = NULL;
free(tmp);
return;
}
while (head->next->prev != phead)
{
phead = phead->next;
}
phead->prev->next = tmp;
tmp->prev = phead->prev;
phead->next = NULL;
phead->prev = NULL;
free(phead);
return ;
}
/* *********************************************************************************
*
*
* @function name: DoubleCirDestvalDel
* @brief : 将数据从指定数据位置删除
* @param :
* @head :头节点
* @destval:指定的数据
* @retval :无
* @date : 2024/04/25
* @version :1.0
* @note : 当链表删除掉为最后一个元素时需要重新对头节点做初始化,所以链表删掉只剩一个元素时做特殊处理
* 当链表遍历到最后一个元素还没找到目标值时,分两种情况,最后一个元素是目标值和最后一个元素不是目标值
* 如果最后一个元素是目标值,则进行特殊尾删操作,如果最后一个元素不是目标值,则输出:该链表中没有找到需要删除的数据!并结束函数
*
* *******************************************************************************/
void DoubleCirDestvalDel(DoubleLList_t *head,DataType_t destval)
{
if (head->next == head)
{
printf("The Link is empty! can not delete!");
return;
}
DoubleLList_t *tmp = head->next;
DoubleLList_t *phead = head->next;
if (tmp->next == head->next)
{
head->next = head;
head->prev = head;
tmp->next = NULL;
tmp->next = NULL;
free(tmp);
return;
}
while (tmp->data != destval)
{
tmp = tmp->next;
if (tmp->next == phead)
{
if (tmp->data != destval)
{
printf("该链表中没有找到需要删除的数据!\n");
return;
}
tmp->prev->next = phead;
phead->prev = tmp->prev;
tmp->next = NULL;
tmp->prev = NULL;
free(tmp);
return;
}
}
if (tmp->data == head->next->data)
{
while (phead->next != head->next)
{
phead = phead->next;
}
phead->next = tmp->next;
tmp->next->prev = phead;
head->next = tmp->next;
tmp->next = NULL;
tmp->prev = 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: DoubleCirLinkPrintf
* @brief : 将数据从链表中打印出来
* @param :
* @head :头节点
* @retval :
* 无
* @date : 2024/04/25
* @version :1.0
* @note : 无
*
*
* *******************************************************************************/
void DoubleCirLinkPrintf(DoubleLList_t *head)
{
//对单向循环链表的头结点的地址进行备份
DoubleLList_t *Phead = head;
//判断当前链表是否为空,为空则直接退出
if (head->next == head)
{
printf("current linkeflist is empty!\n");
return;
}
while (head->next->prev != Phead)
{
Phead = Phead->next;
printf("data = %d\n",Phead->data);
}
}
int main(int argc, char const *argv[])
{
DoubleLList_t *head = DoubleCirLList_Create()
//头插
printf("头插法:\n")
DoubleCirHeadInsert(head,1)
DoubleCirHeadInsert(head,2)
DoubleCirHeadInsert(head,3)
DoubleCirHeadInsert(head,4)
DoubleCirLinkPrintf(head)
printf("\n")
//尾插法
printf("尾插法:\n")
DoubleCirTailInsert(head,8)
DoubleCirTailInsert(head,9)
DoubleCirTailInsert(head,10)
DoubleCirLinkPrintf(head)
printf("\n")
//指定插法
printf("指定插法:\n")
DoubleCirDestvalInsert(head,4,12)
DoubleCirDestvalInsert(head,8,20)
DoubleCirDestvalInsert(head,10,50)
DoubleCirDestvalInsert(head,7,12)
DoubleCirLinkPrintf(head)
printf("\n")
//头删法
printf("头删法:\n")
DoubleCirHeadDel(head)
// DoubleCirHeadDel(head)
// DoubleCirHeadDel(head)
// DoubleCirHeadDel(head)
// DoubleCirHeadDel(head)
// DoubleCirHeadDel(head)
// DoubleCirHeadDel(head)
// DoubleCirHeadDel(head)
// DoubleCirHeadDel(head)
// DoubleCirHeadDel(head)
DoubleCirLinkPrintf(head)
printf("\n")
//尾删法
printf("尾删法:\n")
DoubleCirTailDel(head)
// DoubleCirTailDel(head)
// DoubleCirTailDel(head)
// DoubleCirTailDel(head)
// DoubleCirTailDel(head)
// DoubleCirTailDel(head)
// DoubleCirTailDel(head)
// DoubleCirTailDel(head)
// DoubleCirTailDel(head)
DoubleCirLinkPrintf(head)
printf("\n")
//指定删法
printf("指定删法:\n")
// DoubleCirDestvalDel(head,12)
// DoubleCirDestvalDel(head,10)
// DoubleCirDestvalDel(head,8)
// DoubleCirDestvalDel(head,3)
// DoubleCirDestvalDel(head,1)
// DoubleCirDestvalDel(head,2)
// DoubleCirDestvalDel(head,20)
// DoubleCirDestvalDel(head,9)
DoubleCirDestvalDel(head,10)
DoubleCirLinkPrintf(head)
return 0
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)