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

【数据结构】单链表的接口实现(附图解和源码)

单链表的接口实现(附图解和源码)


文章目录

  • 单链表的接口实现(附图解和源码)
  • 前言
  • 一、定义结构体
  • 二、接口实现(附图解+源码)
    • 1.开辟新空间
    • 2.头插数据
    • 3.头删数据
    • 4.打印整个单链表
    • 5.尾删数据
    • 6.查找单链表中的数据
    • 7.在pos位置之前插入一个节点
    • 8.在pos位置之后插入一个节点
    • 9.删除pos节点
    • 10.删除pos的下一个节点
    • 11.销毁单链表
  • 三、源代码展示
    • 1.test.c(测试+主函数)
    • 2.Slist.h(接口函数的声明)
    • 3.Slist.c(接口函数的实现)
  • 总结


前言

本文主要介绍单链表中增删查改等接口实现,结尾附总源码


一、定义结构体

在这里插入图片描述

代码如下(示例):

typedef int SLTDataType;
typedef struct SListNode
{SLTDataType data;struct SListNode* next;
}SLTNode;

二、接口实现(附图解+源码)

在这里插入图片描述
这里一共11个接口,我会我都会一 一为大家讲解(图解+源码


1.开辟新空间

(1)开辟一个链表类型的动态空间,将地址赋给指针newnode;
(2)将值放入newnode的data数据内;
(3)将新成员的next指针置为空指针,因为这个成员将成为链表的最后一个成员
注意:1.将malloc开辟空间存到newnode里面时,参数为结构体所占的字节大小!2.对newnode进行NULL判断!

代码如下(示例):

SLTNode* BuyListNode(SLTDataType x)//开辟新空间
{SLTNode* newnode = (SLTNode*)malloc(sizeof(SLTNode));//开辟一个链表类型的动态空间 将地址赋给指着newnodeif (newnode == NULL){printf("malloc fail\n");exit(-1);}newnode->data = x;//将值放入newnode的data数据内newnode->next = NULL;//将新成员的next指针 置为空指针 因为这个成员将称为链表的最后一个成员
}

2.头插数据

注意:头插接口传参的时候一定要传二级指针变量,如果传一级指针就不会实现效果,如下图
在这里插入图片描述


代码如下(示例):

void SListPushFront(SLTNode** pphead, SLTDataType x)
{assert(pphead);SLTNode* newnode = BuyListNode(x);newnode->next = *pphead;*pphead = newnode;
}

3.头删数据

头删数据注意:当单链表为空指针NULL时,头删时会对空指针进行解引用,会造成err,所以要进行两步assert断言!在这里插入图片描述


图解实现:这里传参也需要传二级指针!
在这里插入图片描述


代码如下(示例):

void SListPopFront(SLTNode** pphead)
{assert(pphead);assert(*pphead != NULL);SLTNode* next = (*pphead)->next;free(*pphead);*pphead = next;
}

4.打印整个单链表

注意:这里传参用一级指针即可,因为不需要对结构体进行修改访问!
在这里插入图片描述


代码如下(示例):

void SListPrint(SLTNode* phead)
{SLTNode* cur = phead;while (cur != NULL){printf("%d->", cur->data);cur = cur->next;}printf("NULL\n");
}

5.尾删数据

注意:分为两种情况 1.只有一个链表;2.存在两个及以上链表!

只有一个链表 :如下(示例):

if ((*pphead)->next == NULL)//如果第一个链表的next指针存放的是空指针 说明只有一个链表{free(*pphead);//将唯一一个链表的动态内存释放*pphead = NULL;//将指针置为空指针}

在这里插入图片描述


两个或两个以上链表 : 如下(示例):
第一种情况 : 定义两个指针情况

//定义2个指针方法SLTNode* tail = *pphead;//寻找当前需要被释放的地址 所创建的变量SLTNode* prev = *pphead;//删除最后一个链表数据后,所保留的最后一个链表的地址。while (tail->next != NULL){prev = tail;tail = tail->next;}//当循环停下来时 prev指针指向的是 tail前面的一个链表  而此时tail->next 指针指向的地址是NULLfree(tail);//释放最后一个链表对应的动态内存tail = NULL;//将最后一个链表指针置为空指针prev->next = NULL;//尾删最重要的是记得要把被删除链表的前一个链表的next指针存放地址置为空指针,避免野指针的情况。

在这里插入图片描述


两个或两个以上链表 : 如下(示例):
第二种情况 : 定义一个指针情况

//定义一个指针方法
//来到这说明至少有两个链表SLTNode* tail = *pphead;//将链表地址交给tail指针while (tail->next->next)//当tail指向的地址的地址不是空指针则继续循环{tail = tail->next;//在循环中tail拿到下一个tail的next指针地址}free(tail->next);//tail指向的next地址的动态空间被释放tail->next = NULL;//tail指向的next指针被置为空指针

在这里插入图片描述


6.查找单链表中的数据

单链表中查找数据和顺序表里面的查找顺序非常相似,这里不做过多介绍,如果找不到返回NULL

代码如下(示例):

SLTNode* SListFind(SLTNode* phead, SLTDataType x)
{SLTNode* cur = phead;while (cur){if (cur->data == x){return cur;}else{cur = cur->next;}}return NULL;
}

7.在pos位置之前插入一个节点

第一种情况(pos就是*pphead)代码如下(示例):

if (*pphead == pos){newnode->next = *pphead;*pphead = newnode;}

在这里插入图片描述


第二种情况(pos 不是*pphead)代码如下(示例):

else
{//找到pos前一个链表地址SLTNode* posPrev = *pphead;while (posPrev->next != pos){posPrev = posPrev->next;}posPrev->next = newnode;newnode->next = pos;
}

在这里插入图片描述


8.在pos位置之后插入一个节点

在这里插入图片描述


代码如下(示例):

void SListInserAfter(SLTNode* pos, SLTDataType x)
{assert(pos);SLTNode* newnode = BuyListNode(x);newnode->next = pos->next;pos->next = newnode;
}

9.删除pos节点

注意:这里分为两种情况:1.pos==*pphead;2.pos 不等于 * pphead

第一种情况 pos==*pphead,这里相等于头删

if (*pphead == pos){//头删*pphead = pos->next;free(pos);}

在这里插入图片描述


第二种情况 pos 不等于 *pphead :

else
{//找前一个SLTNode* prev = *pphead;while (prev->next != pos){prev = prev->next;}prev->next = pos->next;free(pos);pos = NULL;
}

在这里插入图片描述


10.删除pos的下一个节点

注意:如果链表为空,则不能删除,否则会对空指针进行访问!所以也需要进行两步assert断言
在这里插入图片描述

代码如下(示例):

void SListEraseAfter(SLTNode* pos)
{assert(pos);assert(pos->next);SLTNode* next = pos->next;pos->next = next->next;free(next);next = NULL;
}

在这里插入图片描述


11.销毁单链表

很多人都是用free直接销毁,这样会导致内存泄漏问题(因为单链表不是连续存放的),如下图所示
在这里插入图片描述


代码如下(示例):

void SListDestroy(SLTNode** pphead)
{assert(pphead);while (*pphead){SLTNode* tmp = (*pphead)->next;free(*pphead);*pphead = tmp;}*pphead = NULL;
}

在这里插入图片描述


三、源代码展示

1.test.c(测试+主函数)

代码如下(示例):

#include "Slist.h"
void TestSList1()
{SLTNode* plist = NULL;SListPushBack(&plist, 1);//尾插SListPushBack(&plist, 2);//尾插SListPushBack(&plist, 3);//尾插SListPushBack(&plist, 4);//尾插SListPushFront(&plist, 5);//头插SListPopFront(&plist);//头删SListPopBack(&plist);//尾删SListPopBack(&plist);//尾删SListPopBack(&plist);//尾删SListPopBack(&plist);//尾删SListPopFront(&plist);//头删SListPrint(plist);//打印
}void TestSList2()
{SLTNode* plist = NULL;SListPushBack(&plist, 1);//尾插SListPushBack(&plist, 2);//尾插SListPushBack(&plist, 1);//尾插SListPushBack(&plist, 3);//尾插SListPushBack(&plist, 4);//尾插SListPushBack(&plist, 1);//尾插SListPushFront(&plist, 5);//头插SListPopFront(&plist);//头删SListPrint(plist);//打印
}
void TestSList3()
{SLTNode* plist = NULL;SListPushBack(&plist, 1);//尾插SListPushBack(&plist, 2);//尾插SListPushBack(&plist, 1);//尾插SListPushBack(&plist, 3);//尾插SListPushBack(&plist, 4);//尾插SListPushBack(&plist, 1);//尾插SListPushFront(&plist, 5);//头插SLTNode* pos = SListFind(plist, 1);int i = 1;while (pos){printf("第%d个pos节点:%p->%d\n", i++, pos, pos->data);pos = SListFind(pos->next, 1);}pos = SListFind(plist, 4);if (pos){pos->data = 30;}SListPrint(plist);
}void TestSList4()
{SLTNode* plist = NULL;SListPushBack(&plist, 2);//尾插SListPushBack(&plist, 3);//尾插SListPushBack(&plist, 4);//尾插SListPushBack(&plist, 5);//尾插SListPushBack(&plist, 6);//尾插SListPushFront(&plist, 1);//头插//SLTNode* pos = SListFind(plist, 6);//SListInserAfter(pos, 1);//SListInsert(&plist, pos, 7);//SListErase(&plist, pos);SListDestroy(&plist);SListPrint(plist);
}
int main()
{//TestSList1();//TestSList2();//TestSList3();TestSList4();return 0;
}

2.Slist.h(接口函数的声明)

代码如下(示例):

#pragma onc
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
typedef int SLTDataType;
typedef struct SListNode
{SLTDataType data;struct SListNode* next;
}SLTNode;void SListPrint(SLTNode* phead);//打印
void SListPushBack(SLTNode** pphead, SLTDataType x);//尾插
void SListPushFront(SLTNode** pphead, SLTDataType x);//头插
void SListPopBack(SLTNode** pphead);//尾删
void SListPopFront(SLTNode** pphead);//头删
SLTNode* SListFind(SLTNode* phead, SLTDataType x);//找数据
//在pos位置前插入一个节点
void SListInsert(SLTNode** pphead, SLTNode* pos, SLTDataType x);
//在pos位置之后去插入一个节点
void SListInserAfter(SLTNode* pos, SLTDataType x);
void SListErase(SLTNode** pphead, SLTNode* pos);//删除pos节点
void SListEraseAfter(SLTNode* pos);//删除pos的下一个节点
void SListDestroy(SLTNode** pphead);

3.Slist.c(接口函数的实现)

代码如下(示例):

#include "Slist.h"
SLTNode* BuyListNode(SLTDataType x)//开辟新空间
{SLTNode* newnode = (SLTNode*)malloc(sizeof(SLTNode));//开辟一个链表类型的动态空间 将地址赋给指着newnodeif (newnode == NULL){printf("malloc fail\n");exit(-1);}newnode->data = x;//将值放入newnode的data数据内newnode->next = NULL;//将新成员的next指针 置为空指针 因为这个成员将称为链表的最后一个成员
}
void SListPrint(SLTNode* phead)
{SLTNode* cur = phead;while (cur != NULL){printf("%d->", cur->data);cur = cur->next;}printf("NULL\n");
}
void SListPushBack(SLTNode** pphead, SLTDataType x)
{assert(pphead);SLTNode* newnode = BuyListNode(x);if (*pphead == NULL){*pphead = newnode;//如果*pphead是空指针 将 newnode的地址给与 *pphead 称为链表的第一个成员}else{//如果链表已经不是空的了 *pphead那么肯定也不是NULL空指针则进入这里SLTNode* tail = *pphead;//用一个tail指针 接收链表地址while (tail->next != NULL)//while寻找链表的最后成员{tail = tail->next;//循环直至找到最后一个链表的成员}tail->next = newnode;//最后一个成员取得新链表成员地址}
}
void SListPushFront(SLTNode** pphead, SLTDataType x)
{assert(pphead);SLTNode* newnode = BuyListNode(x);newnode->next = *pphead;*pphead = newnode;
}
void SListPopBack(SLTNode** pphead)
{assert(pphead);assert(*pphead != NULL);//仿C++处理错误的方式//来到这说明至少有一个链表  或 两个以上链表if ((*pphead)->next == NULL)//如果第一个链表的next指针存放的是空指针 说明只有一个链表{free(*pphead);//将唯一一个链表的动态内存释放*pphead = NULL;//将指针置为空指针}else{//定义2个指针方法SLTNode* tail = *pphead;//寻找当前需要被释放的地址 所创建的变量SLTNode* prev = *pphead;//删除最后一个链表数据后,所保留的最后一个链表的地址。while (tail->next != NULL){prev = tail;tail = tail->next;}//当循环停下来时 prev指针指向的是 tail前面的一个链表  而此时tail->next 指针指向的地址是NULLfree(tail);//释放最后一个链表对应的动态内存tail = NULL;//将最后一个链表指针置为空指针prev->next = NULL;//尾删最重要的是记得要把被删除链表的前一个链表的next指针存放地址置为空指针,避免野指针的情况。//定义一个指针方法//来到这说明至少有两个链表//SLTNode* tail = *pphead;//将链表地址交给tail指针//while (tail->next->next)//当tail指向的地址的地址不是空指针则继续循环//{//	tail = tail->next;//在循环中tail拿到下一个tail的next指针地址//}//free(tail->next);//tail指向的next地址的动态空间被释放//tail->next = NULL;//tail指向的next指针被置为空指针}
}
void SListPopFront(SLTNode** pphead)
{assert(pphead);assert(*pphead != NULL);SLTNode* next = (*pphead)->next;free(*pphead);*pphead = next;
}
SLTNode* SListFind(SLTNode* phead, SLTDataType x)
{SLTNode* cur = phead;while (cur){if (cur->data == x){return cur;}else{cur = cur->next;}}return NULL;
}
void SListInsert(SLTNode** pphead, SLTNode* pos, SLTDataType x)
{assert(pphead);SLTNode* newnode = BuyListNode(x);if (*pphead == pos){newnode->next = *pphead;*pphead = newnode;}else{//找到pos前一个链表地址SLTNode* posPrev = *pphead;while (posPrev->next != pos){posPrev = posPrev->next;}posPrev->next = newnode;newnode->next = pos;}
}
//自己写的
void SListInserAfter(SLTNode* pos, SLTDataType x)
{assert(pos);SLTNode* newnode = BuyListNode(x);newnode->next = pos->next;pos->next = newnode;
}
void SListErase(SLTNode** pphead, SLTNode* pos)
{assert(pos);if (*pphead == pos){//头删*pphead = pos->next;free(pos);}else{//找前一个SLTNode* prev = *pphead;while (prev->next != pos){prev = prev->next;}prev->next = pos->next;free(pos);pos = NULL;}
}
void SListEraseAfter(SLTNode* pos)
{assert(pos);assert(pos->next);SLTNode* next = pos->next;pos->next = next->next;free(next);next = NULL;
}
void SListDestroy(SLTNode** pphead)
{assert(pphead);while (*pphead){SLTNode* tmp = (*pphead)->next;free(*pphead);*pphead = tmp;}*pphead = NULL;
}

总结

以上就是今天要讲的内容,本文介绍了单链表11种接口的模拟实现的图解+源代码
如果我的博客对你有所帮助记得三连支持一下,感谢大家的支持!

在这里插入图片描述

相关文章:

【数据结构】单链表的接口实现(附图解和源码)

单链表的接口实现&#xff08;附图解和源码&#xff09; 文章目录单链表的接口实现&#xff08;附图解和源码&#xff09;前言一、定义结构体二、接口实现&#xff08;附图解源码&#xff09;1.开辟新空间2.头插数据3.头删数据4.打印整个单链表5.尾删数据6.查找单链表中的数据7…...

TikTok话题量超30亿,这款承载美好记忆的剪贴簿引发讨论

回忆风剪贴簿在TikTok引起关注小超在浏览超店有数后台时发现&#xff0c;有一款平平无奇的剪贴簿的种草视频爆火&#xff0c;在24h内收获了9.9K点赞&#xff0c;播放量更是突破了100W&#xff0c;直接冲到了【种草视频飙升榜】第六名的位置&#xff0c;并且这个数字目前仍在继续…...

了解Dubbo

1.注册中心挂了&#xff0c;消费者还能不能调用生产者&#xff1f; 注册中心挂了&#xff0c; 消费者依然可以调用生产者。生产者和消费者都会在本地缓存注册中心的服务列表&#xff0c;当注册中心宕机时&#xff0c;消费者会读取本地的缓存数据&#xff0c;直接访问生产者&am…...

2023年前端面试知识点总结(JavaScript篇)

近期整理了一下高频的前端面试题&#xff0c;分享给大家一起来学习。如有问题&#xff0c;欢迎指正&#xff01; 1. JavaScript有哪些数据类型 总共有8种数据类型&#xff0c;分别是Undefined、Null、Boolean、Number、String、Object、Symbol、BigInt Null 代表的含义是空对象…...

jQuery

文章目录jQuery 介绍初体验核心函数jQuery 对象和 dom 对象区分什么是 jQuery 对象&#xff0c;什么是 dom 对象问题&#xff1a;jQuery 对象的本质是什么&#xff1f;jQuery 对象和 Dom 对象使用区别Dom 对象和 jQuery 对象互转&#xff08;重点&#xff09;jQuery 选择器&…...

强化学习基础概念

强化学习入门 入门学习第一周&#xff1a;基础概念 经验回放&#xff1a; 将sss,agent当前步的action环与境的交互rrr以及下一步的状态st1s_{t1}st1​组成的四元组[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-wxhVd0dn-1676710992983)(null)] 组…...

Redis学习【9】之Redis RDB持久化

文章目录一 AOF(Append Only File) 持久化二 AOF 基础配置2.1 AOF的开启2.2 文件名配置2.3 混合式持久化开启2.4 AOF 文件目录配置三 AOF 文件格式3.1 Redis 协议3.2 查看 AOF 文件3.3 清单文件3.4 Rewrite 机制3.4.1 rewrite简介3.4.2 rewrite 计算策略3.4.3 手动开启 rewrite…...

分析 vant4 源码,学会用 vue3 + ts 开发毫秒级渲染的倒计时组件,真是妙啊

2022年11月23日首发于掘金&#xff0c;现在同步到公众号。11. 前言大家好&#xff0c;我是若川。推荐点右上方蓝字若川视野把我的公众号设为星标。我倾力持续组织了一年多源码共读&#xff0c;感兴趣的可以加我微信 lxchuan12 参与。另外&#xff0c;想学源码&#xff0c;极力推…...

事件驱动型架构

事件驱动型架构是一种软件设计模式&#xff0c;其中微服务会对状态变化&#xff08;称为“事件”&#xff09;作出反应。事件可以携带状态&#xff08;例如商品价格或收货地址&#xff09;&#xff0c;或者事件也可以是标识符&#xff08;例如&#xff0c;订单送达或发货通知&a…...

20222023华为OD机试 - 不含 101 的数(Python)

不含 101 的数 题目 小明在学习二进制时,发现了一类不含 101 的数, 也就是将数字用二进制表示,不能出现 101 。 现在给定一个正整数区间 [l,r],请问这个区间内包含了多少个不含 101 的数? 输入 输入一行,包含两个正整数 l l l, r r r...

杭州电子科技大学2023年MBA招生考试成绩查询和复查申请的通知

根据往年的情况&#xff0c;2023杭州电子大学MBA考试初试成绩可能将于2月21日公布&#xff0c;最早于20号出来&#xff0c;为了广大考生可以及时查询到自己的分数&#xff0c;杭州达立易考教育为大家汇总了信息。根据教育部和浙江省教育考试院关于硕士研究生招生考试工作的统一…...

电子技术——CS和CE放大器的高频响应

电子技术——CS和CE放大器的高频响应 在绘制出MOS和BJT的高频响应模型之后&#xff0c;我们对MOS和BJT的高频响应有了进一步的认识。现在我们想知道的是在高频响应中 fHf_HfH​ 的关系。 高频响应分析对电容耦合还是直接耦合都是适用的&#xff0c;因为在电容耦合中高频模式下…...

2023年数学建模美赛D题(Prioritizing the UN Sustainability Goals):SDGs 优先事项的选择

正在写&#xff0c;不断更新&#xff0c;别着急。。。 4. SDGs 优先事项的选择 4.1 基于SDG密度分布图选择优先事项 虽然每个可持续发展目标的接近度矩阵和中心性度量的结果是通用的&#xff0c;并创建了基本的可持续发展目标网络&#xff0c;但由于各国在网络的不同部分取得…...

springboot实现项目启动前的一些操作

在服务启动时&#xff0c;做一些操作&#xff0c;比如加载配置&#xff0c;初始化数据&#xff0c;请求其他服务的接口等。 有三种方法&#xff1a; 第一种是实现CommandLineRunner接口 第二种是实现ApplicationRunner接口 第三种是使用注解&#xff1a;PostConstruct 三者使用…...

详解JavaScript的形参,实参以及传参

文章目录 前言一、参数是什么&#xff1f;二、形参和实参 1.形参 2.实参三、传参 1.参数传递的对应关系2.两个传参的例子 总结前言 编程初学者在接触JavaScript这门语言时&#xff0c;很难搞懂里面的逻辑&#xff0c;这就会导致入门慢&#xff0c;入门难。这种难度一般…...

Vue中的diff算法

diff算法介绍 diff算法是一种高效对比算法。diff算法在组件更新即响应式数据监控到数据的改变&#xff0c;重新生成虚拟DOM树的时候调用&#xff0c;然后通过diff算法计算出前后虚拟dom树的差异点&#xff0c;更新dom时只更新变化的部分。 直接比较和修改两个数的复杂度为什么…...

【面试题】前端春招第二面

不容错过的一些面试题小细节&#xff0c;话不多说&#xff0c;直接看题~大厂面试题分享 面试题库后端面试题库 &#xff08;面试必备&#xff09; 推荐&#xff1a;★★★★★地址&#xff1a;前端面试题库HTML/CSS/Javascript/ES篇&#xff08;1&#xff09;标准盒模型和怪异盒…...

Pytorch 基础之张量数据类型

学习之前&#xff1a;先了解 Tensor&#xff08;张量&#xff09; 官方文档的解释是&#xff1a; 张量如同数组和矩阵一样, 是一种特殊的数据结构。在PyTorch中, 神经网络的输入、输出以及网络的参数等数据, 都是使用张量来进行描述。 说白了就是一种数据结构 基本数据类型…...

Java 基础面试题——常见类

目录1.String 为什么是不可变的&#xff1f;2.字符串拼接用“” 和 StringBuilder 有什么区别?3.String、StringBuffer 和 StringBuilder 的区别是什么?4.String 中的 equals() 和 Object 中的 equals() 有何区别&#xff1f;5.Object 类有哪些常用的方法&#xff1f;6.如何获…...

Windows 系统从零配置 Python 环境,安装CUDA、CUDNN、PyTorch 详细教程

文章目录1 配置 python 环境1.1 安装 Anaconda1.2 检查环境安装成功1.3 创建虚拟环境1.4 进入/退出 刚刚创建的环境1.5 其它操作1.5.1 查看电脑上所有已创建的环境1.5.2 删除已创建的环境2 安装 CUDA 和 CUDNN2.1 查看自己电脑支持的 CUDA 版本2.2 安装 CUDA2.3 安装 CUDNN2.4 …...

接口测试中缓存处理策略

在接口测试中&#xff0c;缓存处理策略是一个关键环节&#xff0c;直接影响测试结果的准确性和可靠性。合理的缓存处理策略能够确保测试环境的一致性&#xff0c;避免因缓存数据导致的测试偏差。以下是接口测试中常见的缓存处理策略及其详细说明&#xff1a; 一、缓存处理的核…...

Mybatis逆向工程,动态创建实体类、条件扩展类、Mapper接口、Mapper.xml映射文件

今天呢&#xff0c;博主的学习进度也是步入了Java Mybatis 框架&#xff0c;目前正在逐步杨帆旗航。 那么接下来就给大家出一期有关 Mybatis 逆向工程的教学&#xff0c;希望能对大家有所帮助&#xff0c;也特别欢迎大家指点不足之处&#xff0c;小生很乐意接受正确的建议&…...

质量体系的重要

质量体系是为确保产品、服务或过程质量满足规定要求&#xff0c;由相互关联的要素构成的有机整体。其核心内容可归纳为以下五个方面&#xff1a; &#x1f3db;️ 一、组织架构与职责 质量体系明确组织内各部门、岗位的职责与权限&#xff0c;形成层级清晰的管理网络&#xf…...

江苏艾立泰跨国资源接力:废料变黄金的绿色供应链革命

在华东塑料包装行业面临限塑令深度调整的背景下&#xff0c;江苏艾立泰以一场跨国资源接力的创新实践&#xff0c;重新定义了绿色供应链的边界。 跨国回收网络&#xff1a;废料变黄金的全球棋局 艾立泰在欧洲、东南亚建立再生塑料回收点&#xff0c;将海外废弃包装箱通过标准…...

Neo4j 集群管理:原理、技术与最佳实践深度解析

Neo4j 的集群技术是其企业级高可用性、可扩展性和容错能力的核心。通过深入分析官方文档,本文将系统阐述其集群管理的核心原理、关键技术、实用技巧和行业最佳实践。 Neo4j 的 Causal Clustering 架构提供了一个强大而灵活的基石,用于构建高可用、可扩展且一致的图数据库服务…...

PL0语法,分析器实现!

简介 PL/0 是一种简单的编程语言,通常用于教学编译原理。它的语法结构清晰,功能包括常量定义、变量声明、过程(子程序)定义以及基本的控制结构(如条件语句和循环语句)。 PL/0 语法规范 PL/0 是一种教学用的小型编程语言,由 Niklaus Wirth 设计,用于展示编译原理的核…...

苹果AI眼镜:从“工具”到“社交姿态”的范式革命——重新定义AI交互入口的未来机会

在2025年的AI硬件浪潮中,苹果AI眼镜(Apple Glasses)正在引发一场关于“人机交互形态”的深度思考。它并非简单地替代AirPods或Apple Watch,而是开辟了一个全新的、日常可接受的AI入口。其核心价值不在于功能的堆叠,而在于如何通过形态设计打破社交壁垒,成为用户“全天佩戴…...

Selenium 查找页面元素的方式

Selenium 查找页面元素的方式 Selenium 提供了多种方法来查找网页中的元素&#xff0c;以下是主要的定位方式&#xff1a; 基本定位方式 通过ID定位 driver.find_element(By.ID, "element_id")通过Name定位 driver.find_element(By.NAME, "element_name"…...

信息收集:从图像元数据(隐藏信息收集)到用户身份的揭秘 --- 7000

目录 &#x1f310; 访问Web服务 &#x1f4bb; 分析源代码 ⬇️ 下载图片并保留元数据 &#x1f50d; 提取元数据&#xff08;重点&#xff09; &#x1f464; 生成用户名列表 &#x1f6e0;️ 技术原理 图片元数据&#xff08;EXIF 数据&#xff09; Username-Anarch…...

2025-06-08-深度学习网络介绍(语义分割,实例分割,目标检测)

深度学习网络介绍(语义分割,实例分割,目标检测) 前言 在开始这篇文章之前&#xff0c;我们得首先弄明白&#xff0c;什么是图像分割&#xff1f; 我们知道一个图像只不过是许多像素的集合。图像分割分类是对图像中属于特定类别的像素进行分类的过程&#xff0c;即像素级别的…...