【双向链表的实现】

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档

目录

前言

1. 双向链表的结构

2. 双向链表的实现

2.1 头文件 ——双向链表的创建及功能函数的定义

2.2 源文件 ——双向链表的功能函数的实现

2.3 源文件 ——双向链表功能的测试

4.双向链表的操作示意图

3.顺序表和双向链表的优缺点分析

总结


前言

世上有两种耀眼的光芒,一种是正在升起的太阳,一种是正在努力学习编程的你!一个爱学编程的人。各位看官,我衷心的希望这篇博客能对你们有所帮助,同时也希望各位看官能对我的文章给与点评,希望我们能够携手共同促进进步,在编程的道路上越走越远!


提示:以下是本篇文章正文内容,下面案例可供参考

1. 双向链表的结构

注意:这里的“带头”跟前面我们说的“头节点”是两个概念,实际前面的在单链表阶段称呼不严 谨,但是为了同学们更好的理解就直接称为单链表的头节点。

带头链表里的头节点,实际为“哨兵位”,哨兵位节点不存储任何有效元素,只是站在这里“放哨的”

“哨兵位”存在的意义: 遍历循环链表避免死循环。

2. 双向链表的实现

2.1 头文件 ——双向链表的创建及功能函数的定义

List.h

#pragma once
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <stdbool.h>//定义双向链表的节点的结构
typedef int STDataType;typedef struct ListNode
{STDataType data;struct ListNode* next;//保存下一个节点的地址struct ListNode* prev;//保存前一个节点的地址
}LTNode;//链表的初始化
//void LTInit(LTNode** pphead);//前提:我们要传入一个头节点//我们更倾向于第二种初始化的方法
//因为双向链表为空(只有一个哨兵位:哨兵位节点是不能被操作的,即不能被改变)
LTNode* LTInit();//不需要传入参数,调用该方法之后给我们返回一个头节点//在双向链表中不会改变哨兵位,所以可以传一级指针
//尾插入操作
void LTPushBack(LTNode* phead, STDataType x);//头插
void LTPushFront(LTNode* phead, STDataType x);//链表的打印
void LTPrint(LTNode* phead);//尾删
void LTPopBack(LTNode* phead);
//头删
void LTPopFront(LTNode* phead);//在pos位置之后插入的数据
void LTInsert(LTNode* pos, STDataType x);
//删除pos位置的节点
void LTErase(LTNode* pos);
LTNode* LTFind(LTNode* phead, STDataType x);//链表的销毁
void LTDestroy(LTNode* phead);

2.2 源文件 ——双向链表的功能函数的实现

List.c

#define _CRT_SECURE_NO_WARNINGS 1
#include "List.h"//链表的初始化
//前提:我们要传入一个头节点
//void LTInit(LTNode** pphead)
//{
//	*pphead = (LTNode*)malloc(sizeof(LTNode));
//	if (*pphead == NULL)
//	{
//		perror("malloc");
//		return;
//	}
//	//节点有三部分内容:数据 前驱指针 后继指针
//	(*pphead)->data = -1;//哨兵位
//	(*pphead)->next = (*pphead)->prev = *pphead;
//}//链表初始化
//不需要传入参数,调用该方法之后给我们返回一个头节点
LTNode* LTInit()
{LTNode* phead = (LTNode*)malloc(sizeof(LTNode));if (phead == NULL){perror("malloc");return;}phead->data = -1;phead->next = phead->prev = phead;return phead;
}//申请一个新的节点
LTNode* ListBuyNode(STDataType x)
{LTNode* node = (LTNode*)malloc(sizeof(LTNode));node->data = x;node->next = node->prev = NULL;return node;
}//链表的打印
void LTPrint(LTNode* phead)
{LTNode* cur = phead->next;while (cur != phead){printf("%d->", cur->data);cur = cur->next;}printf("\n");
}//尾插入操作
void LTPushBack(LTNode* phead, STDataType x)
{assert(phead);LTNode* node = ListBuyNode(x);//先处理新节点node的前驱和后继指针node->prev = phead->prev;node->next = phead;//在处理phead->prev(之前的尾节点)和pheadphead->prev->next = node;phead->prev = node;
}//头插
void LTPushFront(LTNode* phead, STDataType x)
{assert(phead);LTNode* node = ListBuyNode(x);//node的节点 next prevnode->prev = phead;node->next = phead->next;//处理phead phead->nextphead->next->prev = node;phead->next = node;
}//尾删
void LTPopBack(LTNode* phead)
{assert(phead);//链表不能为空链表:链表中只有一个哨兵位节点assert(phead->next != phead);LTNode* del = phead->prev;//先处理del->prev节点del->prev->next = phead;//处理pheadphead->prev = del->prev;free(del);del = NULL;
}
//头删
void LTPopFront(LTNode* phead)
{assert(phead&& phead->next != phead);LTNode* del = phead->next;//phead del->nextdel->next->prev = phead;phead->next = del->next;free(del);del = NULL;
}//在pos位置之后插入的数据
void LTInsert(LTNode* pos, STDataType x)
{assert(pos);LTNode* node = ListBuyNode(x);//node的prev 和 nextnode->next = pos->next;node->prev = pos;//pos的next 和 pos->next的prevpos->next = node;node->next->prev = node;
}
//删除pos位置的节点
void LTErase(LTNode* pos)
{assert(pos);//pos->prev:next pos pos->next:prevpos->next->prev = pos->prev;pos->prev->next = pos->next;free(pos);pos = NULL;
}
//查找数据
LTNode* LTFind(LTNode* phead, STDataType x)
{assert(phead);LTNode* cur = phead->next;while (cur != phead){if (cur->data == x){return cur;}cur = cur->next;}return NULL;
}//链表的销毁
void LTDestroy(LTNode* phead)
{assert(phead);LTNode* cur = phead->next;while (cur != phead){LTNode* next = cur->next;free(cur);cur = next;}//除了循环之后,还有哨兵位没有被释放free(phead);phead = NULL;//我们将phead指向的空间释放掉,plist实参的空间也被释放掉了,phead置为空//但是此时plist实参为野指针,还需要我们手动置为空
}

2.3 源文件 ——双向链表功能的测试

test.c

#define _CRT_SECURE_NO_WARNINGS 1#include "List.h"void ListTest()
{//第一种初始化方法:/*LTNode* plist = NULL;LTInit(&plist);*///第二种初始化方法;LTNode* plist = LTInit();//尾插LTPushBack(plist, 1);LTPushBack(plist, 2);LTPushBack(plist, 3);LTPushBack(plist, 4);//打印LTPrint(plist);头插//LTPushFront(plist, 5);//LTPushFront(plist, 6);//LTPushFront(plist, 7);//LTPrint(plist);//尾删//LTPopBack(plist);//头删/*LTPopFront(plist);LTPopFront(plist);*///测试指定位置之后插入//LTNode* find = LTFind(plist, 1);//LTInsert(find, 11);/*LTErase(find);LTPrint(plist);*///销毁链表LTDestroy(plist);//传一级指针的要手动将plist置为空plist = NULL;
}
int main()
{ListTest();return 0;
}

4.双向链表的操作示意图

3.顺序表和双向链表的优缺点分析


总结

好了,本篇博客到这里就结束了,如果有更好的观点,请及时留言,我会认真观看并学习。
不积硅步,无以至千里;不积小流,无以成江海。

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

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

相关文章

Jmeter测试移动接口性能 —— 压测

一般的公司都想知道自己产品的性能瓶颈和以及提升性能&#xff0c;以期大流量来了还撑得住。其实性能测试很难&#xff0c;难点在你不知道性能要达到怎样的需求。难点在于你没有实际的环境场景给你测试&#xff0c;总不能给线上环境你测试吧&#xff1f; 难点在于找性能瓶颈&a…

kafka C++实现消费者

文章目录 1 Kafka 消费者的逻辑2 Kafka 的C API2.1 RdKafka::Conf2.2 RdKafka::Event2.3 RdKafka::EventCb2.4 RdKafka::TopicPartition2.5 RdKafka::RebalanceCb2.6 RdKafka::Message2.7 RdKafka::KafkaConsumer&#xff08;核心&#xff09; 3 Kafka 消费者客户端开发3.1 必要…

Linux操作系统虚拟机安装(图文详解)

目录 前言 Linux系统介绍 虚拟机安装 1.安装步骤 2.破解激活步骤 3.创建Linux系统虚拟机 虚拟机的相关设置 1.基础设置 2.语言设置为中文 前言 今天我们开始学习Linux操作系统的安装虚拟机以及相关的Linux的环境配置&#xff0c;后面我还会继续发布Linux系统的相关基…

手机电脑同步的时间管理工具

有不少上班族会发现自己有太多的工作要完成&#xff0c;并且在工作中往往会浪费很多时间在无关紧要的事情上&#xff0c;而不是专注于真正重要的任务&#xff0c;因此没有足够的时间来完成所有任务。在这种情况下&#xff0c;我们可以使用时间管理软件来帮助自己优先考虑重要的…

IIS post .html页面报 405错误

IIS是不允许本地文件默认post请求的&#xff0c;windows10系统下的IIS&#xff08;10.0版&#xff09;默认也是不能 post请求\*.html或\*.json文件的 1 需要配置一下&#xff0c;配置如下&#xff1a; 2 双击处理程序映射&#xff0c;添加托管处理程序&#xff1a; 3 请求路径 …

es6 语法 解构 拼接 扩展运算 数组降为 symbol 迭代器 生成器 定时器 map 映射 对象字面量 私有属性 构造函数继承

es6 语法 解构 拼接 扩展运算 数组降为 symbol 迭代器 生成器 定时器 map 映射 对象字面量 私有属性 构造函数继承 promise async await 解构 // 解构var character {name:Brucezzz,pseudonym:Bruce,metadata:{age:32,gender:male,airbags: "说两句啊",airconditio…

springboot+jsp+java人才招聘网站4f21r

本基于springboot的人才招聘网站主要满足3种类型用户的需求&#xff0c;这3种类型用户分别为求职者、企业和管理员&#xff0c;他们分别实现的功能如下。 &#xff08;1&#xff09;求职者进入网站后可查看职位信息、企业信息以及职位新闻等&#xff0c;注册登录后可实现申请职…

在MySQL中如何存储一个IPv4地址?

在MySQL如何存储IPv4地址&#xff1f;这个在秋招面试的过程中被问到过&#xff0c;没有答上来&#xff0c;今天猛地想起了这个问题&#xff0c;做一下复盘。 一个IPv4地址是由32位二进制来表示的&#xff0c;用点分十进制表示可以划分为4部分&#xff0c;每部分占8位&#xff…

云时空社会化商业 ERP 系统 service SQL 注入漏洞复现

0x01 产品简介 时空云社会化商业ERP&#xff08;简称时空云ERP&#xff09; &#xff0c;该产品采用JAVA语言和Oracle数据库&#xff0c; 融合用友软件的先进管理理念&#xff0c;汇集各医药企业特色管理需求&#xff0c;通过规范各个流通环节从而提高企业竞争力、降低人员成本…

『PyTorch学习笔记』分布式深度学习训练中的数据并行(DP/DDP) VS 模型并行

分布式深度学习训练中的数据并行(DP/DDP) VS 模型并行 文章目录 一. 介绍二. 并行数据加载2.1. 加载数据步骤2.2. PyTorch 1.0 中的数据加载器(Dataloader) 二. 数据并行2.1. DP(DataParallel)的基本原理2.1.1. 从流程上理解2.1.2. 从模式角度理解2.1.3. 从操作系统角度看2.1.…

11-22 SSM3

书城分页查询 使用mybatis分页插件&#xff1a; 请完成登陆注册 -> 跳转到首页 解决前端上架时间点击切换 以及侧边栏点击由背景颜色的改变 完成超链接的绑定点击时间 -> jquery $(document).ready(function() { // 初始化上架时间状态为 true&#xff08;上架&…

简明指南:使用Kotlin和Fuel库构建JD.com爬虫

概述 爬虫&#xff0c;作为一种自动化从网络上抓取数据的程序&#xff0c;广泛应用于数据分析、信息提取以及竞争对手监控等领域。不同的实现方式和编程语言都能构建出高效的爬虫工具。在本文中&#xff0c;我们将深入介绍如何充分利用Kotlin和Fuel库&#xff0c;构建一个简单…

道路病害检测数据集RDD2022的标签映射关系【参考自官网给出的label_map.pbtxt文件,附查看代码】

TOC 结论 Label ID: 1, Label Name: D00 Label ID: 2, Label Name: D10 Label ID: 3, Label Name: D20 Label ID: 4, Label Name: D40链接地址 https://github.com/sekilab/RoadDamageDetector/ 查看代码 # 打开 label_map.pbtxt 文件 def read_label_map(file_path):label…

【稳定检索|投稿优惠】2024年经济管理与安全科学国际学术会议(EMSSIC 2024)

2024年经济管理与安全科学国际学术会议(EMSSIC 2024) 2024 International Conference on Economic Management and Security Sciences(EMSSIC 2024) 一、【会议简介】 2024年经济管理与安全科学国际学术会议(EMSSIC 2024)&#xff0c;将于繁华的上海城召开。这次会议的主题是“…

C++17那些事开篇之类模版参数推导(CTAD)

C17那些事开篇之类模版参数推导(CTAD) 引入 大家好&#xff0c;我是光城&#xff0c;今天开始正式开篇C17的新特性了&#xff0c;期待不&#xff0c;欢迎留言区说出想要更新的特性呀&#xff5e; C模板元编程一直是C开发者们熟知的一项功能&#xff0c;无论是初学者还是高级开发…

【猜数字游戏】用wxPython实现:基本的游戏框架 + 简单的图形用户界面

【猜数字游戏】 写在最前面猜数字游戏 实现【猜数字游戏】安装wxPython全部代码代码解析1. 初始化界面2. 生成随机数3. 处理猜测4. 特殊功能5. 分数计算 游戏小程序呈现结语 写在最前面 看到了一个比较有意思的问题 https://ask.csdn.net/questions/8038039 猜数字游戏 在这…

苹果TF签名全称TestFlight签名,需要怎么做才可以上架呢?

如果你正在开发一个iOS应用并准备进行内测&#xff0c;TestFlight是苹果提供的一个免费的解决方案&#xff0c;它使开发者可以邀请用户参加应用的测试。以下是一步步的指南&#xff0c;教你如何利用TestFlight进行内测以便于应用后续可以顺利上架App Store。 1: 准备工作 在测…

客餐书房一体布局,新中式风格禅意十足。福州中宅装饰,福州装修

你是否曾经遇到过这样的痛点&#xff1a;装修时不知道该选择什么样的风格&#xff0c;让家居空间显得既时尚又实用&#xff1f;如果你对此感到困惑&#xff0c;那么新中式风格可能正是你想要的选择&#xff01; 今天&#xff0c;我们将一起探讨一种别样的家居布局&#xff0c;它…

如何用量化交易“做空”来获取收益

最近的市场环境相当不好&#xff0c;今年一年都没有任何主线的模式情况下去交易。更多的都是题材热点聚焦&#xff0c;而且板块轮动过快。市场环境不好的情况下&#xff0c;我们如何通过“做空”来获取收益&#xff01;量化做空是指利用计算机模型和算法&#xff0c;通过分析市…

EasyExcel如何读取全部Sheet页数据方法

一、需求描述 Excel表格里面大约有20个sheet页&#xff0c;每个sheet页65535条数据&#xff0c;需要读取全部数据&#xff0c;并导入至数据库。 找了好多种方式&#xff0c;EasyExcel比较符合&#xff0c;下面看代码。 二、实现方式 采用EasyExcel框架的doReadAll()方法 1、…