双向链表的实现(详解)
目录
- 前言
- 初始化
- 双向链表的结构
- 为双向链表的节点开辟空间
- 头插
- 尾插
- 打印链表
- 尾删
- 头删
- 查找
- 指定位置之后的插入
- 删除pos节点
- 销毁双向链表
前言
链表的分类: 带头 不带头 单向 双向 循环 不循环
一共有 (2 * 2 * 2) 种链表
带头指的是:带有哨兵位节点
哨兵位(头结点):可以放随机数据,哨兵位指向的下一个节点就是我们的第一个有效节点,我们指的头节点是哨兵位

单向:指针只能从前向后遍历
双向:指针既可以从前向后遍历又可以从后向前遍历
循环:可以通过尾节点找到头节点,从而达到循环

主要使用的链表是单链表和双向链表
单链表:不带头单向不循环
双向链表:带头双向循环
初始化
ListNode* TLInit()
{ListNode* phead = ListByNode(-1);//ListByNode后面会介绍//为头节点开辟一个空间,并将头结点指向的值赋值为-1return phead;//将开辟出的头节点返回我们的主函数,主函数中的头节点就知道我们有一个哨兵位了
}
//初始化
void TLInit(ListNode** pphead)
{//给双向链表创建一个哨兵位*pphead = ListByNode(-1);
}
初始化有两种写法,第二种写法也是可行的,但是用第一种,可以使得接口一致,都是一级指针,使用者也会更方便的使用,不用去记忆那个要用一级指针还是二级指针
双向链表的结构
//定义双向链表的结构
typedef int DataType;
typedef struct ListNode//双向链表
{DataType x;//双向链表中的数据struct ListNode* next;//指向后一个节点,后继指针struct ListNode* prev;//指向前一个节点,前驱指针
}ListNode;
为双向链表的节点开辟空间
ListNode* ListByNode(DataType x)
{ListNode* node = (ListNode*)malloc(sizeof(ListNode));if (node == NULL){perror("malloc");return NULL;}//开辟成功node->next = node->prev = node;//初始化一个哨兵位的下一个节点和前一个节点指向的是自己node->x = x;return node;
}
头插
//头插
//在第一个有效节点之前插入一个节点
void TLPushFront(ListNode* phead,DataType x)
//用一级指针为了不改变原链表的哨兵位
{assert(phead);//断言一下是不是空链表ListNode* newnode = ListByNode(x);ListNode* pcur = phead->next;newnode->next = pcur;newnode->prev = phead;pcur->prev = newnode;phead->next = newnode;}

尾插
//尾插
//在头节点之后或者之前插入
//因为在哨兵位前,哨兵位的prev指向尾结点,尾结点的next指向哨兵位
void TLPushBack(ListNode* phead,DataType x)
{assert(phead);//链表不为空ListNode* newnode = ListByNode(x);//为尾插的节点开辟空间ListNode* pcur = phead->prev; newnode->next = phead;newnode->prev = pcur;pcur->next = newnode;phead->prev = newnode;
}

打印链表
//打印链表
void TLPrint(ListNode* phead)
{ListNode* pcur = phead->next;while (pcur != phead){printf("%d->", pcur->x);pcur = pcur->next;}printf("\n");
}
尾删
//尾删
//注意哨兵位不能被删除,所以理论上至少有一个节点,才能够删除
void TLPopBack(ListNode* phead)
{assert(phead&&phead->next!=phead);ListNode* pcur = phead->prev;ListNode* del = pcur->prev;del->next = phead;phead->prev = del;free(pcur);pcur = NULL;}

头删
//头删
//注意哨兵位不能被删除,所以理论上至少有一个节点,才能够删除
void TLPopFront(ListNode* phead)
{assert(phead&&phead->next!=phead);//phead不能为空ListNode* pcur = phead->next;pcur->next->prev = phead;phead->next = pcur->next;free(pcur);pcur = NULL;}

查找
//查找 x 数据的位置并返回
ListNode* SLFind(DataType x,ListNode* phead)
{ListNode* pcur = phead->next;while (pcur != phead){if (pcur->x == x){return pcur;//找到了}pcur = pcur->next;}return NULL;//找不到了
}
指定位置之后的插入
//指定位置之后的插入
//知道了pos节点,就知道了pos之前的数和之后的数
//指定位置之后的插入和指定位置之前的插入是一样的
void TLInsert(ListNode* pos,DataType x)
{assert(pos);//插入的pos位置不能为空ListNode* newnode = ListByNode(x);//为插入的数据开辟空间ListNode* pcur = pos->next;newnode->next = pcur;newnode->prev = pos;pos->next = newnode;pcur->prev = newnode;}

删除pos节点
//删除pos节点
void Erase(ListNode* pos)
{assert(pos);//理论上pos不能为phead,因为phead不能被删除,它是双向链表pos->prev->next = pos->next;pos->next->prev = pos->prev;free(pos);pos = NULL;}

销毁双向链表
//销毁双向链表
void LTDestroy(ListNode* phead)
{assert(phead);//phead不为空,才销毁,为空,不用销毁//销毁时phead也要释放(销毁)ListNode* pcur = phead->next;ListNode* next = pcur->next;while (pcur != phead){next = pcur->next;free(pcur);pcur = next;}//出来后pcur指向pheadfree(phead);phead = NULL;
}
相关文章:
双向链表的实现(详解)
目录 前言初始化双向链表的结构为双向链表的节点开辟空间头插尾插打印链表尾删头删查找指定位置之后的插入删除pos节点销毁双向链表 前言 链表的分类: 带头 不带头 单向 双向 循环 不循环 一共有 (2 * 2 * 2) 种链表 带头指的是:带有哨兵位节点 哨兵位&a…...
SpringBoot项目中如何使用校验工具
用到hutool提供的校验方法与java提供的校验方法 1. 声明数据 String str "123" String regex "^123456$" Boolean is1_6 mismatch(str, regex);2. 定义校验方法 // 校验是否不符合正则格式 private static boolean mismatch(String str, String rege…...
AI预测小分子与蛋白的相关特征: MegaMolBART, MoFlow,ESM-1, ESM-2
1、小分子:MegaMolBART, MoFlow 1)MegaMolBART https://github.com/NVIDIA/MegaMolBART 基于 SMILES 的小分子药物发现与化学信息学深度学习模型。 2)MoFlow https://github.com/calvin-zcx/moflow 用flow流方式分子生成 2、蛋白质:ESM-1, ESM-2 https://github.com/fa…...
基于深度学习的花卉检测系统(含PyQt界面)
基于深度学习的花卉检测系统(含PyQt界面) 前言一、数据集1.1 数据集介绍1.2 数据预处理 二、模型搭建三、训练与测试3.1 模型训练3.2 模型测试 四、PyQt界面实现参考资料 前言 本项目是基于swin_transformer深度学习网络模型的花卉检测系统,…...
深度学习图像处理基础工具——opencv 实战信用卡数字识别
任务 信用卡数字识别 穿插之前学的知识点 形态学操作 模板匹配 等 总体流程与方法 1.有一个模板 2 用轮廓检测把模板中数字拿出来 外接矩形(模板和输入图像的大小要一致 )3 一系列预处理操作 问题的解决思路 1.分析准备:准备模板&#…...
【HBase】HBase高性能架构:如何保证大规模数据的高可用性
HBase高性能原理 HBase 能够提供高性能的数据处理能力,主要得益于其设计和架构的几个关键方面。这些设计特点使得 HBase 特别适合于大规模、分布式的环境中进行高效的数据读写操作。以下是 HBase 高性能的主要原因: 1. 基于列的存储 HBase 是一个列式…...
JAVA基础两个项目案例代码
1.JAVA使用ArrayList上架菜品案例 视频参考链接 创建一个Food.java类 package org.example;// 菜品类 public class Food {private String name; // 菜品名private double price; // 价格private String desc; // 菜品描述public Food() {}public Food(String name, Double …...
asp.net core 网页接入微信扫码登录
创建微信开放平台账号,然后创建网页应用 获取appid和appsecret 前端使用的vue,安装插件vue-wxlogin 调用代码 <wxlogin :appid"appId" :scope"scope" :redirect_uri"redirect_uri"></wxlogin> <scri…...
【板栗糖GIS】如何给微软拼音输入法加上小鹤双拼
【板栗糖GIS】如何给微软拼音输入法加上小鹤双拼 用过在注册表里新建的方法,结果弄完没有出现小鹤双拼方案,想到了自己写reg表 目录 1. 新建一个txt文件 2. 把.txt的后缀名改成.reg,双击运行 3. 在设置中找到微软输入法-常规 1. 新建一个…...
如何解决微信小程序无法使用css3过度属性transition
由于微信小程序不支持CSS3过度属性transition,所以我们需要利用微信小程序api进行画面过度的展示 首先是官方示例: wxml: <view animation="{{animationData}}" style="background:red;height:100rpx;width:100rpx"></view> js: Page(…...
【软件设计师知识点】九、网络与信息安全基础知识
文章目录 计算机网络的概念网络分类网络拓扑结构网络体系结构ISO/OSI 7层参考模型TCP/IP 4层模型TCP/IP 协议族应用层协议传输层协议网络层协议IP 地址IPV4 数据报IP 地址分类子网划分子网掩码IPv6地址...
广东省道路货物运输资格证照片回执可手机线上办理
广东省道路运输资格证是从事道路运输业务、危险品道路运输人员的必要证件,而在办理该证件的过程中,驾驶员照片回执是一项必不可少的材料。随着科技的发展和移动互联网的普及,现在办理驾驶员照片回执已经不再需要亲自前往照相馆,而…...
【微信小程序——案例——本地生活(列表页面)】
案例——本地生活(列表页面) 九宫格中实现导航跳转——以汽车服务为案例(之后可以全部实现页面跳转——现在先实现一个) 在app.json中添加新页面 修改之前的九宫格view改为navitage 效果图: 动态设置标题内容—…...
【设计模式】SOLID设计原则
1、什么是SOLID设计原则 SOLID 是面向对象设计中的五个基本设计原则的首字母缩写,它们是: 单一职责原则(Single Responsibility Principle,SRP): 类应该只有一个单一的职责,即一个类应该有且只…...
基于java+springboot+vue实现的智能停车计费系统(文末源码+Lw+ppt)23-30
摘 要 随着人们生活水平的高速发展,智能停车计费信息管理方面在近年来呈直线上升,人们也了解到智能停车计费的实用性,因此智能停车计费的管理也逐年递增,智能停车计费信息的增加加大了在管理上的工作难度。为了能更好的维护智能…...
IntelliJ IDEA 2022.3.2 解决decompiled.class file bytecode version:52.0(java 8)
1 背景 使用idea 打开一个Kotlin语言编写的demo项目,该项目使用gradle构建。其gradle文件如下: plugins {id javaid org.jetbrains.kotlin.jvm version 1.8.20 } group me.administrator version 1.0-SNAPSHOTrepositories {mavenCentral()jcenter()…...
C++11 设计模式1. 模板方法(Template Method)模式学习。UML图
一 什么是 "模板方法(Template Method)模式" 在固定步骤确定的情况下,通过多态机制在多个子类中对每个步骤的细节进行差异化实现,这就是模板方法模式能够达到的效果。 模板方法模式属于:行为型模式。 二 &…...
HarmonyOS实战开发-自定义分享
介绍 自定义分享主要是发送方将文本,链接,图片三种类型分享给三方应用,同时能够在三方应用中展示。本示例使用数据请求 实现网络资源的获取,使用屏幕截屏 实现屏幕的截取,使用文件管理 实现对文件,文件目录的管理&…...
Spring源码刨析之配置文件的解析和bean的创建以及生命周期
public void test1(){XmlBeanFactory xmlBeanFactory new XmlBeanFactory(new ClassPathResource("applicationContext.xml"));user u xmlBeanFactory.getBean("user",org.xhpcd.user.class);// System.out.println(u.getStu());}先介绍一个类XmlBeanFac…...
如何使用 Grafana 监控文件系统状态
当 JuiceFS 文件系统部署完成并投入生产环境,接下来就需要着手解决一个非常重要的问题 —— 如何实时监控它的运行状态?毕竟,它可能正在为关键的业务应用或容器工作负载提供持久化存储支持,任何小小的故障或性能下降都可能造成不利…...
浏览器访问 AWS ECS 上部署的 Docker 容器(监听 80 端口)
✅ 一、ECS 服务配置 Dockerfile 确保监听 80 端口 EXPOSE 80 CMD ["nginx", "-g", "daemon off;"]或 EXPOSE 80 CMD ["python3", "-m", "http.server", "80"]任务定义(Task Definition&…...
国防科技大学计算机基础课程笔记02信息编码
1.机内码和国标码 国标码就是我们非常熟悉的这个GB2312,但是因为都是16进制,因此这个了16进制的数据既可以翻译成为这个机器码,也可以翻译成为这个国标码,所以这个时候很容易会出现这个歧义的情况; 因此,我们的这个国…...
Spring Boot 实现流式响应(兼容 2.7.x)
在实际开发中,我们可能会遇到一些流式数据处理的场景,比如接收来自上游接口的 Server-Sent Events(SSE) 或 流式 JSON 内容,并将其原样中转给前端页面或客户端。这种情况下,传统的 RestTemplate 缓存机制会…...
【服务器压力测试】本地PC电脑作为服务器运行时出现卡顿和资源紧张(Windows/Linux)
要让本地PC电脑作为服务器运行时出现卡顿和资源紧张的情况,可以通过以下几种方式模拟或触发: 1. 增加CPU负载 运行大量计算密集型任务,例如: 使用多线程循环执行复杂计算(如数学运算、加密解密等)。运行图…...
AI编程--插件对比分析:CodeRider、GitHub Copilot及其他
AI编程插件对比分析:CodeRider、GitHub Copilot及其他 随着人工智能技术的快速发展,AI编程插件已成为提升开发者生产力的重要工具。CodeRider和GitHub Copilot作为市场上的领先者,分别以其独特的特性和生态系统吸引了大量开发者。本文将从功…...
NLP学习路线图(二十三):长短期记忆网络(LSTM)
在自然语言处理(NLP)领域,我们时刻面临着处理序列数据的核心挑战。无论是理解句子的结构、分析文本的情感,还是实现语言的翻译,都需要模型能够捕捉词语之间依时序产生的复杂依赖关系。传统的神经网络结构在处理这种序列依赖时显得力不从心,而循环神经网络(RNN) 曾被视为…...
使用Spring AI和MCP协议构建图片搜索服务
目录 使用Spring AI和MCP协议构建图片搜索服务 引言 技术栈概览 项目架构设计 架构图 服务端开发 1. 创建Spring Boot项目 2. 实现图片搜索工具 3. 配置传输模式 Stdio模式(本地调用) SSE模式(远程调用) 4. 注册工具提…...
CSS | transition 和 transform的用处和区别
省流总结: transform用于变换/变形,transition是动画控制器 transform 用来对元素进行变形,常见的操作如下,它是立即生效的样式变形属性。 旋转 rotate(角度deg)、平移 translateX(像素px)、缩放 scale(倍数)、倾斜 skewX(角度…...
c# 局部函数 定义、功能与示例
C# 局部函数:定义、功能与示例 1. 定义与功能 局部函数(Local Function)是嵌套在另一个方法内部的私有方法,仅在包含它的方法内可见。 • 作用:封装仅用于当前方法的逻辑,避免污染类作用域,提升…...
前端调试HTTP状态码
1xx(信息类状态码) 这类状态码表示临时响应,需要客户端继续处理请求。 100 Continue 服务器已收到请求的初始部分,客户端应继续发送剩余部分。 2xx(成功类状态码) 表示请求已成功被服务器接收、理解并处…...
