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

【双向链表的实现】

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

目录

前言

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.顺序表和双向链表的优缺点分析


总结

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

相关文章:

【双向链表的实现】

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 目录 前言 1. 双向链表的结构 2. 双向链表的实现 2.1 头文件 ——双向链表的创建及功能函数的定义 2.2 源文件 ——双向链表的功能函数的实现 2.3 源文件 ——双向链表功能的…...

中台战略思想与架构总结

中台战略思想与架构总结 在2015年年中&#xff0c;马云带领阿里高管&#xff0c;拜访了游戏公司Supercell&#xff0c;以《部落战争》《海岛奇兵》《卡通农场》等游戏知名。 Supercell是一家典型的以小团队模式进行游戏开发的公司&#xff0c;一般来说两个员工&#xff0c;或…...

VUE2+THREE.JS点击事件

THREE.JS点击事件 1.增加监听点击事件2.点击事件实现3.记得关闭页面时 销毁此监听事件 1.增加监听点击事件 renderer.domElement.addEventListener("click", this.onClick, false); 注:初始化render时监听 2.点击事件实现 onClick(event) {const raycaster new …...

基于SSM+SpringBoot+Vue小区车位租赁系统

[技术实现] 小区车位租赁系统是使用SSMSpringBootVue前后端分离的管理系统。使用Spring框架可以在自动注入项目层级之间的调用对象&#xff0c;方便解耦&#xff0c;SpringMVC是体现了MVC设计思想的轻量级web框架&#xff0c;对web层进行解耦&#xff0c;使开发更简洁,MyBatis…...

Oracle(2-8)Configuring the Database Archiving Mode

文章目录 一、基础知识1、Redo Log History2、NOARCHIVELOG Mode 非归档模式3、ARCHIVELOG Mode 归档模式4、Changing the Archiving Mode 更改归档模式![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/d6a09f9a6de24de7bbcdad90b8d6b9ca.png)5、Auto and Manual Ar…...

制造企业建设数字工厂管理系统的难点主要有哪些

随着科技的飞速发展&#xff0c;制造企业正面临着从传统生产模式向数字化、智能化转型的挑战。其中&#xff0c;建设数字工厂管理系统是实现这一目标的重要途径。然而&#xff0c;在实际操作过程中&#xff0c;制造企业往往会遇到一系列难点。本文将对这些难点进行详细的分析。…...

基于UDP网络聊天室OICQ

Linux系统 Gcc Gdb makefile 实现局域网OICQ程序设计&#xff0c;包括客户端和服务端。 客户端描述&#xff1a;客户端运行开始出现登陆界面。与服务端进行连接&#xff0c;连接后把账号信息发送给服务端&#xff0c;服务端验证后&#xff0c;把确认结果通知客户端。如果通…...

基于STC12C5A60S2系列1T 8051单片机的液晶显示器LCD1602显示整数、小数应用

基于STC12C5A60S2系列1T 8051单片机的液晶显示器LCD1602显示整数、小数应用 STC12C5A60S2系列1T 8051单片机管脚图STC12C5A60S2系列1T 8051单片机I/O口各种不同工作模式及配置STC12C5A60S2系列1T 8051单片机I/O口各种不同工作模式介绍液晶显示器LCD1602简单介绍IIC通信简单介绍…...

【微信小程序】保存多张图片到本地相册 wx.saveImageToPhotosAlbum

这里写目录标题 微信小程序检测是否有存储权限wx.getSetting 图片上传从HTML中提取img标签的src属性多图片下载 微信小程序检测是否有存储权限 wx.getSetting 上传前判断是否开启存储权限&#xff0c;如果不检测直接上传会出现fail的情况 var _this this wx.getSetting({su…...

【Android】使用intent.putExtra()方法在启动Activity时传递数据

食用方法 在Android中&#xff0c;你可以使用Intent对象来在启动Activity时传递数据。以下是一个示例&#xff0c;展示了如何在startActivity时传递数据到被启动的Activity&#xff1a; 在启动Activity的地方&#xff0c;创建一个Intent对象&#xff0c;并使用putExtra()方法…...

数据结构与算法编程题35

用按层次顺序遍历二叉树的方法&#xff0c;统计树中具有度为1的结点数目。 #define _CRT_SECURE_NO_WARNINGS#include <iostream> using namespace std;typedef char ElemType; #define ERROR 0 #define OK 1 #define Maxsize 100 #define STR_SIZE 1024typedef struct B…...

每日一题 - 231201 - Divisibility by Eight

Divisibility by Eight TAG - 整除特性、枚举 整除特性、枚举 整除特性、枚举时间复杂度 - O ( N 3 ) O(N^3) O(N3) // #include<bits/stdc.h> using namespace std; // #define int long long void solve() {string s;cin>>s;for( int i0;i<s.size();i )if(…...

虚幻学习笔记1—给UI添加动画

一、前言 本文所使用的虚幻版本为5.3.2&#xff0c;之前工作都是用unity&#xff0c;做这类效果用的最多的是一个DoTween的插件&#xff0c;在虚幻中都内置集成了这这种效果制作。 图1.1 UI动画 二、过程 1、首先&#xff0c;在诸如按钮、图像等可交互控件中选中&#xff0c;如…...

【RabbitMQ】RabbitMQ快速入门 通俗易懂 初学者入门

目录 1.初识MQ 1.1.同步和异步通讯 1.1.1.同步通讯 1.1.2.异步通讯 1.2.技术对比&#xff1a; 2.快速入门 2.1.安装RabbitMQ 2.2.RabbitMQ消息模型 2.3.导入Demo工程 2.4.入门案例 2.4.1.publisher实现 2.4.2.consumer实现 2.5.总结 3.SpringAMQP 3.1.Basic Que…...

JAVEE初阶 多线程基础(四)

线程安全 一.线程安全存在的问题二.锁三.关于锁的理解四.关于锁操作混淆的理解4.1两个线程是否对同一对象加锁 一.线程安全存在的问题 为什么这里的count不是一百万呢?这就是线程所存在的不安全的问题,由于线程是抢占式执行,同时执行count,操作本质是三个指令 1.load 读取内存…...

【C 语言经典100例】C 练习实例19

题目&#xff1a;一个数如果恰好等于它的因子之和&#xff0c;这个数就称为"完数"。例如61&#xff0b;2&#xff0b;3.编程找出1000以内的所有完数。 程序分析&#xff1a;请参照&#xff1a;C 练习实例14。 #include<stdio.h> #define N 1000 int main() {…...

Jmeter+Maven+jenkins+eclipse搭建自动化测试平台

背景&#xff1a; 首先用jmeter录制或者书写性能测试的脚本&#xff0c;用maven添加相关依赖&#xff0c;把性能测试的代码提交到github&#xff0c;在jenkins配置git下载性能测试的代码&#xff0c;配置运行脚本和测试报告&#xff0c;配置运行失败自动发邮件通知&#xff0c…...

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

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

WordPress:构建强大的网站和博客的完美选择

WordPress&#xff1a;构建强大的网站和博客的完美选择 一、WordPress 简介1.1 WordPress 介绍1.2 WordPress 优势 二、部署LNMP环境2.1 前提条件2.2 关闭防火墙和SELinux2.3 安装Nginx2.4 安装MySQL2.5 安装PHP2.6 配置Nginx2.7 配置MySQL2.8 配置PHP2.9 测试访问LNMP平台 三、…...

2021年8月18日 Go生态洞察:整合Go的网络体验

&#x1f337;&#x1f341; 博主猫头虎&#xff08;&#x1f405;&#x1f43e;&#xff09;带您 Go to New World✨&#x1f341; &#x1f984; 博客首页——&#x1f405;&#x1f43e;猫头虎的博客&#x1f390; &#x1f433; 《面试题大全专栏》 &#x1f995; 文章图文…...

Java如何权衡是使用无序的数组还是有序的数组

在 Java 中,选择有序数组还是无序数组取决于具体场景的性能需求与操作特点。以下是关键权衡因素及决策指南: ⚖️ 核心权衡维度 维度有序数组无序数组查询性能二分查找 O(log n) ✅线性扫描 O(n) ❌插入/删除需移位维护顺序 O(n) ❌直接操作尾部 O(1) ✅内存开销与无序数组相…...

【大模型RAG】Docker 一键部署 Milvus 完整攻略

本文概要 Milvus 2.5 Stand-alone 版可通过 Docker 在几分钟内完成安装&#xff1b;只需暴露 19530&#xff08;gRPC&#xff09;与 9091&#xff08;HTTP/WebUI&#xff09;两个端口&#xff0c;即可让本地电脑通过 PyMilvus 或浏览器访问远程 Linux 服务器上的 Milvus。下面…...

STM32标准库-DMA直接存储器存取

文章目录 一、DMA1.1简介1.2存储器映像1.3DMA框图1.4DMA基本结构1.5DMA请求1.6数据宽度与对齐1.7数据转运DMA1.8ADC扫描模式DMA 二、数据转运DMA2.1接线图2.2代码2.3相关API 一、DMA 1.1简介 DMA&#xff08;Direct Memory Access&#xff09;直接存储器存取 DMA可以提供外设…...

《用户共鸣指数(E)驱动品牌大模型种草:如何抢占大模型搜索结果情感高地》

在注意力分散、内容高度同质化的时代&#xff0c;情感连接已成为品牌破圈的关键通道。我们在服务大量品牌客户的过程中发现&#xff0c;消费者对内容的“有感”程度&#xff0c;正日益成为影响品牌传播效率与转化率的核心变量。在生成式AI驱动的内容生成与推荐环境中&#xff0…...

土地利用/土地覆盖遥感解译与基于CLUE模型未来变化情景预测;从基础到高级,涵盖ArcGIS数据处理、ENVI遥感解译与CLUE模型情景模拟等

&#x1f50d; 土地利用/土地覆盖数据是生态、环境和气象等诸多领域模型的关键输入参数。通过遥感影像解译技术&#xff0c;可以精准获取历史或当前任何一个区域的土地利用/土地覆盖情况。这些数据不仅能够用于评估区域生态环境的变化趋势&#xff0c;还能有效评价重大生态工程…...

OPenCV CUDA模块图像处理-----对图像执行 均值漂移滤波(Mean Shift Filtering)函数meanShiftFiltering()

操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 编程语言&#xff1a;C11 算法描述 在 GPU 上对图像执行 均值漂移滤波&#xff08;Mean Shift Filtering&#xff09;&#xff0c;用于图像分割或平滑处理。 该函数将输入图像中的…...

Unity | AmplifyShaderEditor插件基础(第七集:平面波动shader)

目录 一、&#x1f44b;&#x1f3fb;前言 二、&#x1f608;sinx波动的基本原理 三、&#x1f608;波动起来 1.sinx节点介绍 2.vertexPosition 3.集成Vector3 a.节点Append b.连起来 4.波动起来 a.波动的原理 b.时间节点 c.sinx的处理 四、&#x1f30a;波动优化…...

听写流程自动化实践,轻量级教育辅助

随着智能教育工具的发展&#xff0c;越来越多的传统学习方式正在被数字化、自动化所优化。听写作为语文、英语等学科中重要的基础训练形式&#xff0c;也迎来了更高效的解决方案。 这是一款轻量但功能强大的听写辅助工具。它是基于本地词库与可选在线语音引擎构建&#xff0c;…...

基于SpringBoot在线拍卖系统的设计和实现

摘 要 随着社会的发展&#xff0c;社会的各行各业都在利用信息化时代的优势。计算机的优势和普及使得各种信息系统的开发成为必需。 在线拍卖系统&#xff0c;主要的模块包括管理员&#xff1b;首页、个人中心、用户管理、商品类型管理、拍卖商品管理、历史竞拍管理、竞拍订单…...

scikit-learn机器学习

# 同时添加如下代码, 这样每次环境(kernel)启动的时候只要运行下方代码即可: # Also add the following code, # so that every time the environment (kernel) starts, # just run the following code: import sys sys.path.append(/home/aistudio/external-libraries)机…...