当前位置: 首页 > news >正文

【数据结构】双向链表专题

目录

1.双向链表的结构

2.双向链表的实现

2.1初始化

以参数的形式初始化链表: 

以返回值的形式初始化链表:

2.2尾插

2.3打印

2.4头插

2.5尾删

2.6头删

2.7查找

2.8在指定位置之后插入数据​编辑

2.9删除pos节点

2.10销毁

3.整理代码

3.1 List.h

3.2 List.c

3.3 Test.c


1.双向链表的结构

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

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

2.双向链表的实现

不带头节点的单链表为空链表的判条件:head=NULL,因为head本来指向链表的第一个节点,如果head为NULL,说明链表没有节点,为空链表。

而带头结点的单链表为空链表的判定条件:head->next=NULL;

双向链表为空链表的判定条件:链表中只剩下一个头结点

2.1初始化

申请节点函数

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;
}

以参数的形式初始化链表: 

开始的时候创建一个空链表,LTNode* plist = NULL;我们要对空链表进行初始化,保证让链表只有一个头结点(哨兵位),为我们后续插入操作做准备。由于要改变plist的指向,所以传二级指针。

void LTInit(LTNode** pphead)
{//给双向链表创建一个哨兵位*pphead = LTBuyNode(-1);//哨兵位里面不需要有值,为了调用申请节点函数,传一个值-1好了
}

以返回值的形式初始化链表:

初始化可以不传递二级指针,以返回值的形式返回哨兵位,调用完LTInit函数后,plist指针接收其返回值:LTNode* plist = LTInit();

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

2.2尾插

void LTPushBack(LTNode* phead, LTDataType x)//不改变哨兵位的地址,传一级指针即可
{assert(phead);LTNode* newnode = LTBuyNode(x);//phead phead->prev newnodenewnode->prev = phead->prev;newnode->next = phead;phead->prev->next = newnode;phead->prev = newnode;//注意:这两行代码不能颠倒位置
}

2.3打印

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

2.4头插

void LTPushFront(LTNode* phead, LTDataType x)
{assert(phead);LTNode* newnode = LTBuyNode(x);//phead newnode phead->nextnewnode->next = phead->next;newnode->prev = phead;newnode->next->prev = newnode;phead->next = newnode;//注意:这两行代码不能颠倒位置
}

2.5尾删

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.6头删

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.7查找

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.8在指定位置之后插入数据

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.9删除pos节点

为了保持接口的一致性,这里传的是一级指针,对形参的修改不影响实参,pos置为空不影响find , find此时是野指针,所以调用完 LTERase 函数后要手动将find置为空(find=NULL;)

void LTErase(LTNode* pos)
{assert(pos);// pos->prev pos pos->nextpos->next->prev = pos->prev;pos->prev->next = pos->next;//删除pos节点free(pos);pos = NULL;
}

2.10销毁

同样为了保持接口的一致性,这里也传一级指针,对形参的修改不影响实参,phead置为空不影响实参plist,所以调用完 LTDesTroy 函数后要手动将plist置为空(plist=NULL;)

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;
}

3.整理代码

3.1 List.h

#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>//定义双向链表节点的结构
typedef int LTDataType;
typedef struct ListNode
{LTDataType data;struct ListNode* next;struct ListNode* prev;
}LTNode;//初始化
//void LTInit(LTNode** pphead);//以二级指针形式初始化
LTNode* LTInit();//以返回值形式初始化
//打印
void LTPrint(LTNode* phead);
//尾插
void LTPushBack(LTNode* phead,LTDataType x);
//头插
void LTPushFront(LTNode* phead, LTDataType x);
//尾删
void LTPopBack(LTNode* phead);
//头删
void LTPopFront(LTNode* phead);
//查找
LTNode* LTFind(LTNode* phead, LTDataType x);
//在pos位置之后插⼊数据
void LTInsert(LTNode* pos, LTDataType x);
//删除pos节点
void LTErase(LTNode* pos);
//销毁
void LTDesTroy(LTNode* phead);

3.2 List.c

#include"List.h"
//申请节点
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;
}//初始化
//以返回值形式初始化
LTNode* LTInit()
{LTNode* phead = LTBuyNode(-1);return phead;
}//以二级指针形式初始化
//void LTInit(LTNode** pphead)
//{
//	*pphead = LTBuyNode(-1);
//}//打印
void LTPrint(LTNode* phead)
{LTNode* pcur = phead->next;while (pcur != phead){printf("%d->", pcur->data);pcur = pcur->next;}printf("\n");
}//尾插
void LTPushBack(LTNode* phead, LTDataType x)//不改变哨兵位的地址,传一级指针即可
{assert(phead);LTNode* newnode = LTBuyNode(x);//phead phead->prev newnodenewnode->prev = phead->prev;newnode->next = phead;phead->prev->next = newnode;phead->prev = newnode;//注意:这两行代码不能颠倒位置
}//头插
void LTPushFront(LTNode* phead, LTDataType x)
{assert(phead);LTNode* newnode = LTBuyNode(x);//phead newnode phead->nextnewnode->next = phead->next;newnode->prev = phead;newnode->next->prev = newnode;phead->next = newnode;//注意:这两行代码不能颠倒位置
}//尾删
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;
}//头删
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;
}//查找
LTNode* LTFind(LTNode* phead, LTDataType x)
{LTNode* pcur = phead->next;while (pcur != phead){if (pcur->data == x){return pcur;}pcur = pcur->next;}//没有找到return NULL;
}//在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;}//删除pos节点
void LTErase(LTNode* pos)
{	assert(pos);// pos->prev pos pos->nextpos->next->prev = pos->prev;pos->prev->next = pos->next;//删除pos节点free(pos);pos = NULL;
}//销毁
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;
}

3.3 Test.c

#include"List.h"
void ListTest01()
{  	//传二级指针形式初始化/*LTNode* plist = NULL;LTInit(&plist); *///以返回值形式初始化LTNode* plist = LTInit();//尾插LTPushBack(plist, 1);LTPushBack(plist, 2);	LTPushBack(plist, 3);LTPrint(plist);//打印//头插LTPushFront(plist,4);	LTPushFront(plist,5);			LTPrint(plist);//打印//尾删LTPopBack(plist);LTPrint(plist);//打印//头删LTPopFront(plist);LTPrint(plist);//打印//查找LTNode* find = LTFind(plist,4);//删除pos节点LTErase(find);LTPrint(plist);//打印find = NULL;//手动置空//销毁		LTDesTroy(plist);plist = NULL;//手动置空
}
int main()
{ListTest01();return 0;
}

相关文章:

【数据结构】双向链表专题

目录 1.双向链表的结构 2.双向链表的实现 2.1初始化 以参数的形式初始化链表&#xff1a; 以返回值的形式初始化链表&#xff1a; 2.2尾插 2.3打印 2.4头插 2.5尾删 2.6头删 2.7查找 2.8在指定位置之后插入数据​编辑 2.9删除pos节点 2.10销毁 3.整理代码 3.1…...

大二上学期计划安排

大二上学期计划安排 学期目标: 加强算法学习,提升算法思维,为以后的算法竞赛做准备学习java知识,学习框架,构建知识体系,深入底层,增强理解增加项目经验,独立完成至少一个项目,并进行交流,优化增强团队凝聚力,营造良好的团队氛围阅读书籍,阅读至少3本以上经典书籍 日常学习安…...

HarmonyOS开发实战( Beta5.0)图片编辑实现马赛克效果详解

鸿蒙HarmonyOS开发往期必看&#xff1a; HarmonyOS NEXT应用开发性能实践总结 最新版&#xff01;“非常详细的” 鸿蒙HarmonyOS Next应用开发学习路线&#xff01;&#xff08;从零基础入门到精通&#xff09; 介绍 本示例将原图手指划过的区域分割成若干个大小一致的小方格…...

【新书介绍】《JavaScript前端开发与实例教程(微课视频版)(第2版)》

本书重点 无任何基础的初学者&#xff0c;高校JavaScript课程教材。 配套非常全&#xff0c;提供案例源代码、PPT课件、课后习题答案、微课视频、教案、教学大纲、课程实训、期末考试试卷、章节测试、实验报告、学习通建课资源包。 内容简介 JavaScript是开发Web前端必须掌…...

什么是GWAS全基因组关联分析?

什么是全基因组关联分析&#xff1f;&#xff08;Genome-Wide Association Study&#xff0c;GWAS&#xff09; 全基因组关联分析&#xff08;GWAS&#xff09;是一种在全基因组范围内搜索遗传变异&#xff08;通常是单核苷酸多态性&#xff0c;SNP&#xff09;与复杂性状之间关…...

k8s dashboard token 生成/获取

创建示例用户 在本指南中&#xff0c;我们将了解如何使用 Kubernetes 的服务帐户机制创建新用户、授予该用户管理员权限并使用与该用户绑定的承载令牌登录仪表板。 对于以下每个和的代码片段ServiceAccount&#xff0c;ClusterRoleBinding您都应该将它们复制到新的清单文件(如)…...

windows@openssh免密登陆配置@基于powershell快速配置脚本

文章目录 abstract免密自动登录配置介绍&#x1f47a;修改Server配置文件一键脚本修改&#x1f47a; 向ssh server端上传或创建支持免密登录的公钥文件预执行命令&#x1f47a;方式1方式2重启服务以生效&#x1f47a; 傻瓜式配置免密自动登录&#x1f47a;&#x1f47a;准备 操…...

【深度学习】【图像分类】【OnnxRuntime】【Python】VggNet模型部署

【深度学习】【图像分类】【OnnxRuntime】【Python】VggNet模型部署 提示:博主取舍了很多大佬的博文并亲测有效,分享笔记邀大家共同学习讨论 文章目录 【深度学习】【图像分类】【OnnxRuntime】【Python】VggNet模型部署前言Windows平台搭建依赖环境模型转换--pytorch转onnxONN…...

手写排班日历

手写排班日历&#xff1a; 效果图&#xff1a; vue代码如下&#xff1a; <template><div class"YSPB"><div class"title">排班日历</div><div class"banner"><span classiconfont icon-youjiantou click&qu…...

SpringBoot多数据源配置

1、添加依赖 <!-- 数据库驱动 --><!--mysql--><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>${mysql-connector-java.version}</version><scope>runtime</sco…...

影响画布微信小程序canvas及skyline和webview用户界面布局的关键流程

影响微信小程序画布canvas及skyline和webview用户界面布局的关键流程 目录 影响微信小程序画布canvas及skyline和webview用户界面布局的关键流程 一、微信小程序canvas开发流程 1.1、官方指南 1.2、客制化开发 第一步&#xff1a;在 WXML 中添加 canvas 组件 第二步&…...

MATLAB图像处理

MATLAB图像处理 MATLAB&#xff0c;作为美国MathWorks公司出品的商业数学软件&#xff0c;以其强大的矩阵运算能力和丰富的函数库&#xff0c;在图像处理领域得到了广泛的应用。MATLAB不仅提供了基础的图像处理功能&#xff0c;还通过图像处理工具箱&#xff08;Image Process…...

【编程底层思考】性能监控和优化:JVM参数调优,诊断工具的使用等。JVM 调优和线上问题排查实战经验总结

JVM性能监控和优化是确保Java应用程序高效运行的关键环节。以下是一些JVM性能监控和优化的方法&#xff0c;以及使用诊断工具和实战经验的总结&#xff1a; 一、JVM参数调优&#xff1a; 堆大小设置 : - Xms&#xff1a;设置JVM启动时的初始堆大小。 - -Xmx&#xff1a;设置J…...

数据库的实施过程分析

在完成了数据库的逻辑结构设计和物理结构设计后&#xff0c;下一步就是将设计成果转化为现实&#xff0c;这一步骤被称为数据库的实施。数据库实施是数据库开发过程中至关重要的一环&#xff0c;它标志着从设计阶段向实际应用的过渡。本文将为你详细讲解数据库实施的各个关键步…...

【Kubernetes】常见面试题汇总(十二)

目录 36.简述 Kubernetes 的负载均衡器&#xff1f; 37.简述 Kubernetes 各模块如何与 APl Server 通信&#xff1f; 38.简述 Kubernetes Scheduler 作用及实现原理&#xff1f; 36.简述 Kubernetes 的负载均衡器&#xff1f; &#xff08;1&#xff09;负载均衡器是暴露服务…...

基于SpringBoot+Vue+MySQL的美术馆管理系统

系统展示 用户前台界面 管理员后台界面 系统背景 随着文化艺术产业的蓬勃发展&#xff0c;美术馆作为展示与传播艺术的重要场所&#xff0c;其管理工作变得日益复杂。为了提升美术馆的运营效率、优化参观体验并加强艺术品管理&#xff0c;我们开发了基于SpringBootVueMySQL的美…...

golang面试

算法&#xff1a; 1.提取二进制位最右边的 r i & (~i 1) 2.树上两个节点最远距离&#xff0c;先考虑头结点参与不参与。 3.暴力递归改dp。 1.确定暴力递归方式。 2.改记忆化搜索 3.严格表方式&#xff1a; 分析可变参数变化范围&#xff0c;参数数量决定表维度、 …...

基于"WT2605C的智能血压计:AI对话引领个性化健康管理新时代,健康守护随时在线

在当今快节奏的生活中&#xff0c;健康管理已成为我们日常不可或缺的一部分。随着科技的进步&#xff0c;智能设备正逐步融入我们的日常生活&#xff0c;为健康管理带来前所未有的便捷与智能化。今天&#xff0c;让我们共同探索WT2605C AI在线方案如何在血压计中发挥革命性作用…...

redis高级教程

一 关系型数据库和 NoSQL 数据库 数据库主要分为两大类&#xff1a;关系型数据库与 NoSQL 数据库 关系型数据库 &#xff0c;是建立在关系模型基础上的数据库&#xff0c;其借助于集合代数等数学概念和方法来处理数据库中的数据主流的 MySQL 、 Oracle 、 MS SQL Server 和 D…...

prfm命令初探

1. 前言 在查看一段neon代码时&#xff0c;发现有如下片段&#xff0c;为使用汇编进行数据预取操作。这是一个新的知识点&#xff0c;记录一下学习过程。 __asm__ volatile("prfm pldl2keep,[%0, #8192] \n""prfm pldl1keep,[%0, #1024] \n":"r"…...

AI大模型需要学什么?怎么学?从零基础入门大模型(保姆级),从这开始出发!

一.初聊大模型 1.为什么要学习大模型&#xff1f; 在学习大模型之前&#xff0c;你不必担心自己缺乏相关知识或认为这太难。我坚信&#xff0c;只要你有学习的意愿并付出努力&#xff0c;你就能够掌握大模型&#xff0c;并能够用它们完成许多有意义的事情。在这个快速变化的时代…...

python自述3

Python 条件控制 if语句的一般形式如下所示: if condition_1: statement_block_1 elif condition_2: statement_block_2 else: statement_block_3 Python 中用 elif 代替了 else if,所以if语句的关键字为:if – elif – else。 注意: 1、每个条件后面要使用冒号 :,表…...

Redis常见的数据结构

Redis底层的数据结构是Redis高效存储和操作数据的基础,Redis提供了五种基本的数据类型&#xff0c;每种类型在底层都有对应的数据结构来实现。这五种数据类型分别是&#xff1a;字符串&#xff08;String&#xff09;、哈希&#xff08;Hash&#xff09;、列表&#xff08;List…...

批量插入insert到SQLServer数据库,BigDecimal精度丢失解决办法,不动代码,从驱动层面解决

概述 相信很多人都遇到过&#xff0c;使用sql server数据库&#xff0c;批量插入数据时&#xff0c;BigDecimal类型出现丢失精度的问题&#xff0c;网上也有很多人给出过解决方案&#xff0c;但一般都要修改应用代码&#xff0c;不推荐。 丢失精度的本质是官方的驱动有BUG造成…...

随手记:uniapp小程序登录方式和小程序使用验证码登录

小程序登录方式&#xff1a; 方式一&#xff1a;小程序授权登录 通过uni.login获取 临时登录凭证code&#xff0c;向后端换取token。 <u-button type"primary" shape"circle" click"login">登 录</u-button>login() {uni.login({p…...

【Hadoop|HDFS篇】DataNode概述

1. DataNode的工作机制 1&#xff09;一个数据块在DataNode上以文件形式存储在磁盘上&#xff0c;包括两个文件&#xff0c;一个是数据本身&#xff0c;一个是元数据包括数据块的长度&#xff0c;块数据的校验和&#xff0c;以及时间戳。 2&#xff09;DataNode启动后向NameNod…...

Vue2 VueRouter学习笔记

VueRouter 官方文档 版本对应 vue2&#xff1a;3.x.x vue3&#xff1a;4.x.x 路由&#xff1a;访问路径与vue组件&#xff08;页面&#xff09;之间的映射关系 VueRouter&#xff1a;Vue官方提供的插件&#xff0c;本质上是一个 JavaScript 库&#xff0c;用于在 Vue.js 应用…...

3D培训大师,化工企业安全教育与应急演练的新助力

化工企业的生产安全培训&#xff0c;作为保障员工生命安全与企业稳定运营的基石&#xff0c;其重要性不言而喻。传统的培训方式内容僵化、形式单一缺乏互动、效果难以评估&#xff0c;越来越不适应化工企业的实际需求。因此&#xff0c;探索和应用更为高效、创新的培训工具&…...

斯坦福大学论文润色chat-gpt指令

Quick Prompts快速提示 To enhance text clarity-为了增强文本清晰度 As a non-native English speaker, kindly help me revise the following text for improved understand clarity. Please check for spelling and sentence structure errors and suggest alternatives.为…...

简单硬件在环搭建(ROS+Prescan+Carsim+simulink)

本文通过ROSPrescanCarsimsimulink搭建简单的硬件在环仿真测试平台。 系统架构如下&#xff1a; 在Windows中运行prescan场景仿真软件&#xff0c;在jetson Nano中运行ROS&#xff0c;硬件上两台电脑通过一根网线相连传输信息&#xff1b; 1.prescan与carsim的集成 在C:\car…...