双向链表(C语言版)
1. 双向链表的结构

注意:这里的“带头”跟单链表的“头结点”是两个概念,实际上在单链表阶段称呼不太严谨,但是为了更好地理解就直接称为单链表的头结点。带头链表里的头结点,实际为“哨兵位”,哨兵位结点不存储任何有效元素,只是站在这里“放哨的”。
“哨兵位”存在的意义:
遍历循环链表避免死循环。
2. 双向链表的实现
2.1 双向链表结构体
typedef int LTDataType;
// 定义双向链表节点的结构
typedef struct ListNode
{LTDataType data;struct ListNode* next;struct ListNode* prev;
}LTNode;
2.2 申请结点
// 申请节点
LTNode* LTBuyNode(LTDataType x)
{LTNode* node = (LTNode*)malloc(sizeof(LTNode));if (node == NULL){perror("malloc fail!");exit(1);}node->data = x;node->next = node->prev = node;return node;
}
2.3 初始化
// 初始化
void LTInit(LTNode** pphead)
{// 给链表创建一个哨兵位*pphead = LTBuyNode(-1);
}
2.4 链表的销毁
// 销毁
void LTDestroy(LTNode* phead)
{assert(phead);LTNode* pcur = phead->next;while (pcur != phead){LTNode* next = pcur->next;free(pcur);pcur = next;}// 此时pcur指向phead,而phead还没有被销毁free(phead);phead = NULL;
}
2.5 链表的打印
// 打印
void LTPrint(LTNode* phead)
{LTNode* pcur = phead->next;while (pcur != phead){printf("%d->", pcur->data);pcur = pcur->next;}printf("\n");
}
2.6 链表的尾插
// 尾插
void LTPushBack(LTNode* phead, LTDataType x)
{assert(phead);LTNode* newNode = LTBuyNode(x);// 旧的尾结点就是phead->prev// 先让新的尾结点的前指针指向旧的尾结点newNode->prev = phead->prev;newNode->next = phead; // 再让新的尾结点的下一级指针指向头结点(哨兵位)// 旧的尾结点下一级指针指向新的尾结点phead->prev->next = newNode;phead->prev = newNode; // 再让头结点(哨兵位)的下一级指针指向新的尾结点
}
2.7 链表的头插
// 头插
void LTPushFront(LTNode* phead, LTDataType x)
{assert(phead);LTNode* newNode = LTBuyNode(x);// 要改变的结点:phead newNode phead->nextnewNode->next = phead->next; // 先让新的尾结点的下一级指针指向头结点的下一级指针的结点newNode->prev = phead; // 让新的尾结点的前指针指向头结点//phead->next->prev = newNode; // 指向头结点的下一级指针的结点的下一级指针指向新的结点//phead->next = newNode; // 头结点的下一级指针指向新的结点// 这样也是可行的phead->next = newNode; // 头结点的下一级指针指向新的结点newNode->next->prev = newNode; // 指向头结点的下一级指针的结点的下一级指针指向新的结点}
2.8 链表的尾删
// 尾删
void LTPopBack(LTNode* phead)
{// 链表必须有效且链表不能为空(只有一个哨兵位)assert(phead && phead->next != phead);LTNode* del = phead->prev;// 影响的指针:phead del->prev deldel->prev->next = phead;phead->prev = del->prev;// 删除del节点free(del);del = NULL;
}
2.9 链表的头删
// 头删
void LTPopFront(LTNode* phead)
{// 链表必须有效且链表不能为空(只有一个哨兵位)assert(phead && phead->next != phead);LTNode* del = phead->next;// 影响的指针:phead del del->nextphead->next = del->next;del->next->prev = phead;// 删除del节点free(del);del = NULL;
}
2.10 链表查找数据
// 查找数据
LTNode* LTFind(LTNode* phead, LTDataType x)
{LTNode* pcur = phead->next;while (pcur != phead){if (pcur->data == x){return pcur;}pcur = pcur->next;}// 没有找到return NULL;
}
2.11 在pos位置之后插入数据
// 在 pos 位置之后插入数据
void LTInsert(LTNode* pos, LTDataType x)
{assert(pos);LTNode* newNode = LTBuyNode(x);// 影响的指针:pos newNode pos->nextnewNode->next = pos->next;newNode->prev = pos;pos->next->prev = newNode;pos->next = newNode;
}
2.12 删除pos结点
// 删除 pos节点
void LTErase(LTNode* pos)
{// pos理论上来说不能为phead,但是没有参数phead,无法增加校验assert(pos);// 影响的指针:pos->prev pos pos->nextpos->next->prev = pos->prev;pos->prev->next = pos->next;free(pos);pos = NULL;
}
相关文章:
双向链表(C语言版)
1. 双向链表的结构 注意:这里的“带头”跟单链表的“头结点”是两个概念,实际上在单链表阶段称呼不太严谨,但是为了更好地理解就直接称为单链表的头结点。带头链表里的头结点,实际为“哨兵位”,哨兵位结点不存储任何有…...
【算法/学习】前缀和差分
前缀和&&差分目录 1. 前缀和的概念及作用 🌈概念 🌈用途 🌙一维前缀和 🌙二维前缀和 2. 差分的概念及用途 🌈概念: 🌈用途 🌙一维差分 🌙二维差分 1. …...
idea Project 不显示文件和目录
idea Project 不显示文件和目录 File - Close Project - 重新打开项目即可删除.idea文件夹,重新打开项目即可。 原因分析: 可能与使用不同ide例如java、python打开同一项目有关 参考: https://blog.csdn.net/hgnuxc_1993/article/details/132595900 解决打开IDE…...
Linux--Socket编程预备
目录 1. 理解源 IP 地址和目的 IP 地址 2.端口号 2.1端口号(port)是传输层协议的内容 2.2端口号范围划分 2.3理解 "端口号" 和 "进程 ID" 2.4理解 socket 3.传输层的典型代表 3.1认识 TCP 协议 3.2认识 UDP 协议 4. 网络字节序 5. socket 编程接…...
100个python的基本语法知识【下】
50. 压缩文件: import zipfilewith zipfile.ZipFile("file.zip", "r") as zip_ref:zip_ref.extractall("extracted")51. 数据库操作: import sqlite3conn sqlite3.connect("my_database.db") cursor conn.c…...
Git如何将一个分支上的修改转移到另一个分支
在我们使用git进行版本控制时,当代码写错分支,怎么将这些修改转移到正确的分支上去呢?这时,我们可以使用git stath命令来暂存我们的修改,然后再切换到其他分支 未commit(提交)操作时 1. 先将修…...
jvm-证明cpu指令是乱序执行的案例
package jvm;/*** 证明cpu指令是乱序执行的** author 1* version 1.0* description: TODO* date 2024-07-19 9:31*/ public class T04_Disorder {private static int x 0, y 0;private static int a 0, b 0;public static void main(String[] args) throws InterruptedExcep…...
《流程引擎原理与实践》开源电子书
流程引擎原理与实践 电子书地址:https://workflow-engine-book.shuwoom.com 第一部分:流程引擎基础 1 引言 1.1 流程引擎介绍 1.2 流程引擎技术的发展历程 1.3 相关产品国内外发展现状 1.4 本书的内容和结构安排 2 概念 2.1 基础概念 2.2 进阶…...
谷粒商城实战笔记-52~53-商品服务-API-三级分类-新增-修改
文章目录 一,52-商品服务-API-三级分类-新增-新增效果完成1,点击Append按钮,显示弹窗2,测试完整代码 二,53-商品服务-API-三级分类-修改-修改效果完成1,添加Edit按钮并绑定事件2,修改弹窗确定按…...
uni-app 影视类小程序开发从零到一 | 开源项目分享
引言 在数字娱乐时代,对于电影爱好者而言,随时随地享受精彩影片成为一种日常需求。分享一款基于 uni-app 开发的影视类小程序。它不仅提供了丰富的影视资源推荐,还融入了个性化知乎日报等内容,是不错的素材,同时对电影…...
Python使用正则替换字符串
Python小技:使用正则替换字符串 java中有String.replaceAll()方法使用正则替换字符串, 在Python中,字符串也有一个replace方法,但是这个方法只能精准替换, 如果想正则替换,就要改成re.sub方法,而…...
每日一练,java03
目录 题目wait()、notify()和notifyAll()方法的特性和使用场景wait() 方法notify() 方法notifyAll() 方法使用场景 注意事项 题目 选自牛客网 1.下面关于JAVA的垃圾回收机制,正确的是( ) A.当调用“System.gc()”来强制回收时,系…...
【机器学习】深入理解损失函数(Loss Functions)
🌈个人主页: 鑫宝Code 🔥热门专栏: 闲话杂谈| 炫酷HTML | JavaScript基础 💫个人格言: "如无必要,勿增实体" 文章目录 深入理解损失函数(Loss Functions)什么是损失函数?常见损失函数类型1. 均方误差…...
python实现特征检测算法3
python实现SIFT(尺度不变特征变换)算法、SURF(Speeded Up Robust Features)算法 1.SIFT算法详解算法步骤Python实现详细解释优缺点应用领域2.SURF算法详解算法步骤Python实现详细解释SURF算法原理优缺点应用领域尺度不变特征变换(SIFT,Scale-Invariant Feature Transform…...
软件更新的双刃剑:从”微软蓝屏”事件看网络安全的挑战与对策
引言 原文链接 近日,一场由微软视窗系统软件更新引发的全球性"微软蓝屏"事件震惊了整个科技界。这次事件源于美国电脑安全技术公司"众击"提供的一个带有"缺陷"的软件更新,如同一颗隐形炸弹在全球范围内引爆,…...
Redis 主从搭建
Redis主从搭建 7.2.5 文章目录 一. 同主机搭建Redis主从1. 环境介绍2. 环境前准备工作3. 安装 Redis 7.2.54. redis 配置修改并且启动4.1 修改配置文件4.2 编写启动脚本 5. 开启主从5.1 开启5.2 主库实例查看主从信息5.3 从库实例查看主从信息5.4 验证主从配置是否生效 6. 解除…...
LeetCode 129, 133, 136
文章目录 129. 求根节点到叶节点数字之和题目链接标签思路代码 133. 克隆图题目链接标签思路代码 136. 只出现一次的数字题目链接标签思路代码 129. 求根节点到叶节点数字之和 题目链接 129. 求根节点到叶节点数字之和 标签 树 深度优先搜索 二叉树 思路 由于本题需要 从…...
macOS 环境Qt Creator 快捷键
在 macOS 环境下,Qt Creator 是一个流行的集成开发环境(IDE),用于开发 Qt 项目。下面是一些常用的快捷键和操作技巧,帮助你更高效地使用 Qt Creator 进行项目开发和管理: 在 macOS 中,Cmd 键 四…...
【C# WInForm】将TextBox从输入框设置为文本框
1.需求情形: textbox作为最常用的控件之一,通常是用来输入文本信息或者显示文字,但是如果要在界面中显示大段文本,一个带有边框、可选中的文本样式似乎不合适。像这样: 我需要的是这段文字不仅能跨行,而且…...
minio 服务docker配置
用minio docker配置了一个服务,分享链接始终是127.0.01开始的, 改成docker的host的ip则提示签名不匹配, 好在这个文件主要是用来下载的,所以可以通过设置bucket的匿名访问权限来实现下载; 这样不需要后面的地址参数就…...
基于大模型的 UI 自动化系统
基于大模型的 UI 自动化系统 下面是一个完整的 Python 系统,利用大模型实现智能 UI 自动化,结合计算机视觉和自然语言处理技术,实现"看屏操作"的能力。 系统架构设计 #mermaid-svg-2gn2GRvh5WCP2ktF {font-family:"trebuchet ms",verdana,arial,sans-…...
学校招生小程序源码介绍
基于ThinkPHPFastAdminUniApp开发的学校招生小程序源码,专为学校招生场景量身打造,功能实用且操作便捷。 从技术架构来看,ThinkPHP提供稳定可靠的后台服务,FastAdmin加速开发流程,UniApp则保障小程序在多端有良好的兼…...
Java-41 深入浅出 Spring - 声明式事务的支持 事务配置 XML模式 XML+注解模式
点一下关注吧!!!非常感谢!!持续更新!!! 🚀 AI篇持续更新中!(长期更新) 目前2025年06月05日更新到: AI炼丹日志-28 - Aud…...
【HTTP三个基础问题】
面试官您好!HTTP是超文本传输协议,是互联网上客户端和服务器之间传输超文本数据(比如文字、图片、音频、视频等)的核心协议,当前互联网应用最广泛的版本是HTTP1.1,它基于经典的C/S模型,也就是客…...
AspectJ 在 Android 中的完整使用指南
一、环境配置(Gradle 7.0 适配) 1. 项目级 build.gradle // 注意:沪江插件已停更,推荐官方兼容方案 buildscript {dependencies {classpath org.aspectj:aspectjtools:1.9.9.1 // AspectJ 工具} } 2. 模块级 build.gradle plu…...
用机器学习破解新能源领域的“弃风”难题
音乐发烧友深有体会,玩音乐的本质就是玩电网。火电声音偏暖,水电偏冷,风电偏空旷。至于太阳能发的电,则略显朦胧和单薄。 不知你是否有感觉,近两年家里的音响声音越来越冷,听起来越来越单薄? —…...
springboot整合VUE之在线教育管理系统简介
可以学习到的技能 学会常用技术栈的使用 独立开发项目 学会前端的开发流程 学会后端的开发流程 学会数据库的设计 学会前后端接口调用方式 学会多模块之间的关联 学会数据的处理 适用人群 在校学生,小白用户,想学习知识的 有点基础,想要通过项…...
脑机新手指南(七):OpenBCI_GUI:从环境搭建到数据可视化(上)
一、OpenBCI_GUI 项目概述 (一)项目背景与目标 OpenBCI 是一个开源的脑电信号采集硬件平台,其配套的 OpenBCI_GUI 则是专为该硬件设计的图形化界面工具。对于研究人员、开发者和学生而言,首次接触 OpenBCI 设备时,往…...
通过 Ansible 在 Windows 2022 上安装 IIS Web 服务器
拓扑结构 这是一个用于通过 Ansible 部署 IIS Web 服务器的实验室拓扑。 前提条件: 在被管理的节点上安装WinRm 准备一张自签名的证书 开放防火墙入站tcp 5985 5986端口 准备自签名证书 PS C:\Users\azureuser> $cert New-SelfSignedCertificate -DnsName &…...
Vue 模板语句的数据来源
🧩 Vue 模板语句的数据来源:全方位解析 Vue 模板(<template> 部分)中的表达式、指令绑定(如 v-bind, v-on)和插值({{ }})都在一个特定的作用域内求值。这个作用域由当前 组件…...
