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

链表——删除元素或插入元素(头插法及尾插法)

目录

链表的结点由一个结构体构成

判断链表是否为空

键盘输入链表中的数据

输出链表中的数据

返回链表的元素个数

清空链表

 返回指定位置的元素值

查找数据所在位置

删除链表的元素

插入元素

建立无头结点的单链表

建立有头结点的单链表(头插法)

建立有头节点的单链表(尾插法)

总代码如下:


链表:

是一种在存储单元上非连续,非顺序的存储结构,由一系列结点组成,结点可以在运行的过程中动态生成,每个结点包括两部分:存储数据的数据域;存储下一节点地址的指针域

指针的理解:

将某个变量(例如 int a)赋值给指针,实际上就是将这个变量的地址赋值给指针,或者反过来说,指针中存储了这个变量的内存地址,指向了这个变量,通过指针就能找到这个变量。

链表的结点由一个结构体构成

struct node
{int data;//数据域struct node *next;//指针域
};

判断链表是否为空

如果链表头结点的指针域不为空,如果定义链表头结点是 struct node *L,也就是 L->next !=NULL.

(因为在有头结点的链表中,头结点数据域中不存储数据,它的指针域存放的是链表第一个元素的地址)

//判断链表是否为空
bool isEmptyList(struct node* L)
{//判断头结点指向的下一指针域不为空,说明该链表不为空if (L->next != NULL)return true;//不为空elsereturn false;//为空
}

建立头结点:

创建头结点,为头结点分配内存(用到 malloc 函数,使用头文件),令链表的头指针为空指针(有头节点的链表)。

键盘输入链表中的数据

//输入n个元素
void putList(struct node *L, int n)
{struct node* p, * q;L->next = (struct node*)malloc(sizeof(struct node));q = L->next;printf("输入%d个元素放入链表:",n);for (int i = 0; i < n; i++){int x;scanf("%d", &x);p = (struct node*)malloc(sizeof(struct node));p->data = x;p->next = NULL;q->next = p;q = p;}
}

输出链表中的数据

//输出链表中的数据
void printList(struct node* L)
{struct node* p;p = L->next;printf("当前链表元素:");while (p->next != NULL){p = p->next;//工作指针后移printf("%d ", p->data);//输出当前结点的数据}printf("\n");
}

返回链表的元素个数

因为链表是动态分配内存,所以没有记录结点个数,此时可以从头结点开始,通过指针后移找到后面的结点,当指针域为空时,就结束循环,循环的次数就是结点个数。

//返回链表元素个数
int numList(struct node* L)
{int sum = 0;//计数器struct node* p;//定义一个工作指针,因为如果直接用L指针后移的话,这个链表就找不到了p = L->next;//将头指针指针域指向的地址赋给p,也就是链表的第一个元素(头指针中不存放数据)while (p->next != NULL){p=p->next;sum++;}return sum;
}

清空链表

对于清空链表,是要把链表中每一个结点的空间都释放,而不是只释放头结点的空间。而且在释放空间之前,要记录它的指针域。

//清空链表
void clearList(struct node** L)
{struct node* p, * q;p = (*L)->next;//工作指针while (p!=NULL){//记录将要被释放空间的结点的指针域,如果不记录,那么链表后面的结点就找不到了q = p->next;free(p);p = q;}(*L)->next = NULL;
}

 返回指定位置的元素值

用一个工作指针后移找结点,循环时计数器自增,找到指定位置,然后返回。

//返回链表的指定位置的元素
int elementList(struct node* L, int x)//x为指定位置
{int i = 0;//计数器struct node* p;p = L->next;//找到指定位置的前面那个位置,因为当刚好i==x-1时,此时进入循环,p=p->next,刚好到达结点为x的位置while (p != NULL&&i<x){p = p->next;i++;}if (p)return p->data;elsereturn 0;
}

查找数据所在位置

用一个工作指针后移找结点,循环中计数器自增,如果找到一个结点的数据与目标值相等就返回该位置,直到循环结束,若是没有返回,就说明链表里面没有 x 元素。

//查找数据所在位置
int findList(struct node* L, int x)
{int i = 0;struct node* p;p = L->next;while (p != NULL){if (p->data == x)//找到了直接输出该节点的序号return i;i++;p = p->next;}return 0;//代表没有找到数据为x的结点
}

也有更好的方法,比如说如果有多个结点的元素与 x 相等,上面这个代码就解决不了了,此时可以用一个数组记录找到的位置,结束时返回该数组的地址。

删除链表的元素

先搞清有头结点的链表和无头结点的链表之间的区别:

http://t.csdn.cn/3Nghn

对于有头结点的链表就相对来说方便一些,不用考虑删除头指针的情况。

将要删除的结点赋给q,然后将 p->next 赋给 p->next.

//删除元素
bool deleteList(struct node* L, int x,int *e)//x是删除元素的结点序号,传入的地址e是用来记录删除结点的数据的
{struct node* p,* q;p = L->next;int i = 0;while (i < x-1&&p->next != NULL)//这里循环到i<x-1,因为找到当前的结点后,是删除它后面那个元素{p = p->next;i++;}if (p->next == NULL)return false;//删除失败q = p->next;*e = q->data;p->next = q->next;return true;//删除成功
}

插入元素

首先插入键盘输入的数字作为插入的数据:

先开辟一块空间,再将值放入 p 的数据域,将其指针域赋为 NULL,每次循环都进行此操作(到了最后一个结点的时候,它的指针域就是 NULL),也可以在输入完数据后将最后一个结点的指针域赋为 NULL。

每次循环将 p 结点赋给 q 结点,下一轮循环时就将 q->next=p.

//插入元素(输入)
void PutList(struct node* L,int x,int y)
{struct node* q,* p,* s;int i=1;p = L;while (i < x && p != NULL)//找到要插入元素的位置{p = p->next;i++;}s = (struct node*)malloc(sizeof(struct node));s->data = y;//赋值//这两步不能反s->next = p->next;p->next = s;
}

也可以生成随机数据作为插入的数据:此时用到 rand 函数和 srand 函数(用到 #include<stdlib.h> 函数和 #include<time.h> 头文件)

//插入元素(随机)
void PutRandList(struct node** L,int x)
{struct node* p, * q;q = NULL;int i = 1;p = (*L);while (i < x && p != NULL){p = p->next;i++;}srand(time(0));int s = rand()%100;q = (struct node*)malloc(sizeof(struct node));q->data = s;q->next = p->next;p->next = q;
}

建立无头结点的单链表

链表的每一个结点都有数据域,说明首元结点前没有头结点。

//创建链表(无头结点)
void creatList(struct node** L, int n)
{printf("输入%d个元素:",n);struct node* p, * q;*L = NULL;for (int i = 0; i < n; i++){int x;scanf("%d", &x);p = (struct node*)malloc(sizeof(struct node));p->data = x;p->next = NULL;if (*L == NULL)//如果头结点是空的就将第一个结点赋值给头结点(因为这是无头结点)*L = p;elseq->next = p;q = p;}
}

建立有头结点的单链表(头插法)

建立一个带头结点的链表,为结点 p 开辟一块空间,然后将生成的随机数赋值给 p 的数据域,将 p 插入到表头,循环执行。

//建立有头结点的单链表(头插法)
void CreateListHead(struct node* L, int n)//n为元素个数
{srand(time(0));struct node* p;for(int i=0;i<n;i++){p = (struct node*)malloc(sizeof(struct node));int s = rand() % 100;//随机数p->data = s;p->next = L->next;L->next = p;}
}

建立有头节点的单链表(尾插法)

与头插法不同的是:尾插法需要另外一个指向尾部的结点 r ,在链表中插入元素时,只需要将 r 的指针指向 p 即可,然后将 p 赋值给 r ,这样可以使 r 始终在链表尾部,并且将要插入的元素置于 r 的后方,也就是链表的尾部。插入结束后,将链表尾部的元素的指针指向NULL。

//建立有头结点的单链表(尾插法)
void CreateListTail(struct node* L, int n)
{srand(time(0));struct node* p, * q;q = L;for (int i = 0; i < n; i++){p = (struct node*)malloc(sizeof(struct node));int s = rand() % 100;p->data = s;q->next = p;q = p;}q->next = NULL;
}

总代码如下:

#include<stdio.h>
#include<stdlib.h>
#include<time.h>
struct node
{int data;struct node *next;
};
//清空链表
void clearList(struct node** L)
{struct node* p, * q;p = (*L)->next;//工作指针while (p!=NULL){//记录将要被释放空间的结点的指针域,如果不记录,那么链表后面的结点就找不到了q = p->next;free(p);p = q;}(*L)->next = NULL;
}
//输入n个元素
void putList(struct node *L, int n)
{struct node* p, * q;L->next = (struct node*)malloc(sizeof(struct node));q = L;printf("输入%d个元素放入链表:",n);for (int i = 0; i < n; i++){int x;scanf("%d", &x);p = (struct node*)malloc(sizeof(struct node));p->data = x;p->next = NULL;q->next = p;q = p;}
}
//输出链表中的数据
void printList(struct node* L)
{struct node* p;p = L->next;printf("当前链表元素:");while (p != NULL){printf("%d ", p->data);//输出当前结点的数据p = p->next;//工作指针后移}printf("\n");
}
//返回链表元素个数
int numList(struct node* L)
{int sum = 0;//计数器struct node* p;//定义一个工作指针,因为如果直接用L指针后移的话,这个链表就找不到了p = L->next;//将头指针指针域指向的地址赋给p,也就是链表的第一个元素(头指针中不存放数据)while (p->next != NULL){p=p->next;sum++;}return sum;
}
//判断链表是否为空
bool isEmptyList(struct node* L)
{//判断头结点指向的下一指针域不为空,说明该链表不为空if (L->next != NULL)return true;//不为空elsereturn false;//为空
}
//初始化
void InitList(struct node** L)
{*L = (struct node *)malloc(sizeof(struct node));(*L)->next = NULL;
}
//返回链表的指定位置的元素
int elementList(struct node* L, int x)//x为指定位置
{int i = 0;//计数器struct node* p;p = L->next;//找到指定位置的前面那个位置,因为当刚好i==x-1时,此时进入循环,p=p->next,刚好到达结点为x的位置while (p != NULL&&i<x){p = p->next;i++;}if (p)return p->data;elsereturn 0;
}
//查找数据所在位置
int findList(struct node* L, int x)
{int i = 0;struct node* p;p = L->next;while (p != NULL){if (p->data == x)//找到了直接输出该节点的序号return i;i++;p = p->next;}return 0;//代表没有找到数据为x的结点
}
//删除元素
bool deleteList(struct node *L, int x,int *e)//x是删除元素的结点序号,传入的地址e是用来记录删除结点的数据的
{struct node* p,* q;p = L->next;int i = 0;while (i < x-1&&p->next != NULL)//这里循环到i<x-1,因为找到当前的结点后,是删除它后面那个元素{p = p->next;i++;}if (p->next == NULL)return false;//删除失败q = p->next;*e = q->data;p->next = q->next;return true;//删除成功
}
//插入元素(输入)
void PutList(struct node* L,int x,int y)
{struct node* q,* p,* s;int i=1;p = L;while (i < x && p != NULL)//找到要插入元素的位置{p = p->next;i++;}s = (struct node*)malloc(sizeof(struct node));s->data = y;//赋值//这两步不能反s->next = p->next;p->next = s;
}
//插入元素(随机)
void PutRandList(struct node** L,int x)
{struct node* p, * q;q = NULL;int i = 1;p = (*L);while (i < x && p != NULL){p = p->next;i++;}srand(time(0));int s = rand()%100;q = (struct node*)malloc(sizeof(struct node));q->data = s;q->next = p->next;p->next = q;
}
//创建链表(无头结点)
void creatList(struct node** L, int n)
{printf("输入%d个元素:",n);struct node* p, * q;*L = NULL;for (int i = 0; i < n; i++){int x;scanf("%d", &x);p = (struct node*)malloc(sizeof(struct node));p->data = x;p->next = NULL;if (*L == NULL)//如果头结点是空的就将第一个结点赋值给头结点(因为这是无头结点)*L = p;elseq->next = p;q = p;}
}
//建立有头结点的单链表(头插法)
void CreateListHead(struct node* L, int n)//n为元素个数
{srand(time(0));struct node* p;for(int i=0;i<n;i++){p = (struct node*)malloc(sizeof(struct node));int s = rand() % 100;//随机数p->data = s;p->next = L->next;L->next = p;}
}
//建立有头结点的单链表(尾插法)
void CreateListTail(struct node* L, int n)
{srand(time(0));struct node* p, * q;q = L;for (int i = 0; i < n; i++){p = (struct node*)malloc(sizeof(struct node));int s = rand() % 100;p->data = s;q->next = p;q = p;}//这个地方不能省,因为输出的时候是以最后一个结点的指针域为NULL判断结束的q->next = NULL;
}int main()
{int n, x;struct node* L;//初始化后判断链表是否为空InitList(&L);//初始化链表if (isEmptyList(L))printf("当前链表不为空\n");elseprintf("当前链表为空\n");//输入n个元素存入链表printf("输入元素个数:");scanf("%d", &n);//输入元素个数putList(L, n);//键盘输入n个元素进入链表printList(L);if (isEmptyList(L))printf("当前链表不为空\n");elseprintf("当前链表为空\n");//统计链表中元素个数printf("链表中元素个数:%d\n",numList(L));//输入链表的结点位置,找对应位置的元素printf("输入要查找的地址:");scanf("%d", &x);printf("%d位置上的元素是:%d\n", x,  elementList(L,x));//输入元素,找链表中对应的位置printf("输入要查找的数据:");scanf("%d", &x);printf("%d在链表的第%d个\n", x,findList(L, x));//输入要删除的位置,删除对应的元素printf("输入要删除的位置:");scanf("%d", &x);int y;//记录删除的那个元素是什么if (deleteList(L, x, &y)){printList(L);//打印出链表printf("删除的元素是:%d\n", y);}else printf("删除失败\n");//插入元素printf("输入插入的元素的位置和元素:");scanf("%d%d", &x, &y);PutList(L, x, y);printList(L);//打印出链表//插入元素(随机生成数)printf("输入要插入随机数字的位置:");scanf("%d", &x);PutRandList(&L, x);printList(L);//打印出链表clearList(&L);//清空链表if (isEmptyList(L))//判断链表是否为空printf("当前链表不为空\n");elseprintf("当前链表为空\n");//建立无头结点的链表printf("建立无头结点的单链表,输入结点个数:");scanf("%d", &x);creatList(&L, x);//建立无头结点的单链表struct node *t = L;while (t != NULL)//打印无头结点单链表(打印时不能用上面的printList函数,因为这个是无头结点的链表){printf("%d ", t->data);t = t->next;}printf("\n");clearList(&L);//清空//建立有头结点的单链表printf("输入头插法的要插入的元素个数:");scanf("%d", &x);CreateListHead(L,x);printList(L);clearList(&L);//清空//建立有头结点的单链表(随机生成数)printf("输入尾插法的要插入的元素个数:");scanf("%d", &x);CreateListTail(L, x);printList(L);clearList(&L);//清空
}

相关文章:

链表——删除元素或插入元素(头插法及尾插法)

目录 链表的结点由一个结构体构成 判断链表是否为空 键盘输入链表中的数据 输出链表中的数据 返回链表的元素个数 清空链表 返回指定位置的元素值 查找数据所在位置 删除链表的元素 插入元素 建立无头结点的单链表 建立有头结点的单链表&#xff08;头插法&#xff…...

oracle容器的使用

oracle容器的使用 1.下载oracle容器 1.1拉取容器 docker pull registry.cn-hangzhou.aliyuncs.com/helowin/oracle_11g拉取国内镜像&#xff0c;该镜像大小为2.99G&#xff0c;已经集成了oracle环境&#xff0c;拉取完可以直接用&#xff0c;推荐使用这款oracle镜像 1.2查看…...

基于springboot会员制医疗预约服务管理信息系统演示【附项目源码】

基于springboot会员制医疗预约服务管理信息系统演示开发语言&#xff1a;Java 框架&#xff1a;springboot JDK版本&#xff1a;JDK1.8 服务器&#xff1a;tomcat7 数据库&#xff1a;mysql 5.7 数据库工具&#xff1a;Navicat11 开发软件&#xff1a;eclipse/myeclipse/idea M…...

GoogleAdsense国内加载慢怎么解决?

一淘模板 56admin.com 发现GoogleAdsense&#xff08;谷歌广告联盟&#xff09;国内加载慢拖网站速度怎么解决&#xff1f;GoogleAdsense是谷歌旗下的站长广告联盟系统&#xff0c;如果站长没有好的变现渠道&#xff0c;挂谷歌联盟是最好的选择&#xff08;日积月累&#xff09…...

【MySQL专题】03、性能优化之读写分离(MaxScale)

在我们了解了MySQL的主从复制的性能优化之后&#xff0c;紧接着《【MySQL专题】02、性能优化之主从复制》中&#xff0c;我们提及的读写分离&#xff0c;来进行读操作和写操作分散到不同的服务器结构中&#xff0c;同时希望对多个从服务器能提供负载均衡&#xff0c;读写分离和…...

Redis7高级之BigKey(二)

1.MoreKey案例 往redis里面插入大量测试数据key 生成100W条redis批量设置kv的语句保存在redisTest.txt for((i1;i<100*10000;i)); do echo "set k$i v$i" >> /tmp/redisTest.txt ;done; # 生成100W条redis批量设置kv的语句(keykn,valuevn)写入到/tmp目录下的…...

flex弹性盒子

概念 弹性盒子是一种用于按行或者按列布局的一维布局方法&#xff0c;元素可以膨胀以填充额外的空间&#xff0c;缩小以适应更小的空间 以下属性是给父元素添加的 1.flex-direction --改变轴的方向 row 默认值 默认沿着x轴排版(横向从左到右排列&#xff08;左对齐&#xff…...

[Java Web]Cookie | 一文详细介绍会话跟踪技术中的Cookie

⭐作者介绍&#xff1a;大二本科网络工程专业在读&#xff0c;持续学习Java&#xff0c;努力输出优质文章 ⭐作者主页&#xff1a;逐梦苍穹 ⭐所属专栏&#xff1a;Java Web 目录Cookie1、工作原理2、如何使用2.1、发送Cookie2.2、获取Cookie3、Cookie的存活时间4、中文错误Coo…...

这可能是2023最全的Java面试八股文,共计1658页,Java技术手册的天花板

前两天有个小伙伴在后台留言&#xff0c;最近的面试越来越难了&#xff0c;尤其是技术面&#xff0c;考察得越来越细&#xff0c;越来越底层&#xff0c;庆幸的是最终顺利找到了工作。 一般技术面试官都会通过自己的方式去考察程序员的技术功底与基础理论知识 比如果这样的问题…...

字节流及存放本地文件上传和下载文件

前言 之前的文章有写过 vuespringboot使用文件流实现文件下载 实现如何通过 D:\file\文件名.文件格式的形式进行下载文件 但是它对于很多业务场景相对适用性不是很广泛。 以及 elementUI加springboot实现上传excel文件给后端并读取excel 也只能是通过elementui的元素类型进行…...

【翻译】下一步:Go 泛型

原文地址&#xff1a; The Next Step for Generics - The Go Blog https://blog.golang.org/generics-next-step 介绍 自从我们上次写下关于在Go中加入泛型的可能性的文章以来&#xff0c;已经快一年了。现在是该更新的时候了。 设计的更新 我们一直在继续完善泛型设计草案。…...

如何简单实现ELT?

在商业中&#xff0c;数据通常和业务、企业前景以及财务状况相关&#xff0c;有效的数据管理可以帮助决策者快速有效地从大量数据中分析出有价值的信息。数据集成(Data Integration)是整个数据管理流程中非常重要的一环&#xff0c;它是指将来自多个数据源的数据组合在一起&…...

细思极恐,第三方跟踪器正在获取你的数据,如何防范?

细思极恐&#xff0c;第三方跟踪器正在获取你的数据&#xff0c;如何防范&#xff1f; 当下&#xff0c;许多网站都存在一些Web表单&#xff0c;比如登录、注册、评论等操作需要表单。我们都知道&#xff0c;我们在冲浪时在网站上键入的数据会被第三方跟踪器收集。但是&#x…...

Java基础之==,equal的区别(温故而知新)-----点点滴滴的积累

1. 为运算符&#xff0c;equal 为String数据类型的比较方法&#xff1b;相同内容的对象地址不一定相同&#xff0c;但相相同地址的对象内容一定相同&#xff1b; 比较的是值是否相等&#xff0c;equal比较的是是否是同一个对象。 2.基本概念不同 1&#xff09;对于&#xff0c…...

SpringBoot项目使用切面编程实现数据权限管理

springBoot项目使用切面编程实现数据权限管理什么是数据权限管理如何实现数据权限管理什么是数据权限管理 不同用户在某页面看到数据不一致&#xff0c;实现每个用户之间数据隔离的效果。 如以下场景&#xff1a; ● 页面期望展示当前登录人所在部门的数据。 ● 页面期望展示当…...

亚马逊测评是做什么的,风险有哪些?

自养号测评顾名思义就是自己养国外的买家账号给自己店铺提升销量和评论&#xff0c;做过多年的跨境卖家都知道测评可以快速提高产品的排名、权重和销量&#xff0c;&#xff08;国内某宝一样的逻辑&#xff09;但随着测评需求日益增大&#xff0c;卖家在寻求真人测评时也很容易…...

安科瑞导轨式智能通讯管理机

安科瑞 李亚娜 一、概述 AWT200 数据通讯网关应用于各种终端设备的数据采集与数据分析。实现设备的监测、控制、计算&#xff0c;为系统与设备之间建立通讯纽带&#xff0c;实现双向的数据通讯。实时监测并及时发现异常数据&#xff0c;同时自身根据用户规则进行逻辑判断&…...

vs2010下 转换到 COFF 期间失败: 文件无效或损坏

因为同一个电脑上安装多个VS&#xff0c;有多个cvtres.exe。按照下面的操作如果还是不行就在C盘搜索cvtres.exe&#xff0c;然后挨个重命名&#xff0c;看看是调用的哪个&#xff0c;然后修改就可以了。 用VS2010编译C项目时出现这样的错误&#xff1a; LNK1123: 转换到 COFF …...

托福高频真词List19 // 附托福TPO阅读真题

目录 3.28单词 3.29真题​​​​​​​ 3.28单词 legitimately/properlyadv.正当地likewise/similarlyadv.同样地reveal/showv.揭示substantiate/confirmv.证实suppress/stop by forcev.镇压trend/tendencyn.趋势empirical/based on observationa.凭借经验的illuminate/li…...

Go语言项目标准结构应该如何组织的?

这里写自定义目录标题Go项目本身的目录结构Go语言项目典型目录结构GO语言项目最小标准目录结构可执行的Go语言项目目录结构库的Go语言项目目录结构关于internal目录总结参考文章每当我们写一个非hello world实用程序的Go程序或库时&#xff0c;我们都会在项目结构、代码风格和标…...

LabelImg图像标注工具:3分钟掌握高效目标检测数据标注技巧

LabelImg图像标注工具&#xff1a;3分钟掌握高效目标检测数据标注技巧 【免费下载链接】labelImg LabelImg is now part of the Label Studio community. The popular image annotation tool created by Tzutalin is no longer actively being developed, but you can check ou…...

简单几步,让AI帮你画瑜伽女孩:雯雯的后宫-造相Z-Image-瑜伽女孩模型使用教程

简单几步&#xff0c;让AI帮你画瑜伽女孩&#xff1a;雯雯的后宫-造相Z-Image-瑜伽女孩模型使用教程 1. 模型介绍&#xff1a;你的专属AI瑜伽画师 想象一下&#xff0c;你只需要用文字描述&#xff0c;就能让AI为你创作出专业级的瑜伽女孩图片。这就是"雯雯的后宫-造相Z…...

UnityXR实战:用Pico实现物体抓取与场景重置(含材质交互技巧)

UnityXR实战&#xff1a;用Pico实现物体抓取与场景重置&#xff08;含材质交互技巧&#xff09; 在虚拟现实开发领域&#xff0c;交互体验的质量往往决定了产品的成败。Pico作为国内领先的VR设备&#xff0c;结合UnityXR框架&#xff0c;为开发者提供了强大的工具链来实现沉浸式…...

RAGFlow图片回答避坑指南:为什么不用Base64和阿里云OSS?

RAGFlow图片回答架构设计&#xff1a;从Base64到容器化服务器的技术演进 当RAG系统需要处理包含图片的回答时&#xff0c;技术选型直接关系到系统的性能、安全性和可维护性。本文将深入探讨几种主流方案的优劣对比&#xff0c;并解析为何容器化图片服务器成为当前最优解。 1. 图…...

ROS路径规划实战:用move_base让机器狗在Gazebo中自主导航(避坑指南)

ROS路径规划实战&#xff1a;用move_base让机器狗在Gazebo中自主导航&#xff08;避坑指南&#xff09; 当机器狗在仿真环境中流畅地绕过障碍物走向目标点时&#xff0c;那种成就感就像看着自家宠物第一次成功接住飞盘。作为ROS开发者&#xff0c;掌握move_base实现自主导航的能…...

保姆级教程:STM32F103开发第一步,搞定Keil5安装、激活与芯片包(附资源包)

STM32F103开发环境搭建全指南&#xff1a;从Keil5安装到芯片包配置 引言&#xff1a;为什么选择Keil MDK进行STM32开发 对于刚接触STM32微控制器的新手来说&#xff0c;开发环境搭建往往是第一个"拦路虎"。Keil MDK&#xff08;Microcontroller Development Kit&…...

SDMatte多风格背景生成:抠图后智能匹配艺术化背景

SDMatte多风格背景生成&#xff1a;抠图后智能匹配艺术化背景 1. 效果亮点预览 SDMatte带来的不仅是简单的透明背景抠图。它开创性地将精准抠图与智能背景生成相结合&#xff0c;让每张图片都能拥有无限可能的艺术化呈现。想象一下&#xff0c;你的产品照片可以瞬间变成油画风…...

AI净界-RMBG-1.4入门指南:理解Alpha通道、PNG透明度与导出规范

AI净界-RMBG-1.4入门指南&#xff1a;理解Alpha通道、PNG透明度与导出规范 你是不是也遇到过这样的烦恼&#xff1f;拍了一张不错的照片&#xff0c;想换个背景发朋友圈&#xff0c;或者做电商需要把商品图抠出来&#xff0c;结果发现边缘抠得跟狗啃的一样&#xff0c;头发丝和…...

Qwen2-VL-2B-Instruct在Qt桌面应用中的集成:开发跨平台图像分析工具

Qwen2-VL-2B-Instruct在Qt桌面应用中的集成&#xff1a;开发跨平台图像分析工具 1. 引言 如果你是做桌面应用开发的&#xff0c;特别是用C和Qt的&#xff0c;最近可能也注意到了AI模型带来的新机会。很多开发者都在想&#xff0c;怎么把这些强大的AI能力&#xff0c;比如看图…...

MT5中文增强工具多场景落地:保险条款通俗化改写与消费者理解度提升实践

MT5中文增强工具多场景落地&#xff1a;保险条款通俗化改写与消费者理解度提升实践 1. 项目概述与核心价值 MT5中文增强工具是一个基于Streamlit和阿里达摩院mT5模型构建的本地化NLP工具&#xff0c;专门针对中文文本进行语义改写和数据增强。这个工具的最大特点是能够在保持…...