数据结构——单链表专题

前言

本篇我们继续来介绍数据结构的知识——链表,这与顺序表是一个类别的知识,同样也非常重要,所以大家需要掌握好链表的内容,这对我们后面数据结构的学习也很重要,如果你对本篇的内容感兴趣,希望大佬可以一键三连,多多支持;下面进入正文部分。

1. 链表的概念

这里大家首先要明确线性表的概念,线性表是具有相同特性的一类数据的集合,它在逻辑结构上一定是线性的,而在物理结构上不一定连续;前面我已经学过一类线性表——顺序表,我们知道顺序表在物理结构和逻辑结构上都是线性的;而今天我们所说的链表在物理结构上是非线性的。

链表是一种在物理结构上非线性非连续的存储结构,由一个个节点组成。

大家仔细来看上面的图,观察节点是由什么组成的,很明显大家可以发现节点是由存储的数据和指向下一个节点的指针组成的。

这里大家可能发现了它们之间的关系了,我们定义链表实际上就是在定义链表节点的结构,那么下面我们就要来讨论节点的定义方法了。

这里大家可以看到,我们声明了一个结构体,结构体中的内容就是前面我们所说的节点的组成元素,包括节点自身存储的数据,以及指向下一个节点的指针(这是一个结构体指针),因为下一个节点依然是一个结构体。

2. 链表的实现

上面铺垫了关于链表的基础,下面我们来实现一下链表;

首先我们要在VS中创建一个项目,来表示链表项目;其次,根据前面我们介绍顺序表的逻辑,我们要创建链表头文件和实现文件,以及测试文件。

这里我们就创建好了 

2.1 链表的打印

首先我们要在头文件中进行声明;

void SLTPrint(SLTNode* phead);

在实现打印方法之前。我们要先在test.c文件中创建好一个链表;

void SListTest01()
{//创建好了4个节点SLTNode* node1 =(SLTNode*)malloc(sizeof(SLTNode));node1->data = 1;SLTNode* node2 = (SLTNode*)malloc(sizeof(SLTNode));node2->data = 2;SLTNode* node3 = (SLTNode*)malloc(sizeof(SLTNode));node3->data = 3;SLTNode* node4 = (SLTNode*)malloc(sizeof(SLTNode));node4->data = 4;//下面将节点连接起来node1->next = node2;node2->next = node3;node3->next = node4;node4->next = NULL;SLTNode* plist = node1;SLTPrint(plist);
}

上面就是创建链表的代码,链表的每个节点是由数据和指向下一个节点的指针组成,所以我们要按照这个规则来创建链表的正确结构。

下面在Slist.c文件写打印的代码;

​
void SLTPrint(SLTNode* phead)
{SLTNode* pcur = phead;while (pcur){printf("%d->", pcur->data);pcur = pcur->next;}printf("NULL\n");
}​

大家来看打印代码,代码并不复杂,我们通过while循环去遍历链表的内容,每打印一次,我们就让pcur指向下一个节点,通过这样的方式去遍历每一个节点,当遍历到最后一个节点时,循环停止。

这里不知道大家有没有发现,我们遍历链表的方法和之前我们遍历数组和顺序表的方法有所不同,之前我们可以连续地遍历,那是因为数组和顺序表在物理结构上是连续的;而链表不满足这一特点,所以我们不能使用原来的方法去对链表进行遍历。只能通过指针的方式一个个遍历。

 2.2 链表的尾插

第一步在头文件中声明:

void SLTPushBack(SLTNode** pphead, SLTDataType x);

在前面介绍顺序表的插入时,我们需要判断空间大小够不够,在链表这里也类似,我们要为新节点申请空间,下面我们先来写申请空间的代码:

SLTNode* SLTBuyNode(SLTDataType x)
{SLTNode* newnode = (SLTNode*)malloc(sizeof(SLTNode));if (newnode == NULL){perror("malloc");exit(1);}newnode->data = x;newnode->next = NULL;return newnode;
}

这里我们创建新指针,使用malloc来申请空间,注意申请完后一定要进行判断,保证申请成功后再使用。

接下来我们来看尾插的实现方法:

void SLTPushBack(SLTNode** pphead, SLTDataType x)
{assert(pphead);SLTNode* newnode = SLTBuyNode(x);//空链表和非空链表if (*pphead == NULL)//{*pphead = newnode;//空链表}else//非空链表{//找尾节点SLTNode* ptail = *pphead;while (ptail->next){ptail = ptail->next;}ptail->next = newnode;}
}

这里大家要注意,我们一定要采用传址调用,上来我们先断言,pphead不能为NULL,我们要分两种情况进行讨论,如果传过去的是空链表,那我们直接将申请好的节点给phead这个头节点;如果传过来的不是空链表,因为我们要完成尾插,所以我们就需要找到原本链表的最后一个节点,上面代码中ptail就是尾节点,我们将新节点和尾节点连接在一起即可。

下面我们进行测试:

这里我们经过测试,可以成功地将数据插入到链表中,这里大家一定要注意在尾插代码中的一些坑点。

2.3 链表的头插

首先我们还是先在头文件中声明:
 

void SLTPushFront(SLTNode** pphead, SLTDataType x);

下面我们在SList文件中写头插代码:

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

这里大家发现,头插代码是比较简单的,上来还是先断言,然后为新插入的节点申请空间,然后我们要让原本的首节点成为新节点中指向下一个位置的节点,最后再让新节点成为新的首节点,这样就完成了头插的任务。

下面我们来对头插进行测试:

这里大家就可以清楚地看到头插的效果,证明我们上面的头插实现代码是正确的。

2.4 链表的尾删 

第一步还是先进行声明:

void SLTPopBack(SLTNode** pphead);

下面我们进行方法的实现:

void SLTPopBack(SLTNode** pphead)
{assert(pphead && *pphead);//链表不能为空//只有一个节点if ((*pphead)->next == NULL)//->优先级高于括号{free(*pphead);*pphead = NULL;}//有多个节点else{SLTNode* prev = *pphead;SLTNode* ptail = *pphead;while (ptail->next)//找尾节点{prev = ptail;ptail = ptail->next;}//prev是尾节点的前一个节点free(ptail);ptail = NULL;prev->next = NULL;}
}

这里大家注意来看,我们还是要分两种情况,第一种情况是当链表中只有一个节点时,我们直接释放它就可以达到删除的效果;第二种情况是链表中有多个节点,那么我们先要找到尾节点,然后将尾节点释放掉,并将其置为NULL,最后将尾节点的前一个节点中的指针置为NULL,这里是防止其成为野指针。

方法实现完了,我们下面来进行测试:

 这里我们完成了尾删的操作,这里还要提醒大家一下,删除的时候一定不能删“过头”了,删除的次数不能大于链表的节点数,否则断言那里就会受到NULL,这个时程序就会报错。

2.5 链表的头删

首先还是在头文件中声明:

void SLTPopFront(SLTNode** pphead);

下面来实现头删的方法:

void SLTPopFront(SLTNode** pphead)
{assert(pphead && *pphead);//链表不能为空SLTNode* next = (*pphead)->next;free(*pphead);*pphead = next;
}

这里头删的代码并不难,上来先断言一下,保证链表不为空;我们只需要先创建一个指针去存储头节点的下一个节点,然后再将原本的头节点删除,最后再让刚首节点向后移动。

最后我们来对头删进行测试:

这里大家可以看到头删的效果,证明上面的头删代码是正确的。 

 2.6 链表的查找

先进行声明:

SLTNode* SLTFind(SLTNode* phead, SLTDataType x);

然后我们来写查找的方法:

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

这里我们还是使用while来遍历链表,当所存数据与我们给的数据相等时就找到了那个对应的节点,这个时候我们直接返回pcur这个节点;如果没有找到,拿就返回NULL。

最后我们来测试查找方法:

 2.7 在链表指定位置之前插入数据

我们先在头文件中声明一下:

void SLTInsert(SLTNode** pphead, SLTNode* pos, SLTDataType x);

下面来实现一下这个方法:

void SLTInsert(SLTNode** pphead, SLTNode* pos, SLTDataType x)
{assert(pphead && *pphead);assert(pos);SLTNode* newnode = SLTBuyNode(x);if (pos == *pphead)//判断是否是头插{SLTPushFront(pphead, x);}else{SLTNode* prev = *pphead;while (prev->next != pos){prev = prev->next;}newnode->next = pos;prev->next = newnode;}
}

这里大家要分两种情况,第一种情况,当pos就是指向首节点的指针时,那么就相当于头插;第二种情况,当pos是指向其他节点的指针时,我们需要找到pos、pos的前一个节点(prev),找到后我们需要将newnode插入在这两个节点之间。

下面。我们来进行测试:

这里大家可以看到,我们在第三个节点之前插入了指定的数据。

2.8 在链表指定位置之后插入数据

我们还是先进行声明:

void SLTInsertAfter(SLTNode* pos, SLTDataType x);

这里大家可以发现,我们在函数的参数中并没有定义二级指针去接受头节点的地址,因为我们要完成在指定位置之后插入数据,所以我们只需要找到pos和pos下一个位置的节点即可。

下面我们来实现对应方法:

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

这里大家要注意指针是怎么操作的,我们要将pos、newnode、pos->next连接起来,那么连接方式很重要,有的同学可能会将最后两行颠倒位置,这个时候代码就会出问题,换位置后相当于newnode->next=newnode,这变成自己指向自己了,所以不能更换最后两行的位置。

下面我们来测试一下这个方法:

 

2.9 删除链表指定位置的数据

首先还是先来声明:

void SLTErase(SLTNode** pphead, SLTNode* pos);

下面来进行方法实现:

void SLTErase(SLTNode** pphead, SLTNode* pos)
{assert(pphead && *pphead);assert(pos);if (pos == *pphead){SLTPopFront(pphead);}else{SLTNode* prev = *pphead;while (prev->next != pos){prev = prev->next;}prev->next = pos->next;free(pos);pos = NULL;}
}

这里大家来观察代码,我们要分两种情况:第一种情况,当pos就是指向首节点的指针时,这就相当于头删,我们可以直接调用前面写好的头删方法;第二种情况,如果pos指向的不是首节点,我们就需要找到pos的前一个节点的指针(prev),要先将prev里的指针指向pos的下一个节点,然后释放pos,实现删除的效果。

下面来测试这个方法:


 

2.10 删除链表指定位置之后的数据

这里先进行声明:

void SLTEraseAfter(SLTNode* pos);

声明完后,我们进行方法的实现:

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

方法实现这里就比较简单,我们需要创建一个临时指针来保存pos的下一个节点的地址,然后再将对应的两个节点进行连接。

下面我们进行测试:
 

2.11 链表的销毁

 先来进行声明:

void SListDestroy(SLTNode** pphead);

下面我们来实现链表的销毁:

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

我们知道,链表是由一个个节点组成的,那么销毁链表的本质就是销毁节点;所以我们要遍历链表,然后逐个删除,最后不要忘了将头节点置为NULL。

下面我们来进行测试:

 

2.12 链表完整代码

SList.h

#pragma once
#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);
void SLTPushBack(SLTNode** pphead, SLTDataType x);
void SLTPushFront(SLTNode** pphead, SLTDataType x);
void SLTPopBack(SLTNode** pphead);
void SLTPopFront(SLTNode** pphead);
SLTNode* SLTFind(SLTNode* phead, SLTDataType x);
void SLTInsert(SLTNode** pphead, SLTNode* pos, SLTDataType x);
void SLTInsertAfter(SLTNode* pos, SLTDataType x);
void SLTErase(SLTNode** pphead, SLTNode* pos);
void SLTEraseAfter(SLTNode* pos);
void SListDestroy(SLTNode** pphead);

SList.c 

#define _CRT_SECURE_NO_WARNINGS 1
#include"SList.h"
void SLTPrint(SLTNode* phead)
{SLTNode* pcur = phead;while (pcur){printf("%d->", pcur->data);pcur = pcur->next;}printf("NULL\n");
}
SLTNode* SLTBuyNode(SLTDataType x)
{SLTNode* newnode = (SLTNode*)malloc(sizeof(SLTNode));if (newnode == NULL){perror("malloc");exit(1);}newnode->data = x;newnode->next = NULL;return newnode;
}
void SLTPushBack(SLTNode** pphead, SLTDataType x)
{assert(pphead);SLTNode* newnode = SLTBuyNode(x);//空链表和非空链表if (*pphead == NULL)//{*pphead = newnode;//空链表}else//非空链表{//找尾节点SLTNode* ptail = *pphead;while (ptail->next){ptail = ptail->next;}ptail->next = newnode;}
}
void SLTPushFront(SLTNode** pphead, SLTDataType x)
{assert(pphead);SLTNode* newnode = SLTBuyNode(x);newnode->next = *pphead;*pphead = newnode;
}
void SLTPopBack(SLTNode** pphead)
{assert(pphead && *pphead);//链表不能为空//只有一个节点if ((*pphead)->next == NULL)//->优先级高于括号{free(*pphead);*pphead = NULL;}//有多个节点else{SLTNode* prev = *pphead;SLTNode* ptail = *pphead;while (ptail->next)//找尾节点{prev = ptail;ptail = ptail->next;}//prev是尾节点的前一个节点free(ptail);ptail = NULL;prev->next = NULL;}
}
void SLTPopFront(SLTNode** pphead)
{assert(pphead && *pphead);//链表不能为空SLTNode* next = (*pphead)->next;free(*pphead);*pphead = next;
}
SLTNode* SLTFind(SLTNode* phead,SLTDataType x)
{SLTNode* pcur = phead;while (pcur){if (pcur->data == x){return pcur;}pcur = pcur->next;}return NULL;
}
void SLTInsert(SLTNode** pphead, SLTNode* pos, SLTDataType x)
{assert(pphead && *pphead);assert(pos);SLTNode* newnode = SLTBuyNode(x);if (pos == *pphead)//判断是否是头插{SLTPushFront(pphead, x);}else{SLTNode* prev = *pphead;while (prev->next != pos){prev = prev->next;}newnode->next = pos;prev->next = newnode;}
}
void SLTInsertAfter( SLTNode* pos, SLTDataType x)
{assert(pos);SLTNode* newnode = SLTBuyNode(x);newnode->next = pos->next;pos->next = newnode;
}
void SLTErase(SLTNode** pphead, SLTNode* pos)
{assert(pphead && *pphead);assert(pos);if (pos == *pphead){SLTPopFront(pphead);}else{SLTNode* prev = *pphead;while (prev->next != pos){prev = prev->next;}prev->next = pos->next;free(pos);pos = NULL;}
}
void SLTEraseAfter(SLTNode* pos)
{assert(pos&&pos->next);SLTNode* del = pos->next;pos->next = del->next;free(del);del = NULL;
}
void SListDestroy(SLTNode** pphead)
{assert(pphead && *pphead);SLTNode* pcur = *pphead;while (pcur){SLTNode* next = pcur->next;free(pcur);pcur = next;}*pphead = NULL;
}

test.c 

#define _CRT_SECURE_NO_WARNINGS 1
#include"SList.h"
void SListTest01()
{//创建好了4个节点SLTNode* node1 =(SLTNode*)malloc(sizeof(SLTNode));node1->data = 1;SLTNode* node2 = (SLTNode*)malloc(sizeof(SLTNode));node2->data = 2;SLTNode* node3 = (SLTNode*)malloc(sizeof(SLTNode));node3->data = 3;SLTNode* node4 = (SLTNode*)malloc(sizeof(SLTNode));node4->data = 4;//下面将节点连接起来node1->next = node2;node2->next = node3;node3->next = node4;node4->next = NULL;SLTNode* plist = node1;SLTPrint(plist);
}
void SListTest02()
{SLTNode* plist = NULL;SLTPushBack(&plist, 1);SLTPushBack(&plist, 2);SLTPushBack(&plist, 3);SLTPushBack(&plist, 4);SLTPrint(plist);SLTPushFront(&plist, 6);SLTPrint(plist);SLTPushFront(&plist, 7);SLTPrint(plist);SLTPushFront(&plist, 8);SLTPrint(plist);SLTPopFront(&plist);SLTPrint(plist);SLTPopFront(&plist);SLTPrint(plist);	SLTPopFront(&plist);SLTPrint(plist);SLTPopFront(&plist);SLTPrint(plist);SLTNode* find = SLTFind(plist, 2);SLTInsert(&plist,find,11);SLTInsertAfter(find, 11);SLTErase(&plist, find);SLTEraseAfter(find);SLTPrint(plist);SListDestroy(&plist);SLTPrint(plist);if (find == NULL){printf("没有找到\n");}else{printf("找到了\n");}
}
int main()
{SListTest02();//SListTest01();return 0;
}

3. 总结

本篇博客为大家介绍了链表这个数据结构,它不同于顺序表,有自己的特点;大家要理解每一个方法的实现代码,并且尝试自己写出来,链表是一种重要的线性表,希望本篇博客可以帮助大家学习,感谢阅读!

                                  
 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/42301.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

四大常见的排序算法JAVA

1. 冒泡排序 相邻的元素两两比较&#xff0c;大的放右边&#xff0c;小的放左边 第一轮比较完毕之后&#xff0c;最大值就已经确定&#xff0c;第二轮可以少循环一次&#xff0c;后面以此类推 如果数组中有n个数据&#xff0c;总共我们只要执行n-1轮的代码就可以 package Bu…

【matlab】状态空间模型与传递函数模型的建立与转换

目录 SISO系统 MIMO系统 状态空间模型 状态空间模型到传递函数模型的转换 传递函数模型到状态空间模型的转换 (1) 转换函数ss() (2) 规范形转换函数canon() (3) 常微分方程(传递函数)转换为状态空间模型函数dif2ss() 状态空间模型的变换 特征值、特征向量与广义特征向量的计算…

everything高级搜索-cnblog

everything高级搜索用法 基础4选项验证 总结搜索方式 高级搜索搜指定路径文件名: 文件名 路径不含文件名: &#xff01;文件名包含单词 路径包含指定内容: 路径 content:内容 大小写 区分大小写搜索搜指定路径文件名: case:文件名 路径全字匹配 全字搜指定路径文件名: wholewo…

中霖教育:二级建造师未注册还需要继续教育吗?

关键词&#xff1a;中霖教育怎么样&#xff0c;中霖教育口碑 如果通过了二级建造师考试但是没有注册&#xff0c;还用继续教育吗? 1. 未注册的二级建造师 二级建造师在其证书获取后三年内没有进行注册时&#xff0c;在申请初始注册之前必须完成规定的本专业继续教育课程。 …

ubuntu运行qq音乐闪退

ubuntu运行qq音乐闪退 修改/usr/share/applications中的qqmusic.desktop&#xff0c;在Exec后加上 --no-sandbox,如下图所示&#xff1a; 该文件有可能是只读&#xff0c;权限不够的话用sudo vim qqmusic.desktop

java项目的一些功能(完善登录功能、注册接口参数校验、完善分页查询、完善日期格式、更新文章分类和添加文章分类的分组校验、自定义校验、文件上传 )

目录 完善登录功能 注册接口参数校验 完善分页查询 完善日期格式 更新文章分类和添加文章分类的分组校验 ​编辑 自定义校验 文件上传 完善登录功能 对前端传过来的明文密码进行md5加密处理 password DigestUtils.md5DigestAsHex(password.getBytes()); 这样既可 注…

Python数据分析案例50——基于EEMD-LSTM的石油价格预测

案例背景 很久没更新时间序列预测有关的东西了。 之前写了很多CNN-LSTM&#xff0c;GRU-attention&#xff0c;这种神经网络之内的不同模型的缝合&#xff0c;现在写一个模态分解算法和神经网络的缝合。 虽然eemd-lstm已经在学术界被做烂了&#xff0c;但是还是很多新手小白或…

驾校管理系统的全面革新与升级

智慧驾校系统是一款专为现代驾校量身定制的综合性管理平台,它深度融合了云计算、大数据、物联网及人工智能等前沿技术,旨在为驾校打造一个高效、智能、便捷的运营生态系统。该系统通过数字化、信息化的手段,彻底革新了传统驾校的管理模式,不仅极大地提升了驾校的运营效率,…

Open3D 点云CPD算法配准(粗配准)

目录 一、概述 二、代码实现 2.1关键函数 2.2完整代码 三、实现效果 3.1原始点云 3.2配准后点云 一、概述 在Open3D中&#xff0c;CPD&#xff08;Coherent Point Drift&#xff0c;一致性点漂移&#xff09;算法是一种经典的点云配准方法&#xff0c;适用于无序点云的非…

【漏洞复现】宏景eHR LoadOtherTreeServlet SQL注入漏洞

0x01 产品简介 宏景eHR人力资源管理软件是一款人力资源管理与数字化应用相融合&#xff0c;满足动态化、协同化、流程化、战略化需求的软件。 0x02 漏洞概述 宏景eHR LoadOtherTreeServlet接口处存在SQL注入漏洞&#xff0c;未经身份验证的远程攻击者除了可以利用 SQL 注入漏…

孩子很内向,是不是自闭症?

作为星启帆寄宿制自闭症学校的老师&#xff0c;我深知内向与自闭症之间存在着本质的区别&#xff0c;尽管两者在社交表现上可能有一定的相似性。 首先&#xff0c;内向是一种性格特质&#xff0c;表现为个体在社交场合中相对安静、羞涩&#xff0c;更喜欢独处或与小范围的人交往…

Webpack: Loader开发 (1)

概述 如何扩展 Webpack&#xff1f;有两种主流方式&#xff0c;一是 Loader —— 主要负责将资源内容翻译成 Webpack 能够理解、处理的 JavaScript 代码&#xff1b;二是 Plugin —— 深度介入 Webpack 构建过程&#xff0c;重塑 构建逻辑。 相对而言&#xff0c;Loader 的职责…

Zookeeper分布式锁原理说明【简单易理解】

Zookeeper 非公平锁/公平锁/共享锁 。 1.zookeeper分布式锁加锁原理 如上实现方式在并发问题比较严重的情况下&#xff0c;性能会下降的比较厉害&#xff0c;主要原因是&#xff0c;所有的连接都在对同一个节点进行监听&#xff0c;当服务器检测到删除事件时&#xff0c;要通知…

人脸识别课堂签到系统【PyQt5实现】

人脸识别签到系统 1、运用场景 课堂签到,上班打卡,进出门身份验证。 2、功能类别 人脸录入,打卡签到,声音提醒,打卡信息导出,打包成exe可执行文件 3、技术栈 python3.8,sqlite3,opencv,face_recognition,PyQt5,csv 4、流程图 1、导入库 2、编写UI界面 3、打…

HackTheBox----Editorial

Editorial 测试过程 1 信息收集 NMAP端口扫描 nmap -sC -sV 10.10.11.20服务器开启了 22、80 端口 80 端口测试 服务器只开启了 22 和 80 端口&#xff0c;先从 80 端口开始进行测试 echo "10.10.11.20 editorial.htb" | sudo tee -a /etc/hostspublish with us…

SwiftData 模型对象的多个实例在 SwiftUI 中不能及时同步的解决

概览 我们已经知道,用 CoreData 在背后默默支持的 SwiftUI 视图在使用 @FetchRequest 来查询托管对象集合时,若查询结果中的托管对象在别处被改变将不会在 FetchedResults 中得到及时的刷新。 那么这一“囧境”在 SwiftData 里是否也会“卷土重来”呢?空说无益,就让我们在…

RK3588编译rkmpp,拉取海康威视网络摄像头264码流并运行yolo

硬件&#xff1a;EVB评估版 SOC&#xff1a;Rockchip RK3588 背景&#xff1a; 由于项目需要&#xff0c;需要拉取264码流&#xff0c;并通过将yolov5s.pt将模型转化为rknn模型&#xff0c;获取模型分析结果。取流可以通过软件解码或者硬件解码&#xff0c;硬件解码速度更快&…

Java版Flink使用指南——安装Flink和使用IntelliJ制作任务包

大纲 安装Flink操作系统安装JDK安装Flink修改配置启动Flink测试 使用IntelliJ制作任务包新建工程Archetype 编写测试代码打包测试 参考资料 在《0基础学习PyFlink》专题中&#xff0c;我们熟悉了Flink的相关知识以及Python编码方案。这个系列我们将使用相对主流的Java语言&…

LabVIEW在自动化测试项目中的推荐架构

在自动化测试项目中&#xff0c;推荐使用LabVIEW的生产者-消费者&#xff08;Producer-Consumer&#xff09;架构。这种架构利用队列实现数据的异步传输和处理&#xff0c;提供了高效、稳定和可扩展的解决方案。其主要优点包括&#xff1a;实现数据采集与处理的解耦、提高系统响…

中国IDC圈探访北京•光子1号金融算力中心

今天&#xff0c;“AI”、“大模型”是最炙手可热的话题&#xff0c;全球有海量人群在工作生活中使用大模型&#xff0c;大模型产品涉及多模态&#xff0c;应用范围已涵盖电商、传媒、金融、短视频、制造等众多行业。 而回看2003年的互联网记忆&#xff0c; “上网”“在线”是…