数据结构之链表
储备知识:
线性表 :一对一的数据所组成的关系称为线性表。
- 线性表是一种数据内部的逻辑关系,与存储形式无关
- 线性表既可以采用连续的顺序存储(数组),也可以采用离散的链式存储(链表)
- 顺序表和链表都称为线性表
顺序存储就是将数据存储到一片连续的内存中,在C语言环境下,可以是具名的栈数组,或者是匿名的堆数组。
栈空间:char buf[4];自动申请空间,函数结束后自动释放,{}内定义的局部变量,{}过后自动释放,空间大小为8M
堆空间:malloc(16) calloc(4,sizeof(int)) realloc()
手动分配空间,手动释放空间,空间大小为实际物理内存,空间生命周期为整个程序的生命周期
1.优点
- 不需要多余的信息来记录数据的关系,存储密度高
- 所有数据顺序存储在一片连续的内存中,支持立即访问任意一个随机数据
2.缺点
- 插入、删除时需要保持数据的物理位置反映其逻辑关系,需要成片移动数据
- 当数据节点较多时,需要一整片较大的连续内存空间
- 当数据节点数量变化剧烈时,内存的释放和分配不灵活
链表存储可以将数据存储到不连续的内存空间中,可以是单链表或双链表。

单链表
一种常见的数据结构,它由一系列节点组成,每个节点包含了数据部分和指向下一个节点的指针。在单链表中,第一个节点称为头节点,最后一个节点的指针指向空,表示链表的结束。
特点:
- 动态大小:单链表的大小可以根据需要动态增长或缩小。
- 插入和删除操作:在单链表中插入或删除节点通常比较灵活,只需要改变相邻节点的指针即可。
- 不需要连续内存:与数组不同,单链表的节点不需要在内存中连续存储,它们可以分散在内存的任何位置。
- 访问效率:访问单链表中的元素需要从头节点开始,逐个遍历到所需位置,因此访问效率相对较低。
单链表的常见操作包括:
- 插入:在链表的指定位置插入新节点。
- 删除:删除链表中的指定节点。
- 搜索:查找链表中包含特定数据的节点。
- 遍历:从头节点开始,依次访问链表中的每个节点。
创建有头结点单链表
1. 从无到有:第一个节点的诞生,此时的首节点和尾节点都是它本身
2 .从少到多(添加节点过程):
- 尾插法
新节点插入在选定节点后面;若所选节点为尾节点(last)原指向的节点,则原来的尾节点被新节点替代,成为新的尾节点。
- 头插法
新节点插入在选定节点前面;若所选节点为首节点(last)原指向的节点,则原来的首节点被新节点替代,成为新的首节点。
// 定义数据节点
struct node
{dataType data; // 数据域struct node *next; // 指针域,存放(指向)下一个节点的地址
};// 定义头节点
struct headNode
{struct node *first; // 指向第一个数据节点struct node *last; // 指向最后一个数据节点int nodeNumber; // 记录链表节点数
};//创建头节点
struct headNode* create_new_headNode()
{struct headNode* head = malloc(sizeof(struct headNode));if(head == NULL)return NULL;head->first = NULL;head->last = NULL;head->nodeNumber = 0;return head;
}// 创建新节点
struct node* create_new_node(dataType data)
{struct node* pnew = malloc(sizeof(struct node));if(pnew == NULL)return NULL;pnew->data = data;pnew->next = NULL;return pnew;
}// 尾插法
void addTail(struct headNode *head,struct node* pnew)
{head->last->next = pnew;head->last = pnew;
}//创建链表
struct headNode* create_list()
{// 创建头节点struct headNode* head = create_new_headNode();if(head == NULL)return NULL;dataType data = -1;while(1){scanf("%d",&data);if(data == 0)break;// 创建新节点struct node* pnew = create_new_node(data);if(pnew == NULL)return NULL;// 从无到有if(head->first == NULL){head->first = pnew;head->last = pnew;}else // 从少到多{// 尾插法addTail(head,pnew);}// 更新节点head->nodeNumber++;}return head;
}//显示链表
void showList(struct headNode* head)
{if(head->first == NULL){printf("链表为空\n");return;}for(struct node* p = head->first;p != head->last->next;p = p->next){printf("%d\t",p->data);}printf("\n");printf("链表节点数为:%d\n",head->nodeNumber);
}
双链表
是一种链式数据结构,它由一系列节点组成,每个节点除了包含数据外,还包含两个指针:一个指向前一个节点,一个指向后一个节点。这种结构允许双向遍历链表,即可以从头节点开始向前遍历,也可以从尾节点开始向后遍历。
特点:
- 双向链接:每个节点都有指向前一个和后一个节点的指针,这使得在链表中的移动更加灵活。
- 动态大小:与单链表一样,双链表的大小可以动态变化。
- 插入和删除操作:在双链表中,插入和删除操作通常比单链表更加高效,因为可以直接访问前一个或后一个节点,而不需要像单链表那样从头节点开始遍历。
- 不需要连续内存:节点在内存中不需要连续存储,可以分散在内存的任何位置。
双链表的常见操作包括:
- 插入:可以在链表的任意位置插入新节点,包括在头节点之前或尾节点之后。
- 删除:可以快速删除指定节点,因为可以直接访问前一个和后一个节点来更新指针。
- 搜索:可以从头或尾开始搜索特定数据的节点。
- 遍历:可以正向或反向遍历链表。
创建有头结点双链表
// 创建数据节点
struct node
{dataType data;struct node *prev;// 指向上一个节点struct node *next;// 指向下一个节点
};// 创建头节点
struct headNode
{struct node *first; // 指向首节点struct node *last; // 指向最后一个节点int nodeNumber; // 记录节点数
};// 创建头节点
struct headNode *create_head()
{// 创建头节点struct headNode *head = malloc(sizeof(struct headNode));if(head == NULL){perror("create head failed:");return NULL;}head->first = NULL;head->last = NULL;head->nodeNumber = 0;return head;
}// 创建新节点
struct node *create_new_node(dataType data)
{struct node *pnew = malloc(sizeof(struct node));if(pnew == NULL){perror("create new node failed:");return NULL;}pnew->data = data;pnew->prev = NULL;pnew->next = NULL;
}//增加节点
struct headNode *add_node_list(struct headNode *head,dataType newData,dataType data)
{// 创建新节点struct node *pnew = create_new_node(newData);if(pnew == NULL)return NULL;// 找节点struct node *p = head->first;while(p){if(p->data == data)break;else{p = p->next;}}// 如果找的是第一个节点if(p->data == head->first->data){addHead(pnew,head);}else if(p == NULL){addTail(pnew,head);}else{pnew->next = p;pnew->prev = p;p->prev->next = pnew;pnew->prev = pnew; }head->nodeNumber++;return head;
}//删除节点
struct headNode *del_node(struct headNode *head,dataType data)
{// 找节点struct node *p = head->first;while(p){if(p->data == data)break;elsep = p->next;}// 如果是第一个节点if(head->first->data == data){head->first->next->prev = head->first;head->first = p->next;p->next = NULL;p->prev = NULL;free(p);}else if(p->data == head->last->data){p->prev->next = NULL;p->prev = NULL;free(p);}else if(p == NULL){printf("没有可删除的节点\n");}else{p->next->prev = p->prev;p->prev->next = p->next;p->prev = NULL;p->next = NULL;free(p);}head->nodeNumber--;return head;
}//链表遍历
void showList(struct headNode *head)
{for(struct node *p = head->first;p != head->last->next;p = p->next){printf("%d\t",p->data);}printf("\n");printf("节点数为:%d\n",head->nodeNumber);
}// 销毁链表
struct headNode * distory_list(struct headNode *head)
{if(isEmpty(head))return false;// 逐一删除节点struct node *p = NULL;for(struct node *tmp = head->first;tmp != NULL; tmp = p){p = tmp->next;free(tmp);head->nodeNumber--;}return head;
}
双向循环链表
结构上和双向链表就只差首尾相连。
// 至少还有一个节点时将首尾相连
if(head->nodeNumber != 0)
{head->last->next = head->first;head->first->prev = head->last;
}
相关文章:
数据结构之链表
储备知识: 线性表 :一对一的数据所组成的关系称为线性表。 线性表是一种数据内部的逻辑关系,与存储形式无关线性表既可以采用连续的顺序存储(数组),也可以采用离散的链式存储(链表)顺序表和链表都称为线性表 顺序存储就是将数据存…...
【小工具】 Unity相机宽度适配
相机默认是根据高度适配的,但是在部分游戏中需要根据宽度进行适配 实现步骤 定义标准屏幕宽、高判断标准屏幕宽高比与当前的是否相等通过**(标准宽度/当前宽度) (标准高度 / 当前高度)**计算缩放调整相机fieldOfView即…...
centos误删yum和python
在下载pkdg时,因为yum报错坏的解释器,然后误删了yum和python。 在下载各种版本,创建各种软连接,修改yum文件都不好使后,发现了这样一个方法:Centos: 完美解决python升级导致的yum报错问题(相信…...
WP黑格导航主题BlackCandy
BlackCandy-V2.0全新升级!首推专题区(推荐分类)更多自定义颜色!选择自己喜欢的色系,焕然一新的UI设计,更加扁平和现代化! WP黑格导航主题BlackCandy...
elasticsearch底层核心组件
Elasticsearch是一个高度可扩展的开源全文搜索和分析引擎,它基于Apache Lucene构建,并添加了分布式特性。以下是Elasticsearch的一些底层核心组件: 1. **Lucene**: - Elasticsearch基于Apache Lucene,一个高性能的…...
EasyExcel数据导入
前言: 我先讲一种网上信息的获取方式把,虽然我感觉和后面的EasyExcel没有什么关系,可能是因为这个项目这个操作很难实现,不过也可以在此记录一下,如果需要再拆出来也行。 看上了网页信息,怎么抓到&#x…...
20240630 每日AI必读资讯
📚全美TOP 5机器学习博士发帖吐槽:实验室H100数量为0! - 普林斯顿、哈佛「GPU豪门」,手上的H100至少三四百块,然而绝大多数ML博士一块H100都用不上 - 年轻的研究者们纷纷自曝自己所在学校或公司的GPU情况:…...
第十一章 Qt的模型视图
目录 一、模型/视图的原理 1、原理分析 2、模型(数据模型) 3、视图 4、代理 二、文件系统模型 1、项目练习 2、UI 设计 3、代码实现 三、字符串链表模型 QStringListModel 1、项目效果 2、项目实现 四、标准项模型(QStandardItemModel) 1、模型分析 2、项目效…...
力扣 单词规律
所用数据结构 哈希表 核心方法 判断字符串pattern 和字符串s 是否存在一对一的映射关系,按照题意,双向连接的对应规律。 思路以及实现步骤 1.字符串s带有空格,因此需要转换成字符数组进行更方便的操作,将字符串s拆分成单词列表…...
10款好用不火的PC软件,真的超好用!
AI视频生成:小说文案智能分镜智能识别角色和场景批量Ai绘图自动配音添加音乐一键合成视频https://aitools.jurilu.com/市场上有很多软件,除了那些常见的大众化软件,还有很多不为人知的小众软件,它们的作用非常强大,简洁…...
Windows怎么实现虚拟IP
在做高可用架构时,往往需要用到虚拟IP,在linux上面有keepalived来实现虚拟ip的设置。在windows上面该怎么弄,keepalived好像也没有windows版本,我推荐一款浮动IP软件PanguVip,它可以实现windows上面虚拟ip的漂移。设置…...
【计算机网络】HTTP——基于HTTP的功能追加协议(个人笔记)
学习日期:2024.6.29 内容摘要:基于HTTP的功能追加协议和HTTP/2.0 HTTP的瓶颈与各功能追加协议 需求的产生 在Facebook、推特、微博等平台,每分每秒都会有人更新内容,我们作为用户当然希望时刻都能收到最新的消息,为…...
【多媒体】Java实现MP4视频播放器【JavaFX】【音视频播放】
在Java中播放视频可以使用多种方案,最常见的是通过Swing组件JFrame和JLabel来嵌入JMF(Java Media Framework)或Xuggler。不过,JMF已经不再被推荐使用,而Xuggler是基于DirectX的,不适用于跨平台。而且上述方案都需要使用第三方库。…...
2024 Parallels Desktop for Mac 功能介绍
Parallels Desktop的简介 Parallels Desktop是一款由Parallels公司开发的桌面虚拟化软件,它允许用户在Mac上运行Windows和其他操作系统。通过强大的技术支持,用户无需重新启动电脑即可在Mac上运行Windows应用程序,实现了真正的无缝切换。 二…...
颍川韩氏,来自战国七雄韩国的豪族
颍川是战国七雄韩国故土,韩国被秦国灭国后,王公贵族们除了坚决反秦的被杀了外,大部分都留存了下来。这些人在楚、汉反秦战争中,成为反秦统一战线的重要力量,其中两人先后被封为重新恢复的韩国的国王。 一个是横阳君韩…...
Spring boot中如何使用Thymeleaf模板
大家好,我是 网创有方。今天给大家分享下Spring boot中如何使用Thymeleaf模板。 在 IntelliJ IDEA 中使用 Thymeleaf 模板引擎来开发 Spring Boot 应用程序是相对简单的。以下是一些基本步骤,帮助你在 IDEA 中设置和使用 Thymeleaf: 创建一个…...
单片机学习(14)--DS18B20温度传感器
DS18B20温度传感器 13.1DS18B20温度传感器基础知识1.DS18B20介绍2.引脚及应用电路3.内部结构框图4.存储器框图5.单总线介绍6.单总线电路规范7.单总线时序结构8.DS18B20操作流程9.DS18B20数据帧 13.2DS18B20温度读取和温度报警器代码1.DS18B20温度读取(1)…...
ue 材质贴图Tiling repeat
材质问题,如下 贴图显然不符合逻辑,太大,并且是一次性贴图 换一个红砖纹理,就看清了,砖太大了 修改: 拖出一个TexCoord,代表坐标,拖出一个参数,代表次数,如…...
【图像超分辨率】一个简单的总结
文章目录 图像超分辨率(Image Super-Resolution, ISR)1 什么是图像超分辨率?2 图像超分辨率通常有哪些方法?(1)基于插值的方法(2)基于重建的方法(3)基于学习的方法(LR im…...
WEB与低代码:B/S架构在开发中的应用与优势
在互联网迅猛发展的今天,WEB应用已经成为人们日常生活和工作中不可或缺的一部分。随着技术的进步和需求的多样化,开发高效、灵活且易于维护的WEB应用变得尤为重要。B/S架构(Browser/Server Architecture)作为一种常见的WEB应用架构…...
以下是对华为 HarmonyOS NETX 5属性动画(ArkTS)文档的结构化整理,通过层级标题、表格和代码块提升可读性:
一、属性动画概述NETX 作用:实现组件通用属性的渐变过渡效果,提升用户体验。支持属性:width、height、backgroundColor、opacity、scale、rotate、translate等。注意事项: 布局类属性(如宽高)变化时&#…...
论文解读:交大港大上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化学习框架(一)
宇树机器人多姿态起立控制强化学习框架论文解析 论文解读:交大&港大&上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化学习框架(一) 论文解读:交大&港大&上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化…...
Rapidio门铃消息FIFO溢出机制
关于RapidIO门铃消息FIFO的溢出机制及其与中断抖动的关系,以下是深入解析: 门铃FIFO溢出的本质 在RapidIO系统中,门铃消息FIFO是硬件控制器内部的缓冲区,用于临时存储接收到的门铃消息(Doorbell Message)。…...
今日学习:Spring线程池|并发修改异常|链路丢失|登录续期|VIP过期策略|数值类缓存
文章目录 优雅版线程池ThreadPoolTaskExecutor和ThreadPoolTaskExecutor的装饰器并发修改异常并发修改异常简介实现机制设计原因及意义 使用线程池造成的链路丢失问题线程池导致的链路丢失问题发生原因 常见解决方法更好的解决方法设计精妙之处 登录续期登录续期常见实现方式特…...
Go 语言并发编程基础:无缓冲与有缓冲通道
在上一章节中,我们了解了 Channel 的基本用法。本章将重点分析 Go 中通道的两种类型 —— 无缓冲通道与有缓冲通道,它们在并发编程中各具特点和应用场景。 一、通道的基本分类 类型定义形式特点无缓冲通道make(chan T)发送和接收都必须准备好࿰…...
省略号和可变参数模板
本文主要介绍如何展开可变参数的参数包 1.C语言的va_list展开可变参数 #include <iostream> #include <cstdarg>void printNumbers(int count, ...) {// 声明va_list类型的变量va_list args;// 使用va_start将可变参数写入变量argsva_start(args, count);for (in…...
FFmpeg:Windows系统小白安装及其使用
一、安装 1.访问官网 Download FFmpeg 2.点击版本目录 3.选择版本点击安装 注意这里选择的是【release buids】,注意左上角标题 例如我安装在目录 F:\FFmpeg 4.解压 5.添加环境变量 把你解压后的bin目录(即exe所在文件夹)加入系统变量…...
第7篇:中间件全链路监控与 SQL 性能分析实践
7.1 章节导读 在构建数据库中间件的过程中,可观测性 和 性能分析 是保障系统稳定性与可维护性的核心能力。 特别是在复杂分布式场景中,必须做到: 🔍 追踪每一条 SQL 的生命周期(从入口到数据库执行)&#…...
Rust 开发环境搭建
环境搭建 1、开发工具RustRover 或者vs code 2、Cygwin64 安装 https://cygwin.com/install.html 在工具终端执行: rustup toolchain install stable-x86_64-pc-windows-gnu rustup default stable-x86_64-pc-windows-gnu 2、Hello World fn main() { println…...
Vue ③-生命周期 || 脚手架
生命周期 思考:什么时候可以发送初始化渲染请求?(越早越好) 什么时候可以开始操作dom?(至少dom得渲染出来) Vue生命周期: 一个Vue实例从 创建 到 销毁 的整个过程。 生命周期四个…...
