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

[一篇读懂]C语言十一讲:单链表的删除和单链表真题实战

[一篇读懂]C语言十一讲:单链表的删除和单链表真题实战

  • 1. 与408关联解析及本节内容介绍
    • 1 本节内容介绍
  • 2. 单链表的删除操作实战
  • 3. 单链表真题解读与解题设计
    • 1 题目解读
    • 2 解题设计
      • 第一阶段:双指针找中间结点
      • 第二阶段:原地逆置
      • 第三阶段:轮流放入合并链表
  • 4. 代码实战
  • 5. 时间复杂度分析
  • 总结
    • 2
    • 3.2
    • 5


1. 与408关联解析及本节内容介绍

1 本节内容介绍

本节分为四小节讲解。
第一小节是链表删除进行实战
第二小节是是针对408考研真题2019年41题进行题目解读与解题设计
第三小节是针对408考研真题2019年41题进行实战
第四小节是分析真题实战代码的时间复杂度


2. 单链表的删除操作实战

  • 一切数据结构 - 增删查改

之前介绍了链表的新增、删除、查找的原理。

  • 单链表删除操作流程图:

单链表删除

画流程图很关键。

单链表删除操作:

#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <stdlib.h>typedef int ElemType; //写分号typedef struct LNode
{ElemType data; //数据域struct LNode* next;
}LNode, * LinkList;void list_tail_insert(LNode*& L)
{L = (LinkList)malloc(sizeof(LNode));//申请头结点空间,头指针指向头结点L->next = NULL;//头结点的next为NULLElemType x;scanf("%d", &x);LNode* s, * r = L;//s用来指向申请的新节点,r始终指向列表尾部while (x != 9999){s = (LinkList)malloc(sizeof(LNode));//为新节点申请空间s->data = x;r->next = s;//新节点给尾节点的next指针r = s;//r要指向新的尾部scanf("%d", &x);}r->next = NULL;//让尾节点的next为NULL
}void print_list(LinkList L)
{L = L->next;while (L != NULL){printf("%3d", L->data);L = L->next;}printf("\n");
}
//按位置查找
LinkList GetElem(LinkList L, int SearchPos)
{int j = 0;if (SearchPos < 0){return NULL;}while (L && j < SearchPos)//L!=NULL,地址不为NULL{L = L->next;j++;}return L;
}//删除第i个位置的元素
//删除时不改变L,所以不需要加引用
bool ListDelete(LinkList L, int i)
{LinkList p = GetElem(L, i - 1);//拿到要删除结点的前一个结点指针p//判断p是不是空的if (NULL == p){return false;}LinkList q = p->next;//拿到p的下一个结点指针 - 即要删除的结点指针p->next = q->next;//断链free(q);//释放return true;
}//尾插法新建链表
int main()
{LinkList L; //L是链表头指针,是结构体指针类型 - 大小8个字节//list_head_insert(L); //输入数据可以为3 4 5 6 7 9999,头插法新建链表list_tail_insert(L);print_list(L); //链表打印ListDelete(L, 4);//删除第四个结点print_list(L);return 0;
}

这里删除第四个结点,运行结果为:
删除


3. 单链表真题解读与解题设计

1 题目解读

2019年(单链表)
41.(13分)设线性表L=(a1,a2,a3,…,an−2.an−1,an)L=(a_1,a_2,a_3,…,a_{n-2}.a_{n-1},a_n)L=(a1,a2,a3,,an2.an1,an)采用带头结点的单链表保存,链表中的结点定义如下:

	typedef struct node {int data;struct node* next;} NODE;

        请设计一个空间复杂度为O(1)且时间上尽可能高效的算法,重新排列L中的各结点,得到线性表L′=(a1,an,a2,an−1,a3,an−2…)L'=(a_1,a_n,a_2,a_{n-1},a_3,a_{n-2}…)L=(a1,an,a2,an1,a3,an2)。要求:
(1)给出算法的基本设计思想。
(2)根据设计思想,采用C或C++语言描述算法,关键之处给出注释。
(3)说明你所设计的算法的时间复杂度。

解读:
首先空间复杂度是O(1),不能申请额外的空间,然后找到链表的中间结点,前面一半是链表L,将链表的后半部分给一个新的头结点L2,然后将链表L2进行原地逆置,然后再将L和L2链表进行交替合并。

空间复杂度O(?):额外使用的空间和原有空间之间的比例关系。

2 解题设计

分解题目,针对三个阶段封装三个子函数,条理清晰、逻辑缜密。

第一阶段:双指针找中间结点

如何找到链表的中间结点。

  1. 方法一:首先遍历一次链表,长度假如是20,再次遍历走到第10个。
    这样的缺点是遍历了两次链表。
    不好。
  2. 方法二:两个指针同步向后遍历的方法。
    定义两个指针pcur,ppre,让pcur指针每次走两步,ppre指针每次走一步,这样当pcur 指针走到最后,那么ppre指针刚好在中间。
    好。

注意,由于pcur每次循环是走两步的,因此每走一步都注意判断是否为NULL。

双指针找中间结点:
双指针

第二阶段:原地逆置

后一半链表我们设置为了L2,如何让 L2原地逆置?
        首先需要判断链表是否为空,如果为空,就返回,如果只有1个结点,也不需要逆置,直接返回。
        第一步:链表原地逆置,需要使用3个指针,假如分别是r,s,t,它们分别指向链表的1,2,3,也就是前三个结点。
        第二步:让s->next = r,这样2号结点就指向了1号结点,完成了逆置。
        第三步:这时,r = s,s = t,t = t->next,通过这个操作,r,s,t分别指向了链表的2,3,4结点,这时回到第二步,循环往复,当t为NULL时,结束循环。
        第四步:循环结束时,t为NULL,这时s是最后一个结点,r是倒数第第二个结点,需要再次执行一下s->next = r。
        第五步:最后需要L2->next->next = NULL;因为原有链表的头结点变成链表最后一个结点,最后一个结点的next需要为NULL。这时让L2->next = s,因为s是原链表最后一个结点,完成了逆置后,就是第一个结点,因此链表头结点L2指向s。

原地逆置

第三阶段:轮流放入合并链表

将L与L2链表合并,合并时轮流放入一个结点。
        因为空间复杂度是O(1),因此不申请新空间,但是依然需要3个指针(pcur,p,q),合并后的新链表让pcur指针始终指向新链表尾部,初始化为pcur = L->next,使用p指针始终指向链表L待放入的结点,初始化值为p = L->next,q指针始终指向链表L2待放入的结点,初始化值为q =L2->next。因为链表L的第一个结点不动,所以 p=p->next。
        开启循环while(p != NULL && q != NULL),首先将pcur->next = q,然后q = q->next和
pcur = pcur->next,接着pcur->next = p,然后p = p->next和pcur = pcur->next,直到循环结束。循环结束后,有可能L还剩余一个结点,也可能L2剩余一个结点,但是只会有一个剩余的有结点,因此判断如果p不为NULL,把p放入,如果q不为NULL,把q放入即可。
轮流放入


4. 代码实战

代码流程:先用尾插法新建一条链表,然后将链表拆分为两条,分别为L和L2,然后L2进行逆置,再把L和L2进行合并。

此处代码演示与上文一致,实际解题时须与题目一致。

代码实现:

#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <stdlib.h>typedef int ElemType; //写分号typedef struct LNode
{ElemType data; //数据域struct LNode* next;
}LNode, * LinkList;//尾插法新建链表
void list_tail_insert(LNode*& L)
{L = (LinkList)malloc(sizeof(LNode));//申请头结点空间,头指针指向头结点L->next = NULL;//头结点的next为NULLElemType x;scanf("%d", &x);LNode* s, * r = L;//s用来指向申请的新节点,r始终指向列表尾部while (x != 9999){s = (LinkList)malloc(sizeof(LNode));//为新节点申请空间s->data = x;r->next = s;//新节点给尾节点的next指针r = s;//r要指向新的尾部scanf("%d", &x);}r->next = NULL;//让尾节点的next为NULL
}//打印链表
void print_list(LinkList L)
{L = L->next;while (L != NULL)//NULL时为了代表一张空的藏宝图{printf("%3d", L->data);//打印当前结点数据L = L->next;//指向下一个结点}printf("\n");
}//找到链表中间结点,并设置好L2链表
void find_middle(LinkList L, LinkList &L2)
{L2 = (LinkList)malloc(sizeof(LNode));//第二条链表的头结点LinkList pcur, ppre;//双指针遍历 - 常考!ppre = pcur = L->next;while (pcur){pcur = pcur->next;//要检验每一步后是否结束,所以不可以写成pcur = pcur->next->next!if (NULL == pcur)//为了防止pcur为NULL{break;}pcur = pcur->next;//判断没有结束,再走一步if (NULL == pcur)//前一个指针在第二步结束时,后一个指针不动{break;}ppre = ppre->next;}L2->next = ppre->next;//由L2头结点指向后面一半链表 - 让L2成为后一半ppre->next = NULL;//前一半链表的最后一个结点的next为NULL - 让L成为前一半
}//原地逆置链表
void reverse(LinkList L2)//不改变头指针L2,不需要加引用&
{LinkList r, s, t;r = L2->next;if (NULL == r){return;//链表为空 - 只有头结点}s = r->next;if (NULL == s){return;//链表只有1个结点}t = s->next;while (t)//t不为空{s->next = r;//原地逆置r = s;//以下3句 - 3个指针同时向后走一步s = t;t = t->next;}s->next = r;L2->next->next = NULL;//逆置后,链表第一个结点的next要为NULLL2->next = s;//s时链表第一个结点,L2指向它
}//轮流放入合并链表
void merge(LinkList L, LinkList L2)
{LinkList pcur, p, q;pcur = L->next;//pcur始终指向合并链表的链表尾p = pcur->next;//p指向L链表第一个结点 - p用来遍历L链表q = L2->next;//q指向L2链表第一个结点 - q用来遍历L2链表while (NULL != p && NULL != q){pcur->next = q;//链表L2给过来一个结点q = q->next;//指向下一个pcur = pcur->next;//合并链表往后走一个pcur->next = p;//链表L给过来一个结点p = p->next;//指向下一个pcur = pcur->next;//合并链表往后走一个}//任何一个链表都可能剩余一个结点,放进来即可if (NULL != p){pcur->next = p;}if (NULL != q){pcur->next = q;}
}int main()
{LinkList L; //链表头,是结构体指针类型list_tail_insert(L);print_list(L); //链表打印//寻找中间结点,并返回第二条链表LinkList L2 = NULL;find_middle(L, L2);//只有一个结点时,L2中是没有结点的printf("-----------------------------\n");//双指针遍历 - 分L和L2链表print_list(L);print_list(L2);printf("-----------------------------\n");//原地逆置链表reverse(L2);print_list(L2);printf("-----------------------------\n");//轮流放入合并链表merge(L, L2);free(L2);print_list(L);return 0;
}

输入偶数个:1 2 3 4 5 6 9999
输出结果为:
输出1

输入奇数个:1 2 3 4 5 6 7 9999
输出结果为:
输出2


5. 时间复杂度分析

分析上一部分代码。

第一部分:find_middle函数,可以看到有一个while循环,因为pcur每次移动两个节点,因此循环的次数是n/2,忽略首项系数,所以时间复杂度是O(n)

//找到链表中间结点,并设置好L2链表
void find_middle(LinkList L, LinkList &L2)
{L2 = (LinkList)malloc(sizeof(LNode));//第二条链表的头结点LinkList pcur, ppre;//双指针遍历 - 常考!ppre = pcur = L->next;while (pcur){pcur = pcur->next;//要检验每一步后是否结束,所以不可以写成pcur = pcur->next->next!if (NULL == pcur)//为了防止pcur为NULL{break;}pcur = pcur->next;//判断没有结束,再走一步if (NULL == pcur)//前一个指针在第二步结束时,后一个指针不动{break;}ppre = ppre->next;}L2->next = ppre->next;//由L2头结点指向后面一半链表 - 让L2成为后一半ppre->next = NULL;//前一半链表的最后一个结点的next为NULL - 让L成为前一半
}

第二部分:reverse函数,遍历了L2链表,遍历长度是n/2,所以时间复杂度是O(n)

//原地逆置链表
void reverse(LinkList L2)//不改变头指针L2,不需要加引用&
{LinkList r, s, t;r = L2->next;if (NULL == r){return;//链表为空 - 只有头结点}s = r->next;if (NULL == s){return;//链表只有1个结点}t = s->next;while (t)//t不为空{s->next = r;//原地逆置r = s;//以下3句 - 3个指针同时向后走一步s = t;t = t->next;}s->next = r;L2->next->next = NULL;//逆置后,链表第一个结点的next要为NULLL2->next = s;//s时链表第一个结点,L2指向它
}

第三部分:merge函数,while循环遍历次数也是n/2,因此时间复杂度是O(n)

//轮流放入合并链表
void merge(LinkList L, LinkList L2)
{LinkList pcur, p, q;pcur = L->next;//pcur始终指向合并链表的链表尾p = pcur->next;//p指向L链表第一个结点 - p用来遍历L链表q = L2->next;//q指向L2链表第一个结点 - q用来遍历L2链表while (NULL != p && NULL != q){pcur->next = q;//链表L2给过来一个结点q = q->next;//指向下一个pcur = pcur->next;//合并链表往后走一个pcur->next = p;//链表L给过来一个结点p = p->next;//指向下一个pcur = pcur->next;//合并链表往后走一个}//任何一个链表都可能剩余一个结点,放进来即可if (NULL != p){pcur->next = p;}if (NULL != q){pcur->next = q;}
}

上面3个函数总的运行次数是1.5n,忽略首项系数,因此时间复杂度是O(n)


总结

2

  • 单链表删除操作流程图:

单链表删除

3.2

  • 两个指针同步向后遍历的方法很常用

5

  • 分析时间复杂度时最好分块分析
  • 时间复杂度忽略首项系数

相关文章:

[一篇读懂]C语言十一讲:单链表的删除和单链表真题实战

[一篇读懂]C语言十一讲&#xff1a;单链表的删除和单链表真题实战1. 与408关联解析及本节内容介绍1 本节内容介绍2. 单链表的删除操作实战3. 单链表真题解读与解题设计1 题目解读2 解题设计第一阶段&#xff1a;双指针找中间结点第二阶段&#xff1a;原地逆置第三阶段&#xff…...

【C++初阶】list的使用

大家好我是沐曦希&#x1f495; 文章目录一、前言二、构造三、迭代器四、增删查改1.头插头删2.尾插尾删3.查找和插入4.删除五、其他成员函数1.排序和去重2.splice和remove3.resize一、前言 list本质是带头双向循环链表&#xff0c;本文只对list的一些常用接口进行说明&#xf…...

HTML 布局

网页布局对改善网站的外观非常重要。 请慎重设计您的网页布局。 在线实例 使用 <div> 元素的网页布局 如何使用 <div> 元素添加布局。 使用 <table> 元素的网页布局 如何使用 <table> 元素添加布局。 网站布局 大多数网站会把内容安排到多个列中&a…...

如何在虚拟机中安装ikuai软路由系统

首先访问ikuai官网下载固件固件下载-爱快 iKuai-商业场景网络解决方案提供商 (ikuai8.com) 根据需求下载 然后创建一个虚拟机&#xff0c;点击下一步 选择更下载的ISO映像文件&#xff0c;点击下一步 点击下一步 设置一下名称和储存位置&#xff0c;点击下一步 根据需求设置&a…...

Java 多线程 --- 线程协作 wait/notify

Java 多线程 --- 线程协作 wait/notifywait / notifyObject.wait() , Object.notify() / notifyAll()notify 和 wait 的原理notify会导致死锁的问题wait / notify的开销以及问题wait / notify 在多线程中, 如果程序拿到锁之后, 但是没有满足指定条件而不能继续往下执行, 我们可…...

【PyTorch】教程:torch.nn.Hardsigmoid

torch.nn.Hardsigmoid 原型 CLASS torch.nn.Hardsigmoid(inplaceFalse) 参数 inplace (bool) – 默认为 False 定义 Hardsigmoid(x){0if x≤−3,1if x≥3,x/61/2otherwise\text{Hardsigmoid}(x) \begin{cases} 0 & \text{if~} x \le -3, \\ 1 & \text{if~} x \ge 3…...

【手把手一起学习】(八) Altium Designer 20修改和自定义原理图标题栏

1 修改原理图标题栏 直接对原理图标题栏属性进行修改&#xff0c;操作如图所示&#xff1a; 修改后&#xff0c;并不会显示&#xff0c;故该方法不可用&#xff1a; 正确的操作如下&#xff0c;先选择合适的模板&#xff1a; 然后&#xff0c;进行属性的修改&#xff1a; 此时…...

业务流程测试

用例设计主要问题主要问题存在于&#xff1a;1、测试点分析&#xff1a;逻辑性不强对于整个页面功能划分不清晰&#xff1b;不同测试点归类不清晰&#xff1b;不能形成相对固定的套路&#xff0c;书写耗费大量时间...2、测试用例&#xff1a;关于&#xff0c;要细致到什么程度&…...

[极客大挑战 2019]EasySQL 1

[极客大挑战 2019]EasySQL 1解题POC一、解题思路之暴力破解1. 弱口令2. 暴力破解二、解题思路之万能密码1. 什么是万能密码2. 测试过程解题POC 直接点击登录获取flagflag{62f0d2ca-579e-450e-941f-5f7c23a8baf7} 一、解题思路之暴力破解 这题是万能密码&#xff0c;所以暴力破解…...

vulnhub raven2复现

1.扫描全网段&#xff0c;找出了存活主机ip为192.168.85.144 nmap 192.168.85.0/24 2.nmap扫描端口 nmap -p1-65535 192.168.85.144 3.访问此网站&#xff0c;没找到什么地方可以利用漏洞 &#xff0c;查看中间件为wordpress 4.使用dirb对该网站进行目录扫描 dirb http://1…...

LeetCode 剑指 Offer II 079. 所有子集

给定一个整数数组 nums &#xff0c;数组中的元素 互不相同 。返回该数组所有可能的子集&#xff08;幂集&#xff09;。 解集 不能 包含重复的子集。你可以按 任意顺序 返回解集。 示例 1&#xff1a; 输入&#xff1a;nums [1,2,3] 输出&#xff1a;[[],[1],[2],[1,2],[3…...

打印名片-课后程序(Python程序开发案例教程-黑马程序员编著-第二章-课后作业)

实例3&#xff1a;文本进度条 进度条以动态方式实时显示计算机处理任务时的进度&#xff0c;它一般由已完成任务量与剩余未完成任务量的大小组成。本实例要求编写程序&#xff0c;实现图1所示的进度条动态显示的效果。 下载中下载完成图1文本进度条 实例分析 在本实例中可以将…...

为什么我们在判断字符串不为null后还要判断字符串长度大于0?

我们在做字符串判断时一般会&#xff1a; if (s ! null && s.length() > 0) {} 但是我就在想&#xff0c;字符串不为空了&#xff0c;那么他一定有值&#xff0c;字符串长度不就大于0吗&#xff0c;所以s.length()>0是不是有点多余&#xff1f; 我的思维误区是…...

javaEE 初阶 — 应用层中的 DNS 协议(域名解析系统)

文章目录什么是域名1. 如何建立 域名 与 IP 的对应关系2. 域名的分级什么是域名 域名也就是平常所说的网址&#xff0c;比如 www.baidu.com。 其实网络上的服务器要访问这个网址&#xff0c;需要的是 IP 地址。、 但是 IP 地址比较拗口不方便记忆&#xff0c;于是就有使用一些…...

【网络】-- 网络编程套接字(铺垫、预备)

目录 理解源IP地址和目的IP地址 认识端口号 端口号 理解源端口号和目的端口号 套接字 认识TCP与UDP协议 网络字节序 socket编程接口 socket 常见API sockaddr结构 理解源IP地址和目的IP地址 就如同我们唐僧的取经路&#xff1a; 唐僧的出发地到目的地&#xff1a;东…...

一文打通@SentinelResource

Sentinel 提供了 SentinelResource 注解用于定义资源&#xff0c;并提供了 AspectJ 的扩展用于自动定义资源、处理 BlockException 等 如果使用的是Sentinel Annotation AspectJ Extension&#xff0c;需要导这个依赖 <dependency><groupId>com.alibaba.csp</…...

苹果手机备份的文件在电脑什么地方 苹果备份文件怎么查看

在这个网络信息时代&#xff0c;为手机进行定期备份已经成为了家常便饭。在使用备份软件对苹果手机进行备份后&#xff0c;苹果手机备份的文件在什么地方&#xff0c;苹果备份文件怎么查看呢&#xff1f;本文就带大家来了解一下。 一、苹果手机备份的文件在电脑什么地方 大家…...

【MySQL速通篇001】5000字超详细介绍MySQL部分重要知识点

&#x1f340; 写在前面 这篇5000多字博客也花了我几天的时间&#x1f602;&#xff0c;主要是我对MySQL一部分重要知识点的理解【后面当然还会写博客补充噻&#xff0c;欢迎关注我哟】&#xff0c;当然这篇文章可能也会有不恰当的地方【毕竟也写了这么多字&#xff0c;错别字可…...

并发编程——synchronized优化原理

如果有兴趣了解更多相关内容&#xff0c;欢迎来我的个人网站看看&#xff1a;耶瞳空间 一&#xff1a;基本概念 使用synchronized实现线程同步&#xff0c;即加锁&#xff0c;实现的是悲观锁。加锁可以使一段代码在同一时间只有一个线程可以访问&#xff0c;在增加安全性的同…...

LeetCode 剑指 Offer II 083. 没有重复元素集合的全排列

给定一个不含重复数字的整数数组 nums &#xff0c;返回其 所有可能的全排列 。可以 按任意顺序 返回答案。 示例 1&#xff1a; 输入&#xff1a;nums [1,2,3] 输出&#xff1a;[[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]] 1 < nums.length < 6 -10 < nu…...

基于FPGA的PID算法学习———实现PID比例控制算法

基于FPGA的PID算法学习 前言一、PID算法分析二、PID仿真分析1. PID代码2.PI代码3.P代码4.顶层5.测试文件6.仿真波形 总结 前言 学习内容&#xff1a;参考网站&#xff1a; PID算法控制 PID即&#xff1a;Proportional&#xff08;比例&#xff09;、Integral&#xff08;积分&…...

在四层代理中还原真实客户端ngx_stream_realip_module

一、模块原理与价值 PROXY Protocol 回溯 第三方负载均衡&#xff08;如 HAProxy、AWS NLB、阿里 SLB&#xff09;发起上游连接时&#xff0c;将真实客户端 IP/Port 写入 PROXY Protocol v1/v2 头。Stream 层接收到头部后&#xff0c;ngx_stream_realip_module 从中提取原始信息…...

如何将联系人从 iPhone 转移到 Android

从 iPhone 换到 Android 手机时&#xff0c;你可能需要保留重要的数据&#xff0c;例如通讯录。好在&#xff0c;将通讯录从 iPhone 转移到 Android 手机非常简单&#xff0c;你可以从本文中学习 6 种可靠的方法&#xff0c;确保随时保持连接&#xff0c;不错过任何信息。 第 1…...

Reasoning over Uncertain Text by Generative Large Language Models

https://ojs.aaai.org/index.php/AAAI/article/view/34674/36829https://ojs.aaai.org/index.php/AAAI/article/view/34674/36829 1. 概述 文本中的不确定性在许多语境中传达,从日常对话到特定领域的文档(例如医学文档)(Heritage 2013;Landmark、Gulbrandsen 和 Svenevei…...

网站指纹识别

网站指纹识别 网站的最基本组成&#xff1a;服务器&#xff08;操作系统&#xff09;、中间件&#xff08;web容器&#xff09;、脚本语言、数据厍 为什么要了解这些&#xff1f;举个例子&#xff1a;发现了一个文件读取漏洞&#xff0c;我们需要读/etc/passwd&#xff0c;如…...

浪潮交换机配置track检测实现高速公路收费网络主备切换NQA

浪潮交换机track配置 项目背景高速网络拓扑网络情况分析通信线路收费网络路由 收费汇聚交换机相应配置收费汇聚track配置 项目背景 在实施省内一条高速公路时遇到的需求&#xff0c;本次涉及的主要是收费汇聚交换机的配置&#xff0c;浪潮网络设备在高速项目很少&#xff0c;通…...

【电力电子】基于STM32F103C8T6单片机双极性SPWM逆变(硬件篇)

本项目是基于 STM32F103C8T6 微控制器的 SPWM(正弦脉宽调制)电源模块,能够生成可调频率和幅值的正弦波交流电源输出。该项目适用于逆变器、UPS电源、变频器等应用场景。 供电电源 输入电压采集 上图为本设计的电源电路,图中 D1 为二极管, 其目的是防止正负极电源反接, …...

基于Springboot+Vue的办公管理系统

角色&#xff1a; 管理员、员工 技术&#xff1a; 后端: SpringBoot, Vue2, MySQL, Mybatis-Plus 前端: Vue2, Element-UI, Axios, Echarts, Vue-Router 核心功能&#xff1a; 该办公管理系统是一个综合性的企业内部管理平台&#xff0c;旨在提升企业运营效率和员工管理水…...

libfmt: 现代C++的格式化工具库介绍与酷炫功能

libfmt: 现代C的格式化工具库介绍与酷炫功能 libfmt 是一个开源的C格式化库&#xff0c;提供了高效、安全的文本格式化功能&#xff0c;是C20中引入的std::format的基础实现。它比传统的printf和iostream更安全、更灵活、性能更好。 基本介绍 主要特点 类型安全&#xff1a…...

协议转换利器,profinet转ethercat网关的两大派系,各有千秋

随着工业以太网的发展&#xff0c;其高效、便捷、协议开放、易于冗余等诸多优点&#xff0c;被越来越多的工业现场所采用。西门子SIMATIC S7-1200/1500系列PLC集成有Profinet接口&#xff0c;具有实时性、开放性&#xff0c;使用TCP/IP和IT标准&#xff0c;符合基于工业以太网的…...