数据结构——双链表

1. 双向带头循环链表

1. 双链表的功能

1. 初始化

2. 销毁

3. 打印

4. 检查链表是否为空

5. 尾插

6. 尾删

7. 头插

8. 头删

9. 在目标节点之后插入数据

10. 删除目标节点

11. 查找

2. 双链表的定义

结构体需要包含三个成员,一个成员存储数据,一个成员存储前一个节点的地址,一个成员存储下一个节点的地址。

typedef int LTDataType;
typedef struct ListNode
{LTDataType data;struct ListNode* next;//指针保存后一个节点的位置struct ListNode* prev;//指针保存前一个节点的位置
}LTNode;

3. 双链表功能实现

创建节点

缩减代码,避免代码冗余

LTNode* CreateNode(LTDataType x) {LTNode* node = (LTNode*)malloc(sizeof(LTNode));//创建节点if (node == NULL) {printf("创建节点失败\n");exit(-1);}node->data = x;node->prev = node;node->next = node;return node;
}

1. 初始化

LTNode* LTInit() {LTNode* phead = CreateNode(-1);return phead;
}

2. 销毁

void LTDestroy(LTNode* phead) {LTNode* ptail = phead->next;LTNode* pointer = NULL;//先释放非哨兵节点//因为链表的最后一个节点的 next 指向哨兵位,// 哨兵位的 prev 指向最后一个节点,形成一个循环。while (ptail!=phead) {pointer = ptail;ptail = ptail->next;free(pointer);}free(phead);
}

3. 打印

void LTPrint(LTNode* phead) {LTNode* ptail = phead->next;while (ptail != phead) {printf("%d ", ptail->data);ptail = ptail->next;}printf("\n");
}

4. 检查链表是否为空

bool LTEmpty(LTNode* phead) {return phead->next == phead;
}

5. 尾插

void LTPushBack(LTNode* phead, LTDataType x) {//assert(phead);//LTNode* node = CreateNode(x);将新节点插入链表尾部//node->prev = phead->next;//node->next = phead;//phead->prev->next = node;//phead->prev = node;LTInsert(phead->prev, x);
}

6. 尾删

void LTPopBack(LTNode* phead) {//assert(phead);//assert(phead->next != phead);//LTNode* pointer = phead->prev;//pointer->prev->next = phead;//phead->prev = pointer->prev;//free(pointer);pointer = NULL;LTErase(phead->prev);
}

7. 头插

void LTPushFront(LTNode* phead, LTDataType x) {//assert(phead);//LTNode* node = CreateNode(x);//node->prev = phead;//node->next = phead->next;//phead->next->prev = node;//phead->next = node;LTInsert(phead, x);
}

8. 头删

void LTPopFront(LTNode* phead) {//assert(phead && phead->next);//LTNode* pointer = phead->next;//phead->next = pointer->next;//pointer->next->prev = phead;//free(pointer);LTErase(phead->next);
}

9. 在目标节点之后插入数据

void LTInsert(LTNode* pos, LTDataType x) {assert(pos);LTNode* node = CreateNode(x);node->prev = pos;node->next = pos->next;pos->next->prev = node;pos->next = node;
}

10. 删除目标节点

void LTErase(LTNode* pos) {assert(pos);LTNode* pointer = pos;pos->prev->next = pos->next;pos->next->prev = pos->prev;free(pointer);
}

11. 查找

LTNode* LTFind(LTNode* phead, LTDataType x) {assert(phead);LTNode* pointer = phead->next;while (pointer != phead) {if (pointer->data == x) {printf("找到了\n");return pointer;}pointer = pointer->next;}return NULL;
}

4. 完整代码

1. DList.h

#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <stdbool.h>
typedef int LTDataType;
typedef struct ListNode
{LTDataType data;struct ListNode* next;//指针保存后一个节点的位置struct ListNode* prev;//指针保存前一个节点的位置
}LTNode;//初始化
LTNode* LTInit();
//销毁链表
void LTDestroy(LTNode* phead);
//打印
void LTPrint(LTNode* phead);
//检查链表是否为空
bool LTEmpty(LTNode* phead);
//尾插
void LTPushBack(LTNode* phead, LTDataType x);
//尾删
void LTPopBack(LTNode* phead);
//头插
void LTPushFront(LTNode* phead, LTDataType x);
//头删
void LTPopFront(LTNode* phead);
//在pos位置之后插入数据
void LTInsert(LTNode* pos, LTDataType x);
//删除pos节点
void LTErase(LTNode* pos);
//查找
LTNode* LTFind(LTNode* phead, LTDataType x);

2. DList.c

#include "DList.h"
//创建节点
LTNode* CreateNode(LTDataType x) {LTNode* node = (LTNode*)malloc(sizeof(LTNode));//创建节点if (node == NULL) {printf("创建节点失败\n");exit(-1);}node->data = x;node->prev = node;node->next = node;return node;
}
//初始化
LTNode* LTInit() {LTNode* phead = CreateNode(-1);return phead;
}
//销毁链表
void LTDestroy(LTNode* phead) {LTNode* ptail = phead->next;LTNode* pointer = NULL;//先释放非哨兵节点//因为链表的最后一个节点的 next 指向哨兵位,// 哨兵位的 prev 指向最后一个节点,形成一个循环。while (ptail!=phead) {pointer = ptail;ptail = ptail->next;free(pointer);}free(phead);
}
//打印
void LTPrint(LTNode* phead) {LTNode* ptail = phead->next;while (ptail != phead) {printf("%d ", ptail->data);ptail = ptail->next;}printf("\n");
}
//检查链表是否为空
bool LTEmpty(LTNode* phead) {return phead->next == phead;
}
//尾插
void LTPushBack(LTNode* phead, LTDataType x) {//assert(phead);//LTNode* node = CreateNode(x);将新节点插入链表尾部//node->prev = phead->next;//node->next = phead;//phead->prev->next = node;//phead->prev = node;LTInsert(phead->prev, x);
}
//尾删
void LTPopBack(LTNode* phead) {//assert(phead);//assert(phead->next != phead);//LTNode* pointer = phead->prev;//pointer->prev->next = phead;//phead->prev = pointer->prev;//free(pointer);pointer = NULL;LTErase(phead->prev);
}
//头插
void LTPushFront(LTNode* phead, LTDataType x) {//assert(phead);//LTNode* node = CreateNode(x);//node->prev = phead;//node->next = phead->next;//phead->next->prev = node;//phead->next = node;LTInsert(phead, x);
}
//头删
void LTPopFront(LTNode* phead) {//assert(phead && phead->next);//LTNode* pointer = phead->next;//phead->next = pointer->next;//pointer->next->prev = phead;//free(pointer);LTErase(phead->next);
}
//在pos位置之后插入数据
void LTInsert(LTNode* pos, LTDataType x) {assert(pos);LTNode* node = CreateNode(x);node->prev = pos;node->next = pos->next;pos->next->prev = node;pos->next = node;
}
//删除pos节点
void LTErase(LTNode* pos) {assert(pos);LTNode* pointer = pos;pos->prev->next = pos->next;pos->next->prev = pos->prev;free(pointer);
}
//查找
LTNode* LTFind(LTNode* phead, LTDataType x) {assert(phead);LTNode* pointer = phead->next;while (pointer != phead) {if (pointer->data == x) {printf("找到了\n");return pointer;}pointer = pointer->next;}return NULL;
}

3. text.c

#include "DList.h"
void Realize(void) {LTNode* phead = LTInit();//创建哨兵节点//检查链表是否为空LTEmpty(phead);if (LTEmpty(phead)) {printf("链表为空\n");}else {printf("链表不为空\n");}//尾插LTPushBack(phead, 5);LTPushBack(phead, 7);//尾删LTPopBack(phead);//头插LTPushFront(phead, 6);//头删LTPopFront(phead);//在pos位置之后插入数据LTInsert(phead->next->next, 8);//删除pos节点LTErase(phead->next);//查找LTFind(phead, 8);//打印LTPrint(phead);//销毁链表LTDestroy(phead);phead = NULL;}
int main() {Realize();return 0;
}

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

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

相关文章

微服务2025/2/15

微服务是一种软件架构风格&#xff0c;它是以专注于单一职责的很多小型项目为基础&#xff0c;组合出复杂的大型应用。 微服务是一种架构。 微服务是一种架构。 微服务是一种架构。 以前自己做项目最常用的架构是单体架构。单体项目不适合开发大型项目。 学习微服务技术来解…

Locust性能压测工具使用指南

Locust是一款用Python编写的开源性能测试工具&#xff0c;主要用于对网站或其他系统进行负载测试和性能测试&#xff0c;以下是关于它的详细介绍&#xff1a; 特点 高可扩展性&#xff1a;能够轻松模拟大量用户并发访问&#xff0c;通过简单增加节点&#xff0c;可以在短时间…

DaoCloud 亮相 2025 GDC丨开源赋能 AI 更多可能

2025 年 2 月 21 日至 23 日&#xff0c;上海徐汇西岸&#xff0c;2025 全球开发者先锋大会以 “模塑全球&#xff0c;无限可能” 的主题&#xff0c;围绕云计算、机器人、元宇宙等多元领域&#xff0c;探讨前沿技术创新、应用场景拓展和产业生态赋能&#xff0c;各类专业论坛、…

Linux 环境“从零”部署 MongoDB 6.0:mongosh 安装与数据操作全攻略

前提 完成linux平台部署MongoDB【部署教程】且完成mongosh的安装 由于本人使用的是6.0版本的MongoDB&#xff0c;新版本 MongoDB&#xff08;尤其是 6.0 及以上版本&#xff09;已经不再默认捆绑传统的 mongo shell&#xff0c;而改用新的 MongoDB Shell&#xff08;mongosh&am…

SQL注入之二次注入

1、概述 二次注入是指已存储&#xff08;数据库、文件&#xff09;的用户输入被读取后再次进入到 SQL 查询语句中导致的注入。 二次注入是sql注入的一种&#xff0c;但是比普通sql注入利用更加困难&#xff0c;利用门槛更高。普通注入数据直接进入到 SQL 查询中&#xff0c;而…

AORO M6北斗短报文终端:将“太空黑科技”转化为安全保障

在卫星导航领域&#xff0c;北斗系统作为我国自主研发的全球卫星导航系统&#xff0c;正以其独特的短报文通信功能引发全球范围内的广泛关注。这一突破性技术不仅使北斗系统在全球四大导航系统中独树一帜&#xff0c;具备了双向通信能力&#xff0c;更通过遨游通讯推出的AORO M…

xss-lab

xss XSS全称跨站脚本(Cross Site Scripting)&#xff0c;为避免与层叠样式表(Cascading Style Sheets, CSS)的缩写混淆&#xff0c;故缩写为XSS。这是一种将任意 Javascript 代码插入到其他Web用户页面中执行以达到攻击目的的漏洞。攻击者利用浏览器的动态展示数据功能&#x…

服务器为什么会禁止 Ping?服务器禁止 Ping 的好处

在网络管理和服务器运维中&#xff0c;经常会遇到服务器禁止 Ping 的情况。为了确保网络安全和减少不必要的风险&#xff0c;管理员可能会选择禁止 Ping 命令&#xff0c;即禁止服务器响应 ICMP 请求。尽管 Ping 命令是网络诊断中常用的工具&#xff0c;但禁止 Ping 也有其合理…

课程2. 用PyTorch训练神经网络与梯度下降

课程2. 用PyTorch训练神经网络与梯度下降 Pytorchtorch.TensorPytorch 上的神经网络用于余弦函数逼近的全连接神经网络 训练神经网络 梯度下降最小化一个变量的函数最小化多个变量的函数使用梯度下降训练神经网络在 Pytorch 中训练神经网络从 nn.Module 类继承 将计算传输到显卡…

IP-----动态路由OSPF(2)

这只是IP的其中一块内容&#xff0c;IP还有更多内容可以查看IP专栏&#xff0c;前一章内容为动态路由OSPF &#xff0c;可通过以下路径查看IP-----动态路由OSPF-CSDN博客,欢迎指正 注意&#xff01;&#xff01;&#xff01;本部分内容较多所以分成了两部分在上一章 5.动态路…

手机打电话时如何识别对方按下的DTMF按键的字符-安卓AI电话机器人

手机打电话时如何识别对方按下的DTMF按键的字符 --安卓AI电话机器人 一、前言 前面的篇章中&#xff0c;使用蓝牙电话拦截手机通话的声音&#xff0c;并对数据加工&#xff0c;这个功能出来也有一段时间了。前段时间有试用的用户咨询说&#xff1a;有没有办法在手机上&#xff…

深入剖析:自定义实现C语言中的atoi函数

在C语言的标准库中&#xff0c; atoi 函数是一个非常实用的工具&#xff0c;它能够将字符串形式的数字转换为对应的整数。然而&#xff0c;当我们深入探究其实现原理时&#xff0c;会发现其中蕴含着许多有趣的编程技巧和细节。本文将详细讲解如何自定义实现一个类似 atoi 功能的…

PyTorch 源码学习:GPU 内存管理之它山之石——TensorFlow BFC 算法

TensorFlow 和 PyTorch 都是常用的深度学习框架&#xff0c;各自有一套独特但又相似的 GPU 内存管理机制&#xff08;BFC 算法&#xff09;。它山之石可以攻玉。了解 TensorFlow 的 BFC 算法有助于学习 PyTorch 管理 GPU 内存的精妙之处。本文重点关注 TensorFlow BFC 算法的核…

流式输出方案:sse与websocket的使用

1、sse(Server-Sent Events) SSE是一种允许服务器向浏览器推送实时更新的技术。它基于HTTP协议&#xff0c;是一种单向的通信方式 单向通信基于HTTP自动重连&#xff08;内置了自动重连机制&#xff0c;当连接断开时&#xff0c;浏览器会自动尝试重新连接&#xff09; 1.1 …

基于定制开发开源AI大模型S2B2C商城小程序的商品选品策略研究

摘要&#xff1a;随着电子商务的蓬勃发展和技术的不断进步&#xff0c;商品选品在电商领域中的重要性日益凸显。特别是在定制开发开源AI大模型S2B2C商城小程序的环境下&#xff0c;如何精准、高效地选择推广商品&#xff0c;成为商家面临的一大挑战。本文首先分析了商品选品的基…

时序论文41 | Medformer:基于多粒度patch的时序分类模型

论文标题&#xff1a;Medformer: A Multi-Granularity Patching Transformer for Medical Time-Series Classification 论文链接&#xff1a;https://arxiv.org/abs/2405.19363 代码链接&#xff1a;https://github.com/DL4mHealth/Medformer. &#xff08;后台回复“交流”…

建筑兔零基础自学python记录32|学过的函数代码记录19-25

这是之前matplotlib用过的代码记录&#xff0c;以防忘记记录一下: 19.price_data 是一个 NumPy 记录股票数组。每一列可以有不同的数据类型&#xff0c;并且每列都有一个对应的字段名。&#xff08;类似excel的表中的列&#xff09; date&#xff1a;存储交易日期&#xff0c…

面试八股文--数据库基础知识总结(2) MySQL

本文介绍关于MySQL的相关面试知识 一、关系型数据库 1、定义 关系型数据库&#xff08;Relational Database&#xff09;是一种基于关系模型的数据库管理系统&#xff08;DBMS&#xff09;&#xff0c;它将数据存储在表格&#xff08;表&#xff09;中&#xff0c;并通过表格…

Linux:目录创建命令mkdir功能及用法详解

mkdir是Make Directory的缩写&#xff0c;该命令在 Linux 中用于创建目录&#xff08;单层或多层&#xff09;&#xff0c;在Linux中很常用&#xff0c;可以说是基础性命令。该命令支持&#xff1a;1&#xff09;创建单层或多层目录2&#xff09;直接指定目录权限。本文详细介绍…

2024年国赛高教杯数学建模D题反潜航空深弹命中概率问题解题全过程文档及程序

2024年国赛高教杯数学建模 D题 反潜航空深弹命中概率问题 原题再现 应用深水炸弹&#xff08;简称深弹&#xff09;反潜&#xff0c;曾是二战时期反潜的重要手段&#xff0c;而随着现代军事技术的发展&#xff0c;鱼雷已成为现代反潜作战的主要武器。但是&#xff0c;在海峡或…