双向链表

news/发布时间2024/5/17 3:03:15

以下为双向链表(待测试4.23)

/***************************************************   file name:LkList.c*   author   :momolyl@126.com*   date     :2024/04/23*   brief    :通过构建双向链表学习顺序存储*   note     :None**   CopyRight (c) 2024    momolyl@126.com    All Right Reseverd***************************************************/
#include <stdbool.h>
#include <stdlib.h>
#include <stdio.h>
/***************************************************   func name     :*   brief         :*   func parameter:***   return        :None*   note          :None*   func author   :momolyl@126.com*   date          :2024/04/23*   version       :V1.0**************************************************/
// 结构体用于构建链表节点(指针域1+数据域+指针域2)
typedef int Datatype_t;
typedef struct DoulbeLkList
{struct DoulbeLkList *Prev; // 直接前驱的指针域Datatype_t Data;           // 结点的数据域struct DoulbeLkList *Next; // 直接后继的指针域
} DoulbeLkList_t;// 创建一个双向空链表,使用头节点
DoulbeLkList_t *DoubleLkList_Create(void)
{DoulbeLkList_t *Head = (DoulbeLkList_t *)calloc(1, sizeof(DoulbeLkList_t)); // 为头节点申请内存,并错误处理if (NULL == Head){perror("calloc memory for DoulbeLkList if failed!\n");exit(-1);}// 对头结点进行初始化,头结点是不存储数据域,指针域指向NULLHead->Next = NULL; // 对头结点进行初始化,头结点是不存储数据域,指针域指向NULLHead->Prev = NULL;return Head; // 返回头节点的地址
}// 创建一个新节点,并对新节点初始化(指针域1+数据域+指针域2)
DoulbeLkList_t *DoulbeLkList_NewNode(Datatype_t data)
{DoulbeLkList_t *NewNode = (DoulbeLkList_t *)calloc(1, sizeof(DoulbeLkList_t)); // 为新节点申请一个地址,if (NULL == NewNode)                                                           // 申请新节点的错误处理{perror("calloc memory for NewNode if failed!\n");exit(-1);}NewNode->Data = data; // 初始化数据域NewNode->Next = NULL; // 初始化指针域2NewNode->Prev = NULL; // 初始化指针域1return NewNode;
}
//****************************************************************************21 : 53
// 向链表中头插一个新节点
void DoulbeLkList_HeadAdd(DoulbeLkList_t *Head, Datatype_t data)
{DoulbeLkList_t *NewNode = DoulbeLkList_NewNode(data);if (NULL == Head->Next) // 判断链表是否为空{// 链表为空Head->Next = NewNode;return;}// 2.2链表非空{NewNode->Next = Head->Next; // 让新结点的Next指针指向首结点的地址Head->Next->Prev = NewNode; // 让首结点的Prev指针指向新结点的地址Head->Next = NewNode;       // 让头节点的Next指针指向新结点的地址NewNode->Prev = NULL;       // 让新结点的Prev指针指向NULL}
}// 向链表中尾插一个新节点
void DoulbeLkList_TailAdd(DoulbeLkList_t *Head, Datatype_t data)
{DoulbeLkList_t *NewNode = DoulbeLkList_NewNode(data);if (NULL == Head->Next) // 判断链表是否为空{// 链表为空Head->Next = NewNode;return;}// 2.2链表非空DoulbeLkList_t *Phead = Head->Next; // 备份首结点的地址// 遍历找到尾结点while (Phead->Next) // 判断条件为:当前结点的Next指针是否指向NULL{Phead = Phead->Next; // Phead在循环结束时代表尾结点的地址}// 在尾端插入新节点Phead->Next = NewNode; // 让尾结点的Next指针指向新结点的地址NewNode->Prev = Phead; // 让新结点的Prev指针指向尾结点的地址
}// 向链表中指定数据结点后插入一个新节点
void DoulbeLkList_AppointAdd(DoulbeLkList_t *Head, Datatype_t DestVal, Datatype_t data)
{DoulbeLkList_t *NewNode = DoulbeLkList_NewNode(data);if (NULL == Head->Next) // 判断链表是否为空{// 链表为空Head->Next = NewNode;return;}// 2.2链表非空DoulbeLkList_t *Phead = Head->Next; // 备份首结点的地址DoulbeLkList_t *Dest = NULL;        // 用于判断是否成功查找到指定数值的结点// 遍历找到指定数据结点while (Phead->Next) // 遍历整个链表,确保未找到指定数值也能正常退出循环{if (Phead->Data != DestVal) // 判断条件为:当前结点数据是否与指定数值不相等{Phead = Phead->Next; // 不相等则继续循环break;}Dest = Phead; // 相等则停止循环,此时Dest为指定节点的地址}if (Dest) // 如果成功查找到指定数值,则在指定数据结点后面插入新节点{NewNode->Next = Phead->Next; // 让新结点的Next指针指向目标地址的直接后继结点Phead->Next->Prev = NewNode; // 让目标结点的直接后继结点的Prev指针指向新结点Phead->Next = NewNode;       // 让目标结点的Next指针指向新结点的地址NewNode->Prev = Phead;       // 让新结点的Prev指针指向目标结点的地址}else{printf("Can find the DestVal %d!\n", DestVal);}
}// 在链表中头删一个节点
bool DoulbeLkList_HeadDel(DoulbeLkList_t *Head)
{// 判断链表是否为空if (NULL == Head->Next) // 判断链表是否为空{// 链表为空return false;}// 链表非空DoulbeLkList_t *Phead = Head->Next; // 备份首节点地址,用于最后释放首结点地址Head->Next = Phead->Next;           // 让头结点的Next指针指向首结点的直接后继结点Phead->Next = NULL;                 // 让首结点的Next指针指向NULLHead->Next->Prev = NULL;            // 让首结点的直接后继结点的Prev指针指向NULLfree(Phead);return true;
}// 在链表中尾删一个节点
bool DoulbeLkList_TailDel(DoulbeLkList_t *Head)
{// 判断链表是否为空if (NULL == Head->Next) // 判断链表是否为空{// 链表为空return false;}DoulbeLkList_t *Phead1 = Head->Next; // 备份首节点地址,用于遍历查找尾结点DoulbeLkList_t *Phead2 = Head;       // 备份头节点地址,用于遍历查找尾结点的直接前驱结点// 遍历查找尾结点while (Phead1->Next) // 判断条件为:当前结点的Next指针是否指向首结点{Phead1 = Phead1->Next; // Phead1在循环结束时代表尾结点的地址Phead2 = Phead2->Next; // Phead2在循环结束时代表尾结点的直接前驱结点的地址}Phead1->Prev = NULL; // 将尾结点Prev指针指向NULLPhead2->Next = NULL; // 将尾结点的直接前驱结点的Next指针指向NULLfree(Phead1);return true;
}// 在链表中删指定数据结点
bool DoulbeLkList_AppointDel(DoulbeLkList_t *Head, Datatype_t DestVal)
{// 判断链表是否为空if (NULL == Head->Next) // 判断链表是否为空{// 链表为空return false;}DoulbeLkList_t *Phead1 = Head->Next; // 备份首结点的地址,用于遍历目标节点DoulbeLkList_t *Phead2 = Head;       // 备份头结点的地址,用于遍历目标节点的前驱结点DoulbeLkList_t *Dest = NULL;         // 用于判断是否成功查找到指定数值的结点// 遍历找到指定数据结点while (Phead1->Next) // 判断条件为:当前结点是否为尾结点,确保没有找到目标节点循环也能正常退出{if (Phead1->Data != DestVal) // 判断条件为:当前结点数据是否与指定数值不相等{Phead1 = Phead1->Next; // 不相等则继续循环Phead2 = Phead2->Next;break;}Dest = Phead1; // 相等则停止循环,此时Phead1为指定节点的地址,Phead2为目标结点的前驱结点地址,Dest用于判断是否成功查找}if (Dest == NULL) // 如果没有找到指定数值,则删除失败{printf("Can find the DestVal %d!\n", DestVal);return false;}else // 如果成功查找到指定数值,则删除指定数据结点{// 1.目标结点为首节点(使用头删函数的代码)if (Phead1 == Head->Next){DoulbeLkList_t *Phead = Head->Next; // 备份首节点地址,用于最后释放首结点地址Head->Next = Phead->Next;           // 让头结点的Next指针指向首结点的直接后继结点Phead->Next = NULL;                 // 让首结点的Next指针指向NULLHead->Next->Prev = NULL;            // 让首结点的直接后继结点的Prev指针指向NULLfree(Phead);return true;}// 2.目标结点为尾节点(使用尾删函数的代码)else if (Phead1->Next == NULL){DoulbeLkList_t *Phead3 = Head->Next; // 备份首节点地址,用于遍历查找尾结点DoulbeLkList_t *Phead4 = Head;       // 备份头节点地址,用于遍历查找尾结点的直接前驱结点// 遍历查找尾结点while (Phead1->Next) // 判断条件为:当前结点的Next指针是否指向首结点{Phead3 = Phead3->Next; // Phead1在循环结束时代表尾结点的地址Phead4 = Phead4->Next; // Phead2在循环结束时代表尾结点的直接前驱结点的地址}Phead3->Prev = NULL; // 将尾结点Prev指针指向NULLPhead4->Next = NULL; // 将尾结点的直接前驱结点的Next指针指向NULLfree(Phead3);return true;}// 3.目标结点在中间else{Phead2->Next = Phead1->Next; // 让目标结点的直接前驱结点的Next指针指向目标结点的直接后继结点Phead1->Next->Prev = Phead2; // 让目标结点的直接后继结点的Prev指针指向目标结点的直接前驱结点Phead1->Next = NULL;Phead1->Prev = NULL;free(Phead1);return true;}}
}int main(void)
{DoubleLkList_Create();return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.ulsteruni.cn/article/53206238.html

如若内容造成侵权/违法违规/事实不符,请联系编程大学网进行投诉反馈email:xxxxxxxx@qq.com,一经查实,立即删除!

相关文章

使用ollama分别在我的window、mac、小米手机上部署体验llama3-8b

1、ollama到底是个什么玩意 一句话来说, Ollama 是一个基于 Go 语言开发的简单易用的本地大模型运行框架。可以将其类比为 docker(有类似docker中的一些常规命令list,pull,push,run 等等),事实上确实也制定了类似 docker 的一种模型应用标准,在后边的内容中,你能更加真切…

pwn知识——劫持__malloc_hook(在加入tcache以后)

导论 动调是最好的导师! malloc_hook函数解析 malloc_hook是malloc的钩子函数,在执行malloc时,会先检测__malloc_hook的值,如果malloc_hook的值存在,则执行该地址(值里边表现为十六进制,可以成为地址),也就是说,如果我们成功劫持malloc_hook以后并修改它的值为one_ga…

4.21 团队作业——第二天

今天进行了晨会主要内容是进行了任务的时间管理分配,每个团队成员领取了任务,并且进行了任务的时间限制,燃尽图的书写概况

IEAD添加插件生成UML图

使用IDEA中生成UML(统一建模语言) 一、准备环境 在Ubuntu环境下进行配置使用,工具和插件在Windows环境下也有版本,需要的工具、插件都是相同的,同样安装配置即可。 。IDEA社区版:因为免费 。插件PlantUML Parser:生成".puml"文件 。GrapHviz:通过puml文件生成…

ubuntu无法进入桌面的一种情况

问题描述无法进入桌面 可以进入锁屏 输入密码后黑屏,并返回锁屏 tty能进入startx startx中部分软件无法打开 无法进入桌面最直接的错误,非常严重不可原谅。用户登陆输入密码,黑屏,然后回到用户登陆。后续操作使用tty3执行startx展现。 大量的.desktop无法打开 执行code竟然…