数据结构之链表
储备知识:
线性表 :一对一的数据所组成的关系称为线性表。
- 线性表是一种数据内部的逻辑关系,与存储形式无关
- 线性表既可以采用连续的顺序存储(数组),也可以采用离散的链式存储(链表)
- 顺序表和链表都称为线性表
顺序存储就是将数据存储到一片连续的内存中,在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应用架构…...
golang循环变量捕获问题
在 Go 语言中,当在循环中启动协程(goroutine)时,如果在协程闭包中直接引用循环变量,可能会遇到一个常见的陷阱 - 循环变量捕获问题。让我详细解释一下: 问题背景 看这个代码片段: fo…...
【SpringBoot】100、SpringBoot中使用自定义注解+AOP实现参数自动解密
在实际项目中,用户注册、登录、修改密码等操作,都涉及到参数传输安全问题。所以我们需要在前端对账户、密码等敏感信息加密传输,在后端接收到数据后能自动解密。 1、引入依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId...

Vue2 第一节_Vue2上手_插值表达式{{}}_访问数据和修改数据_Vue开发者工具
文章目录 1.Vue2上手-如何创建一个Vue实例,进行初始化渲染2. 插值表达式{{}}3. 访问数据和修改数据4. vue响应式5. Vue开发者工具--方便调试 1.Vue2上手-如何创建一个Vue实例,进行初始化渲染 准备容器引包创建Vue实例 new Vue()指定配置项 ->渲染数据 准备一个容器,例如: …...

【项目实战】通过多模态+LangGraph实现PPT生成助手
PPT自动生成系统 基于LangGraph的PPT自动生成系统,可以将Markdown文档自动转换为PPT演示文稿。 功能特点 Markdown解析:自动解析Markdown文档结构PPT模板分析:分析PPT模板的布局和风格智能布局决策:匹配内容与合适的PPT布局自动…...

Springcloud:Eureka 高可用集群搭建实战(服务注册与发现的底层原理与避坑指南)
引言:为什么 Eureka 依然是存量系统的核心? 尽管 Nacos 等新注册中心崛起,但金融、电力等保守行业仍有大量系统运行在 Eureka 上。理解其高可用设计与自我保护机制,是保障分布式系统稳定的必修课。本文将手把手带你搭建生产级 Eur…...

MySQL 8.0 OCP 英文题库解析(十三)
Oracle 为庆祝 MySQL 30 周年,截止到 2025.07.31 之前。所有人均可以免费考取原价245美元的MySQL OCP 认证。 从今天开始,将英文题库免费公布出来,并进行解析,帮助大家在一个月之内轻松通过OCP认证。 本期公布试题111~120 试题1…...

ABAP设计模式之---“简单设计原则(Simple Design)”
“Simple Design”(简单设计)是软件开发中的一个重要理念,倡导以最简单的方式实现软件功能,以确保代码清晰易懂、易维护,并在项目需求变化时能够快速适应。 其核心目标是避免复杂和过度设计,遵循“让事情保…...
蓝桥杯 冶炼金属
原题目链接 🔧 冶炼金属转换率推测题解 📜 原题描述 小蓝有一个神奇的炉子用于将普通金属 O O O 冶炼成为一种特殊金属 X X X。这个炉子有一个属性叫转换率 V V V,是一个正整数,表示每 V V V 个普通金属 O O O 可以冶炼出 …...

招商蛇口 | 执笔CID,启幕低密生活新境
作为中国城市生长的力量,招商蛇口以“美好生活承载者”为使命,深耕全球111座城市,以央企担当匠造时代理想人居。从深圳湾的开拓基因到西安高新CID的战略落子,招商蛇口始终与城市发展同频共振,以建筑诠释对土地与生活的…...

【从零开始学习JVM | 第四篇】类加载器和双亲委派机制(高频面试题)
前言: 双亲委派机制对于面试这块来说非常重要,在实际开发中也是经常遇见需要打破双亲委派的需求,今天我们一起来探索一下什么是双亲委派机制,在此之前我们先介绍一下类的加载器。 目录 编辑 前言: 类加载器 1. …...