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

【数据结构】万字深入浅出讲解单链表(附原码 | 超详解)

在这里插入图片描述

🚀write in front🚀
📝个人主页:认真写博客的夏目浅石.
🎁欢迎各位→点赞👍 + 收藏⭐️ + 留言📝
📣系列专栏:C语言实现数据结构
💬总结:希望你看完之后,能对你有所帮助,不足请指正!共同学习交流 🖊
✉️如果无聊的话,就来逛逛我的博客栈吧stack-frame.cn

文章目录

  • 前言
  • 一、链表概念
  • 二、链表的分类
    • 1. 单向或者双向
    • 2. 带头或者不带头
    • 3. 循环或者非循环
  • 三、链表的实现
    • 函数接口汇总SList.h
    • 函数接口实现SList.c
    • 代码实践Test.c
  • 代码汇总
  • 总结


前言

这几天看了数据结构的单链表这一节,真的收获很大,第一次看没有动手敲代码就是感觉学了和没学一样,今天也是从新又看了一遍,并且边学边敲代码,终于算是非常理解单链表这个东西了,今天就把我所学到的知识给大家分享一下。


一、链表概念

链表是一种物理存储结构非连续非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针
接次序实现的 。
在这里插入图片描述

二、链表的分类

1. 单向或者双向

在这里插入图片描述

2. 带头或者不带头

在这里插入图片描述

3. 循环或者非循环

在这里插入图片描述
虽然有这么多的链表的结构,但是我们实际中最常用还是两种结构

1.无头单向链表

2.双向循环链表
在这里插入图片描述

  1. 无头单向非循环链表:结构简单,一般不会单独用来存数据。实际中更多是作为其他数据结构的子结构,如哈希桶、图的邻接表等等。另外这种结构在笔试面试中出现很多。
  2. 带头双向循环链表:结构最复杂,一般用在单独存储数据。实际中使用的链表数据结构,都是带头向循环链表。另外这个结构虽然结构复杂,但是使用代码实现以后会发现结构会带来很多优势,实现反而简单了,后面我们代码实现了就知道了。

三、链表的实现

函数接口汇总SList.h


typedef int SLTDataType;typedef struct SListNode
{SLTDataType data;struct SListNode* next;
}SLTNode;//打印
void SLTPrint(SLTNode* phead);
SLTNode* BuySLTNode(SLTDataType x);
//增
void SLTPushBack(SLTNode** pphead,SLTDataType x);
void SLTPushFront(SLTNode** pphead,SLTDataType x);
//删
void SLTPopBack(SLTNode** pphead);
void SLTPopFront(SLTNode** pphead);//查找
SLTNode* SListFind(SLTNode* phead,SLTDataType x);
//任意位置插入
void SListInsert(SLTNode** pphead, SLTNode* pos, SLTDataType x);
//删除某个节点
void SListErase(SLTNode** pphead, SLTNode* pos);
//在后面插入一个节点
void SListInsertAfter(SLTNode* pos, SLTDataType x);
//删除pos后面这一个节点
void SListEraseAfter(SLTNode* pos);

函数接口实现SList.c


//--------------------------手动分割线---------------------------
//打印
void SLTPrint(SLTNode* phead)
{assert(phead);SLTNode* cur=phead;while(cur){printf("%d ",cur->data);cur=cur->next;}printf("NULL\n");
}
//--------------------------手动分割线-----------------------------
//创建新节点
SLTNode* BuySLTNode(SLTDataType x)
{SLTNode* newnode=(SLTNode*)malloc(sizeof(SLTNode));if(newnode==NULL) {printf("malloc fail\n");return NULL;}newnode->data=x;newnode->next=NULL;return newnode;
}
//--------------------------手动分割线-----------------------------
//尾插
void SLTPushBack(SLTNode** pphead,SLTDataType x)
{assert(pphead);SLTNode* newnode=BuySLTNode(x);if(*pphead==NULL){*pphead=newnode;}else{//找尾SLTNode* cur=*pphead;while(cur->next!=NULL){cur=cur->next;}cur->next=newnode;}
}
//--------------------------手动分割线-----------------------------
//前插
void SLTPushFront(SLTNode** pphead,SLTDataType x)
{assert(pphead);SLTNode* newnode=BuySLTNode(x);newnode->next=*pphead;*pphead=newnode;
}
//--------------------------手动分割线-----------------------------
//尾删
void SLTPopBack(SLTNode** pphead)
{// 暴力检查assert(pphead);assert(*pphead);SLTNode* cur=*pphead;if(*pphead->next==NULL){free(*pphead);*pphead=NULL;}else{SLTNode* cur=*pphead;while(cur->next->next!=NULL){cur=cur->next;}SLTNode* tmp=cur->next;free(tmp);cur->next=NULL;}
}
//--------------------------手动分割线-----------------------------
//前删
void SLTPopFront(SLTNode** pphead)
{assert(pphead);assert(*pphead);if(*pphead->next==NULL){free(*pphead);*pphead=NULL;}else{SLTNode* tmp=*pphead;free(tmp);tmp=NULL;*pphead=*pphead->next;}
}
//--------------------------手动分割线-----------------------------
//查找
SLTNode* SListFind(SLTNode* phead,SLTDataType x)
{SLTNode* cur=phead;while(cur){if(cur->data==x) return cur;cur=cur->next;}return NULL;
}
//--------------------------手动分割线-----------------------------
//任意位置插入
void SListInsert(SLTNode** pphead, SLTNode* pos, SLTDataType x)
{assert(pos);assert(pphead);SLTNode* newnode=BuySLTNode(x);if(*pphead==pos){SLTPushFront(pphead, x);}else{SLTNode* prev=*pphead;while(prev->next!=pos){prev=prev->next;}prev->next=newnode;newnode->next=pos;}
}
//--------------------------手动分割线-----------------------------
//删除某个节点
void SListErase(SLTNode** pphead, SLTNode* pos)
{assert(pphead);assert(pos);SLTNode* cur=*pphead;if(*pphead==pos){SLTPopFront(pphead);}else{while(cur->next!=pos){cur=cur->next;}cur->next=pos->next;free(pos);pos=NULL;}
}
//--------------------------手动分割线-----------------------------
//在后面插入一个节点
void SListInsertAfter(SLTNode* pos, SLTDataType x)
{assert(pos);SLTNode* newnode = BuySLTNode(x);newnode->next = pos->next;pos->next = newnode;
}
//--------------------------手动分割线-----------------------------
//删除pos后面这一个节点
void SListEraseAfter(SLTNode* pos)
{assert(pos);assert(pos->next);SLTNode* del = pos->next;pos->next = del->next;free(del);del = NULL;
}
//--------------------------手动分割线-----------------------------

代码实践Test.c

#include"SList.h"void TestSList1()
{SLTNode* plist = NULL;SLTPushBack(&plist, 1);SLTPushBack(&plist, 2);SLTPushBack(&plist, 3);SLTPushBack(&plist, 4);SLTPrint(plist);
}void TestSList2()
{SLTNode* plist = NULL;SLTPushFront(&plist, 1);SLTPushFront(&plist, 2);SLTPushFront(&plist, 3);SLTPushFront(&plist, 4);SLTPrint(plist);SLTPopBack(&plist);SLTPrint(plist);SLTPopBack(&plist);SLTPrint(plist);SLTPopBack(&plist);SLTPrint(plist);SLTPopBack(&plist);SLTPrint(plist);
}void TestSList3()
{SLTNode* plist = NULL;SLTPushBack(&plist, 1);SLTPushBack(&plist, 2);SLTPushBack(&plist, 3);SLTPushBack(&plist, 4);SLTPrint(plist);SLTPopFront(&plist);SLTPrint(plist);SLTPopFront(&plist);SLTPrint(plist);SLTPopFront(&plist);SLTPrint(plist);SLTPopFront(&plist);SLTPrint(plist);
}int main()
{TestSList3();return 0;
}

代码汇总

#include<stdio.h>
#include<stdlib.h>
#include<assert.h>typedef int SLTDataType;typedef struct SListNode
{SLTDataType data;struct SListNode* next;
}SLTNode;//--------------------------手动分割线---------------------------
//打印
void SLTPrint(SLTNode* phead)
{assert(phead);SLTNode* cur=phead;while(cur){printf("%d ",cur->data);cur=cur->next;}printf("NULL\n");
}
//--------------------------手动分割线-----------------------------
//创建新节点
SLTNode* BuySLTNode(SLTDataType x)
{SLTNode* newnode=(SLTNode*)malloc(sizeof(SLTNode));if(newnode==NULL) {printf("malloc fail\n");return NULL;}newnode->data=x;newnode->next=NULL;return newnode;
}
//--------------------------手动分割线-----------------------------
//尾插
void SLTPushBack(SLTNode** pphead,SLTDataType x)
{SLTNode* newnode=BuySLTNode(x);if(*pphead==NULL){*pphead=newnode;}else{//找尾SLTNode* cur=*pphead;while(cur->next!=NULL){cur=cur->next;}cur->next=newnode;}
}
//--------------------------手动分割线-----------------------------
//前插
void SLTPushFront(SLTNode** pphead,SLTDataType x)
{SLTNode* newnode=BuySLTNode(x);newnode->next=*pphead;*pphead=newnode;
}
//--------------------------手动分割线-----------------------------
//尾删
void SLTPopBack(SLTNode** pphead)
{//暴力检查assert(*pphead);SLTNode* cur=*pphead;if(*pphead->next==NULL){free(*pphead);*pphead=NULL;}else{SLTNode* cur=*pphead;while(cur->next->next!=NULL){cur=cur->next;}SLTNode* tmp=cur->next;free(tmp);cur->next=NULL;}
}
//--------------------------手动分割线-----------------------------
//前删
void SLTPopFront(SLTNode** pphead)
{assert(*pphead);if(*pphead->next==NULL){free(*pphead);*pphead=NULL;}else{SLTNode* tmp=*pphead;free(tmp);tmp=NULL;*pphead=*pphead->next;}
}
//--------------------------手动分割线-----------------------------
//查找
SLTNode* SListFind(SLTNode* phead,SLTDataType x)
{SLTNode* cur=phead;while(cur){if(cur->data==x) return cur;cur=cur->next;}return NULL;
}
//--------------------------手动分割线-----------------------------
//任意位置插入
void SListInsert(SLTNode** pphead, SLTNode* pos, SLTDataType x)
{SLTNode* newnode=BuySLTNode(x);if(*pphead==pos){SLTPushFront(pphead, x);}else{SLTNode* prev=*pphead;while(prev->next!=pos){prev=prev->next;}prev->next=newnode;newnode->next=pos;}
}
//--------------------------手动分割线-----------------------------
//删除某个节点
void SListErase(SLTNode** pphead, SLTNode* pos)
{SLTNode* cur=*pphead;if(*pphead==pos){SLTPopFront(pphead);}else{while(cur->next!=pos){cur=cur->next;}cur->next=pos->next;free(pos);pos=NULL;}
}
//--------------------------手动分割线-----------------------------
//在后面插入一个节点
void SListInsertAfter(SLTNode* pos, SLTDataType x)
{assert(pos);SLTNode* newnode = BuySLTNode(x);newnode->next = pos->next;pos->next = newnode;
}
//--------------------------手动分割线-----------------------------
//删除pos后面这一个节点
void SListEraseAfter(SLTNode* pos)
{assert(pos);assert(pos->next);SLTNode* del = pos->next;pos->next = del->next;free(del);del = NULL;
}
//--------------------------手动分割线-----------------------------void TestSList1()
{SLTNode* plist = NULL;SLTPushBack(&plist, 1);SLTPushBack(&plist, 2);SLTPushBack(&plist, 3);SLTPushBack(&plist, 4);SLTPrint(plist);
}void TestSList2()
{SLTNode* plist = NULL;SLTPushFront(&plist, 1);SLTPushFront(&plist, 2);SLTPushFront(&plist, 3);SLTPushFront(&plist, 4);SLTPrint(plist);SLTPopBack(&plist);SLTPrint(plist);SLTPopBack(&plist);SLTPrint(plist);SLTPopBack(&plist);SLTPrint(plist);SLTPopBack(&plist);SLTPrint(plist);
}void TestSList3()
{SLTNode* plist = NULL;SLTPushBack(&plist, 1);SLTPushBack(&plist, 2);SLTPushBack(&plist, 3);SLTPushBack(&plist, 4);SLTPrint(plist);SLTPopFront(&plist);SLTPrint(plist);SLTPopFront(&plist);SLTPrint(plist);SLTPopFront(&plist);SLTPrint(plist);SLTPopFront(&plist);SLTPrint(plist);
}int main()
{TestSList3();return 0;
}

总结

  今天学习了单链表的知识,初次写数据结构的知识,给我的感觉就是,学三遍不如手敲代码一遍来的实在,所以数据结构的学习我将多画图,多敲代码来学习,希望大家吸取经验和我一起学习数据结构,为后面打比赛刷题打下坚实基础。

  我是夏目浅石,希望和你一起学习进步,刷题无数!!!希望各位大佬能一键三连支持一下博主,hhhh~我们下期见喽
在这里插入图片描述
如果无聊的话,就来逛逛我的博客栈吧stack-frame.cn

原创不易,还希望各位大佬支持一下\textcolor{blue}{原创不易,还希望各位大佬支持一下}原创不易,还希望各位大佬支持一下

👍 点赞,你的认可是我创作的动力!\textcolor{9c81c1}{点赞,你的认可是我创作的动力!}点赞,你的认可是我创作的动力!

⭐️ 收藏,你的青睐是我努力的方向!\textcolor{ed7976}{收藏,你的青睐是我努力的方向!}收藏,你的青睐是我努力的方向!

✏️ 评论,你的意见是我进步的财富!\textcolor{98c091}{评论,你的意见是我进步的财富!}评论,你的意见是我进步的财富!

相关文章:

【数据结构】万字深入浅出讲解单链表(附原码 | 超详解)

&#x1f680;write in front&#x1f680; &#x1f4dd;个人主页&#xff1a;认真写博客的夏目浅石. &#x1f381;欢迎各位→点赞&#x1f44d; 收藏⭐️ 留言&#x1f4dd; &#x1f4e3;系列专栏&#xff1a;C语言实现数据结构 &#x1f4ac;总结&#xff1a;希望你看完…...

无线WiFi安全渗透与攻防(五)之aircrack-ng破解WEP加密

系列文章 无线WiFi安全渗透与攻防(一)之无线安全环境搭建 无线WiFi安全渗透与攻防(二)之打造专属字典 无线WiFi安全渗透与攻防(三)之Windows扫描wifi和破解WiFi密码 无线WiFi安全渗透与攻防(四)之kismet的使用 aircrack-ng破解WEP加密 1.WEP介绍 其实我们平常在使用wifi的时…...

MySQL中事务的相关问题

事务 一、事务的概述&#xff1a; 1、事务处理&#xff08;事务操作&#xff09;&#xff1a;保证所有事务都作为一个工作单元来执行&#xff0c;即使出现了故障&#xff0c;都不能改变这种执行方式。当在一个事务中执行多个操作时&#xff0c;要么所有的事务都被提交(commit…...

推荐算法再次踩坑记录

去年搞通了EasyRec这个玩意&#xff0c;没想到今年还要用推荐方面的东西&#xff0c;行吧&#xff0c;再来一次&#xff0c;再次踩坑试试。1、EasyRec训练测试数据下载&#xff1a;git clone后&#xff0c;进入EasyRec&#xff0c;然后执行&#xff1a;bash scripts/init.sh 将…...

STM32 (十五)MPU6050

简介前言一、MPU6050简介MPU6050是一款性价比很高的陀螺仪&#xff0c;可以读取X Y Z 三轴角度&#xff0c;X Y Z 三轴加速度&#xff0c;还有内置的温度传感器&#xff0c;在姿态解析方面应用非常广泛。下面是它在淘宝上的参数图产品尺寸产品参数产品原理图&#xff1a;二、硬…...

使用yarn,依赖报各种错误怎么办

使用 yarn^3.x 版本时&#xff0c;默认并不会安装包到 node_modules&#xff0c;因为 yarn3.x 是即插即用的&#xff0c;也就是说如果你下载过这个包&#xff0c;yarn只会生成一个 Png文件&#xff0c;然后将包的路径 link 到下载过的地方&#xff0c;这样可以省去很多时间。而…...

面试官:rem和vw有什么区别

"rem" 和 "vw"的区别 "rem" 和 "vw" 都是用于网页设计的CSS单位。 "rem" 是相对于根元素的字体大小来计算的单位&#xff0c;即相对于 "html" 标签的字体大小。例如&#xff0c;如果 "html" 标签的字…...

【GPT-4】GPT-4 相关内容总结

目录 ​编辑 官网介绍 GPT-4 内容提升总结 GPT-4 简短版总结 GPT-4 基础能力 GPT-4 图像处理 GPT-4 技术报告 训练过程 局限性 GPT-4 风险和应对措施 开源项目&#xff1a;OpenAI Evals 申请 GPT-4 API API的介绍以及获取 官网介绍 官网&#xff1a;GPT-4 API候…...

5.springcloud微服务架构搭建 之 《springboot集成Hystrix》

1.springcloud微服务架构搭建 之 《springboot自动装配Redis》 2.springcloud微服务架构搭建 之 《springboot集成nacos注册中心》 3.springcloud微服务架构搭建 之 《springboot自动装配ribbon》 4.springcloud微服务架构搭建 之 《springboot集成openFeign》 目录 1.项目…...

【工作中问题解决实践 七】SpringBoot集成Jackson进行对象序列化和反序列化

去年10月份以来由于公司和家里的事情太多&#xff0c;所以一直没有学习&#xff0c;最近缓过来了&#xff0c;学习的脚步不能停滞啊。回归正题&#xff0c;其实前年在学习springMvc的时候也学习过Jackson【Spring MVC学习笔记 五】SpringMVC框架整合Jackson工具&#xff0c;但是…...

香港服务器遭受DDoS攻击后如何恢复运行?

​  您是否发现流量异常上升?您的网站突然崩溃了吗?当您注意到这些迹象时&#xff0c;可能是在陷入了DDoS攻击的困境&#xff0c;因而&#xff0c;当开始考虑使用香港服务器时&#xff0c;也应该考虑香港服务器设备受DDoS攻击时&#xff0c;如何从中恢复。 在 DDoS 攻击香港…...

【Hive】配置

目录 Hive参数配置方式 参数的配置方式 1. 文件配置 2. 命令行参数配置 3. 参数声明配置 配置源数据库 配置元数据到MySQL 查看MySQL中的元数据 Hive服务部署 hiveserver2服务 介绍 部署 启动 远程连接 1. 使用命令行客户端beeline进行远程访问 metastore服务 …...

IP-GUARD如何强制管控电脑设置开机密码要符合密码复杂度?

如何强制管控电脑设置开机密码要符合密码复杂度? 7 可以在控制台-【策略】-【定制配置】,添加一条配置,开启系统密码复杂度检测。 类别:自定义 关键字:bp_password_complexity 内容:1 效果图:...

剑指 Offer II 031. 最近最少使用缓存

题目链接 剑指 Offer II 031. 最近最少使用缓存 mid 题目描述 运用所掌握的数据结构&#xff0c;设计和实现一个 LRU(Least Recently Used&#xff0c;最近最少使用) 缓存机制 。 实现 LRUCache类&#xff1a; LRUCache(int capacity)以正整数作为容量 capacity初始化 LRU缓…...

44岁了,我从没想过在CSDN创作2年,会有这么大收获

1998年上的大学&#xff0c;02年毕业&#xff0c;就算从工作算起&#xff0c;我也有20余年的码龄生涯了。 但正式开启博文的写作&#xff0c;却是2021年开始的&#xff0c;差不多也就写了2年的博客&#xff0c;今天我来说说我在CSDN的感受和收获。 我是真的没想到&#xff0c;…...

相位相参信号源的设计--示波器上的信号不稳定,来回跑?

目录乱跑的波形边沿触发触发方式外部触发相参与非相参相位相参的射频信号源样机外观与内部设计软件设计上位机软件信号源使用方法PWM触发信号射频信号的时域波形射频信号的频谱输出功率在示波器的实际使用当中波形在示波器的时域上乱跑&#xff0c;左右移动&#xff0c;定不下来…...

Spring Boot 整合 RabbitMQ 多种消息模式

Spring Boot 整合 RabbitMQ 多种消息模式 准备工作集成 RabbitMQ发布/订阅模式点对点模式主题模式总结Spring Boot 是一个流行的 Java 应用程序开发框架,而 RabbitMQ 是一款可靠的消息队列软件。将 Spring Boot 和 RabbitMQ 结合起来可以帮助我们轻松地实现异步消息传递。Rabb…...

node多版本控制

前言 最近在折腾Python&#xff0c;并将node升级至v18.14.2。突然发现一个旧项目无法运行&#xff0c;也无法打包&#xff0c;里面的node-sass报错&#xff0c;显然这是因为node版本过高导致的。 将node版本降低至以前的v14.16.0&#xff0c;果然立马就能正常运行。 存在不同…...

Redis set集合

Redis set &#xff08;集合&#xff09;遵循无序排列的规则&#xff0c;集合中的每一个成员&#xff08;也就是元素&#xff0c;叫法不同而已&#xff09;都是字符串类型&#xff0c;并且不可重复。Redis set 是通过哈希映射表实现的&#xff0c;所以它的添加、删除、查找操作…...

漫画:什么是希尔排序算法?

希尔排序&#xff08;ShellSort&#xff09;是以它的发明者Donald Shell名字命名的&#xff0c;希尔排序是插入排序的改进版&#xff0c;实现简单&#xff0c;对于中等规模数据的性能表现还不错 一、排序思想 前情回顾&#xff1a;漫画&#xff1a;什么是插入排序算法&#xf…...

Lombok 的 @Data 注解失效,未生成 getter/setter 方法引发的HTTP 406 错误

HTTP 状态码 406 (Not Acceptable) 和 500 (Internal Server Error) 是两类完全不同的错误&#xff0c;它们的含义、原因和解决方法都有显著区别。以下是详细对比&#xff1a; 1. HTTP 406 (Not Acceptable) 含义&#xff1a; 客户端请求的内容类型与服务器支持的内容类型不匹…...

IGP(Interior Gateway Protocol,内部网关协议)

IGP&#xff08;Interior Gateway Protocol&#xff0c;内部网关协议&#xff09; 是一种用于在一个自治系统&#xff08;AS&#xff09;内部传递路由信息的路由协议&#xff0c;主要用于在一个组织或机构的内部网络中决定数据包的最佳路径。与用于自治系统之间通信的 EGP&…...

el-switch文字内置

el-switch文字内置 效果 vue <div style"color:#ffffff;font-size:14px;float:left;margin-bottom:5px;margin-right:5px;">自动加载</div> <el-switch v-model"value" active-color"#3E99FB" inactive-color"#DCDFE6"…...

什么是EULA和DPA

文章目录 EULA&#xff08;End User License Agreement&#xff09;DPA&#xff08;Data Protection Agreement&#xff09;一、定义与背景二、核心内容三、法律效力与责任四、实际应用与意义 EULA&#xff08;End User License Agreement&#xff09; 定义&#xff1a; EULA即…...

ElasticSearch搜索引擎之倒排索引及其底层算法

文章目录 一、搜索引擎1、什么是搜索引擎?2、搜索引擎的分类3、常用的搜索引擎4、搜索引擎的特点二、倒排索引1、简介2、为什么倒排索引不用B+树1.创建时间长,文件大。2.其次,树深,IO次数可怕。3.索引可能会失效。4.精准度差。三. 倒排索引四、算法1、Term Index的算法2、 …...

Ascend NPU上适配Step-Audio模型

1 概述 1.1 简述 Step-Audio 是业界首个集语音理解与生成控制一体化的产品级开源实时语音对话系统&#xff0c;支持多语言对话&#xff08;如 中文&#xff0c;英文&#xff0c;日语&#xff09;&#xff0c;语音情感&#xff08;如 开心&#xff0c;悲伤&#xff09;&#x…...

MySQL账号权限管理指南:安全创建账户与精细授权技巧

在MySQL数据库管理中&#xff0c;合理创建用户账号并分配精确权限是保障数据安全的核心环节。直接使用root账号进行所有操作不仅危险且难以审计操作行为。今天我们来全面解析MySQL账号创建与权限分配的专业方法。 一、为何需要创建独立账号&#xff1f; 最小权限原则&#xf…...

重启Eureka集群中的节点,对已经注册的服务有什么影响

先看答案&#xff0c;如果正确地操作&#xff0c;重启Eureka集群中的节点&#xff0c;对已经注册的服务影响非常小&#xff0c;甚至可以做到无感知。 但如果操作不当&#xff0c;可能会引发短暂的服务发现问题。 下面我们从Eureka的核心工作原理来详细分析这个问题。 Eureka的…...

CVE-2020-17519源码分析与漏洞复现(Flink 任意文件读取)

漏洞概览 漏洞名称&#xff1a;Apache Flink REST API 任意文件读取漏洞CVE编号&#xff1a;CVE-2020-17519CVSS评分&#xff1a;7.5影响版本&#xff1a;Apache Flink 1.11.0、1.11.1、1.11.2修复版本&#xff1a;≥ 1.11.3 或 ≥ 1.12.0漏洞类型&#xff1a;路径遍历&#x…...

基于Java+MySQL实现(GUI)客户管理系统

客户资料管理系统的设计与实现 第一章 需求分析 1.1 需求总体介绍 本项目为了方便维护客户信息为了方便维护客户信息&#xff0c;对客户进行统一管理&#xff0c;可以把所有客户信息录入系统&#xff0c;进行维护和统计功能。可通过文件的方式保存相关录入数据&#xff0c;对…...