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

数据结构:单链表

文章目录

  • 🍉前言
  • 🍉基本概念
  • 🍉链表的分类
    • 🍌单链表节点的结构
    • 🍌创建节点
    • 🍌打印链表
    • 🍌插入和删除
      • 🥝尾插
      • 🥝头插
      • 🥝尾删
      • 🥝头删
      • 🥝指定位置之前插入
      • 🥝指定位置之后插入
      • 🥝删除指定节点
    • 🍌销毁
  • 🍉源码
    • 🍌头文件:声明部分
    • 🍌源文件:功能实现部分

🍉前言

喜茶的果汁茶有这样的一句宣传语:一半果汁一半茶。用这个来形容单链表那可是再合适不过了一一 一半数据一半指针。
在这里插入图片描述

🍉基本概念

链表是一种数据结构,采用链式存储一一在内存中不是连续存储的,各元素的逻辑顺序是通过链表中的指针链接次序实现的。它包含数据域指针域,分别保存数据和下一个节点的地址。
在这里插入图片描述
如果要创建节点,一般是在堆上申请。


🍉链表的分类

链表结构多种多样,有三种分类,这些分类进行排列组合共有8种:

①单向或双向
区分单双向就看各节点之间的指向是否是双向的,比如下面这个就是双向链表。
在这里插入图片描述

②带头或不带头
就是有没有带头节点,头节点的数据域一般是存放这个链表的基本信息,其指针域指向第一个节点。在这里插入图片描述>>③循环或非循环
尾节点的指针指向头节点就可以形成一个循环。在这里插入图片描述

我们最常用的是这两种:无头单向非循环链表和带头双向循环链表,本文要讲的是单链表。

🍌单链表节点的结构

typedef int SLTypeDate;
typedef struct SListNode {SLTypeDate data;struct SListNode* next;
}SLNode;

这个结构体里面有一个同类型的结构体指针,这种现象叫做结构体的自引用,往下看你就会知道这个指针的妙处了。

Q:使用 typedef 对结构体重命名之后,可以在结构体内部使用新的名字吗?
A:不可以,因为编译器是向下编译的,上面的语句相当于:

struct SListNode {SLTypeDate data;struct SListNode* next;
};
typedef int SLTypeDate SLNode;

🍌创建节点

刚才已经在头文件里面定义了一个结构体类型SLNode(链表节点),那么现在来建立一些节点,用于后面测试相应的函数。
(原文件 test.c)

void SLTest() {SLNode* Node1 = (SLNode*)malloc(sizeof(SLNode));Node1->data = 1;SLNode* Node2 = (SLNode*)malloc(sizeof(SLNode));Node1->data = 2;SLNode* Node3 = (SLNode*)malloc(sizeof(SLNode));Node1->data = 3;SLNode* Node4 = (SLNode*)malloc(sizeof(SLNode));Node1->data = 4;
}
	Node1->next = Node2;Node2->next = Node3;Node3->next = Node4;Node4->next = NULL;

建立了四个节点,但是它们现在彼此之间还没有联系,就是孤零零的四个节点,此时我们用next指针把它们给串联起来。整体效果图就是这样:
在这里插入图片描述
某个节点的指针域保存的是下一个节点的地址


🍌打印链表

我们来写一个函数打印链表中存放的数据。

void SLPrint(SLNode* phead) {SLNode* pcur = phead;while (pcur) {printf("%d ->", pcur->data);pcur = pcur->next;  //pcur原先指向某个节点,现在让它指向下一个节点}printf("NULL\n");
}

这里解释下为什么要用一个pcur保存第一个节点的地址:因为你如果用phead的话,那到时phead在循环中就会不断往前走,直到它为NULL,也就是说,循环结束以后phead就是空指针了,那你就再也找不到链表中各个节点的地址了。

所以我们不难看出链表是通过地址的赋值,从上一个节点走到下一个节点

接下来也是和顺序表差不多,有头插、尾插的操作,执行插入操作时我们需要申请新节点,为了避免重复,让代码简洁一点,我们可以写一个申请新节点的函数。

SLNode* SLBuyNode(SLTypeDate x) {  //申请一个节点,并将想要存储的数据存进去SLNode* node = (SLNode*)malloc(sizeof(SLNode));node->data = x;node->next = NULL;return node;
}

🍌插入和删除

老规矩,还是分为头插和尾插还有随便插,先来写个尾插

🥝尾插

在这里插入图片描述

我们首先得找到最后一个节点,然后把它的next指针改为node的地址,代码如下,该说的基本都在注释讲了,主要来说一下 while 循环的终止条件。
在这里插入图片描述
如果循环终止条件是pcur == NULL 的话,那就跑过头了,此时pcur就成空指针。

void SLPushBack(SLNode** pphead,SLTypeDate x) {assert(pphead);SLNode* node = SLBuyNode(x);if (*pphead == NULL) {  //phead为空说明此时链表为空,那就直接插入*pphead = node;  //让node是第一个节点的地址return;}//若不为空,则先找到链表的最后一个节点,再插入SLNode* pcur = *pphead;  //老样子,用临时变量pcur去走循环while (pcur->next) {pcur = pcur->next;}//此时pcur指向最后一个节点pcur->next = node;
}

如果你指针部分的知识学得很扎实,那你一眼就可以看出这段代码有问题了。

这样写问题出在哪里呢?问题在于你传的参数,你觉得把实参传给这个phead是传值调用还是传址调用?显然是传值,因为实参虽然是节点的地址,但是它本质上是一个值,你传过来给 phead 的只是一个值而已,任你怎么改变phead,都与实参无关。而在这个函数中,如果你进行尾插时链表为空,那node的值只给到了phead,无法影响到实参。
要解决问题的话,改为传二级指针就ok了。

而如果链表不为空,那就没啥影响了,因为此时你只需改变 next ,无需改变实参。传值确实没问题,但是为了形式上的统一(避免一下子是一级指针,一下子又是二级指针),所以也传二级指针。
phead 是一级指针,那么二级指针我们就记为pphead,把原本的phead改为 *pphead就ok了。同时我们需要对 pphead 进行断言,因为它为空的话那就不能解引用。
所以正确的代码如下:

void SLPushBack(SLNode** pphead,SLTypeDate x) {assert(pphead);  //进行断言,防止传过来的指针为空SLNode* node = SLBuyNode(x);if (*pphead == NULL) {  //phead为空说明此时链表为空,那就直接插入*pphead = node;  //让node是第一个节点的地址return;}//若不为空,则先找到链表的最后一个节点,再插入SLNode* pcur = *pphead;  //老样子,用临时变量pcur去走循环while (pcur->next) {pcur = pcur->next;}//此时pcur指向最后一个节点pcur->next = node;
}

🥝头插

头插就很简单了,不用考虑顺序表为不为空。

void SLPushFront(SLNode** pphead, SLTypeDate x) {assert(pphead);SLNode* node = SLBuyNode(x);node->next = *pphead;*pphead = node;
}

🥝尾删

尾删需要完成2个任务:①释放掉最后一个节点的空间;②将倒数第二个节点的 next 指针置为空。
最后一个节点这个好找,那倒数第二个呢?请看下面代码:

void SLPopBack(SLNode** pphead,SLTypeDate x) {assert(pphead);assert(*pphead);  //如果节点地址为空,那么说明节点为空(为空说明没有指向),而节点为空时显然不能删除SLNode* prev = NULL;SLNode* ptail = *pphead;if ((*pphead)->next == NULL) {free(*pphead);*pphead = NULL;return;}while (ptail->next) {prev = ptail;ptail = ptail->next;}prev->next = ptail->next;free(ptail);ptail = NULL;
}
}

我这次弄了两个指针:prevptailptail经过循环最终指向最后一个节点;而prev则是指向倒数第二个节点。可以看到,每次循环我在把下一个节点地址赋给 ptail之前,就把当下ptail 保存到prev,这样在最后一次循环时 prev 就在倒二了。
然后 if 语句里面的是只有一个节点的情况,为什么要单独把它拿出来讨论呢?因为如果没有这个 if 语句,那么此时 prev 就是NULL,它不能解引用去访问节点里面的 next,更何况此时还是一个空节点。

释放最后一个节点之后,一定要把它的地址置为空,你如果不置空,在尾删这个函数里面确实没问题,但是在打印链表的函数中,循环的终止条件是pcur为空,当pcur走到被删掉的节点时,因为地址不为空,所以会把这里的东西打印出来。
释放掉某块空间,只是把里面的数据给释放掉,但是那块空间仍然存在


🥝头删

头删的思路就是:把第一个节点释放掉,把 phead(*pphead) 给到原先的第二个节点

void SLPopFront(SLNode** pphead) {assert(pphead);assert(*pphead);SLNode* pcur = *pphead;*pphead = (*pphead)->next;free(pcur);pcur = NULL;
}

这里 pcur 可以不置为空,但出于代码规范,所以置空。


🥝指定位置之前插入

既然要在某位置前插入,那就得先找到这个位置,怎么找呢?当然是循环遍历了,先来写下找到我们想要的节点的函数:

SLNode* SLFindNode(SLNode** pphead, SLTypeDate x) {assert(pphead);SLNode* pcur = *pphead;while (pcur) {if (pcur->data == x) {return pcur;}pcur = pcur->next;}return NULL;  //找不到就返回空指针
}

然后可以写插入的函数了:

void SLInsert(SLNode** pphead, SLNode* pos, SLTypeDate x) {assert(pphead);assert(*pphead);assert(pos);SLNode* node = SLFindNode(*pphead,pos);SLNode* prev = *pphead;if (*pphead = pos) {  //只有一个节点或插入位置位于第一个节点之前的情况node->next = *pphead;*pphead = node;return;}//多个节点的情况while (prev->next != pos) {prev = prev->next;}node->next = pos;prev->next = node;
}

注:你画图就会发现只有一个节点or插入第一个节点之前的位置,这两种情况下 pos 和 *pphead 都指向第一个节点。


🥝指定位置之后插入

这个就比上面那个简单多了,因为现在pos节点已知,那就少了遍历的过程。(pos后面的节点可以通过 next 找到,但是pos之前的节点只能遍历得到)
不过这次需要注意的插入的次序,比如现在节点node和pos已知,插入时,应该先让node的next指向第三个节点,然后再让 pos 的 next 指向 node,如果反过来的话,那第三个节点可就找不到了(即pos->next)
在这里插入图片描述
这个函数的实现很简单的,你自己尝试一下。


🥝删除指定节点

如图,要删除pos这个节点
在这里插入图片描述
首先我们得找到pos前面的节点 prev,然后让prev->next = pos->next,完事之后这个pos就没啥“利用价值”了,把它 free 掉。
不过前面做了这么多个接口之后,你应该也会考虑到一些特殊情况,比如要删除的pos就是第一个节点。
在这里插入图片描述

这种情况下我们就先弄一个pcur 保存第一个节点的地址,然后*pphead = (*pphead)->next,再把pcur指向的空间free掉并置空。
这里有一个要注意的点:解引用操作符优先度比“->”低,所以要用括号给括起来,不然会报错。

void SLErase(SLNode** pphead, SLNode* pos) {assert(*pphead);assert(pphead);assert(pos);if (*pphead == pos) {*pphead = (*pphead)->next;free(pos);pos = NULL;return;}SLNode* prev = *pphead;while (prev->next != pos) {prev = prev->next;}prev->next = pos->next;free(pos);pos = NULL;
}

🍌销毁

使用完之后,就要把链表给销毁了。

void SLDestroy(SLNode** pphead) {assert(pphead);SLNode* pcur = *pphead;while (*pphead) {pcur = *pphead;*pphead = (*pphead)->next;free(pcur);pcur = NULL;}
}

🍉源码

🍌头文件:声明部分

#pragma once
#include<stdlib.h>
#include<stdio.h>
#include<assert.h>typedef int SLTypeDate;
typedef struct SListNode {SLTypeDate data;struct SListNode* next;
}SLNode;void SLPrint(SLNode* phead);void SLPushBack(SLNode** pphead, SLTypeDate x);void SLPushFront(SLNode** pphead, SLTypeDate x);void SLPopFront(SLNode** pphead);void SLPopBack(SLNode** pphead);void SLInsert(SLNode** pphead, SLNode* pos, SLTypeDate x);SLNode* SLFindNode(SLNode** pphead, SLTypeDate x);void SLInsertAfter(SLNode* pos, SLTypeDate x);void SLErase(SLNode** pphead, SLNode* pos);void SLDestroy(SLNode** pphead);

🍌源文件:功能实现部分

#include"SList.h"void SLPrint(SLNode* phead) {SLNode* pcur = phead;while (pcur) {printf("%d ->", pcur->data);pcur = pcur->next;}printf("NULL\n");
}SLNode* SLBuyNode(SLTypeDate x) {  //申请一个节点,并将想要存储的数据存进去SLNode* node = (SLNode*)malloc(sizeof(SLNode));node->data = x;node->next = NULL;return node;
}void SLPushBack(SLNode** pphead,SLTypeDate x) {assert(pphead);SLNode* node = SLBuyNode(x);if (*pphead == NULL) {  //phead为空说明此时链表为空,那就直接插入*pphead = node;  //让node是第一个节点的地址return;}//若不为空,则先找到链表的最后一个节点,再插入SLNode* pcur = *pphead;  //老样子,用临时变量pcur去走循环while (pcur->next) {pcur = pcur->next;}//此时pcur指向最后一个节点pcur->next = node;
}void SLPushFront(SLNode** pphead, SLTypeDate x) {assert(pphead);SLNode* node = SLBuyNode(x);node->next = *pphead;*pphead = node;
}void SLPopBack(SLNode** pphead) {assert(pphead);assert(*pphead);  //如果节点地址为空,那么说明节点为空(为空说明没有指向),而节点为空时显然不能删除SLNode* prev = NULL;SLNode* ptail = *pphead;if ((*pphead)->next == NULL) {free(*pphead);*pphead = NULL;return;}while (ptail->next) {prev = ptail;ptail = ptail->next;}free(ptail);ptail = NULL;
}void SLPopFront(SLNode** pphead) {assert(pphead);assert(*pphead);SLNode* pcur = *pphead;*pphead = (*pphead)->next;free(pcur);//pcur = (*pphead)->next;//free(*pphead);//*pphead = pcur;pcur = NULL;
}SLNode* SLFindNode(SLNode** pphead, SLTypeDate x) {assert(pphead);SLNode* pcur = *pphead;while (pcur) {if (pcur->data == x) {return pcur;}pcur = pcur->next;}return NULL;  //找不到就返回空指针
}//在指定位置前插入
void SLInsert(SLNode** pphead, SLNode* pos, SLTypeDate x) {assert(pphead);assert(*pphead);assert(pos);SLNode* node = SLFindNode(*pphead,pos);SLNode* prev = *pphead;if (*pphead = pos) {  //只有一个节点或插入位置位于第一个节点之前的情况node->next = *pphead;*pphead = node;return;}//多个节点的情况while (prev->next != pos) {prev = prev->next;}node->next = pos;prev->next = node;
}void SLInsertAfter(SLNode* pos, SLTypeDate x) {assert(pos);SLNode* node = SLBuyNode(x);node->next = pos->next;pos->next = node;
}void SLErase(SLNode** pphead, SLNode* pos) {assert(*pphead);assert(pphead);assert(pos);if (*pphead == pos) {*pphead = (*pphead)->next;free(pos);pos = NULL;return;}SLNode* prev = *pphead;while (prev->next != pos) {prev = prev->next;}prev->next = pos->next;free(pos);pos = NULL;}void SLDestroy(SLNode** pphead) {assert(pphead);SLNode* pcur = *pphead;while (*pphead) {pcur = *pphead;*pphead = (*pphead)->next;free(pcur);pcur = NULL;}
}

相关文章:

数据结构:单链表

文章目录 &#x1f349;前言&#x1f349;基本概念&#x1f349;链表的分类&#x1f34c;单链表节点的结构&#x1f34c;创建节点&#x1f34c;打印链表&#x1f34c;插入和删除&#x1f95d;尾插&#x1f95d;头插&#x1f95d;尾删&#x1f95d;头删&#x1f95d;指定位置之前…...

官媒代运营:让大众倾听品牌的声音

在当今数字时代&#xff0c;媒体的影响力和多样性远远超出了以往的范畴。品牌和企业越来越依赖媒体来传播信息、建立声誉以及与大众互动。而媒体矩阵成为了现代品牌传播的关键策略&#xff0c;使大众能够倾听品牌的声音。媒体矩阵&#xff1a;多元化的传播渠道 媒体矩阵是指利…...

postgresql 实现计算日期间隔排除周末节假日方案

前置条件&#xff1a;需要维护一张节假日日期表。例如创建holiday表保存当年假期日期 CREATE TABLE holiday (id BIGINT(10) ZEROFILL NOT NULL DEFAULT 0,day TIMESTAMP NULL DEFAULT NULL,PRIMARY KEY (id) ) COMMENT假期表 COLLATEutf8mb4_0900_ai_ci ;返回日期为xx日xx时x…...

金融工作怎么做?低代码如何助力金融行业

10月30日至31日&#xff0c;中央金融工作会议在北京举行。金融是国民经济的“血脉”&#xff0c;是国家核心竞争力的重要组成部分。会议指出&#xff0c;党的十八大以来&#xff0c;在党中央集中统一领导下&#xff0c;金融系统有力支撑经济社会发展大局&#xff0c;坚决打好防…...

基于springboot实现智慧外贸平台系统【项目源码+论文说明】计算机毕业设计

基于springboot实现智慧外贸平台系统演示 摘要 网络的广泛应用给生活带来了十分的便利。所以把智慧外贸管理与现在网络相结合&#xff0c;利用java技术建设智慧外贸平台&#xff0c;实现智慧外贸的信息化。则对于进一步提高智慧外贸管理发展&#xff0c;丰富智慧外贸管理经验能…...

带头+双向+循环链表

前言&#xff1a; 前面我们已经学习了单链表的结构及其功能特点&#xff0c;也了解了单链表在实现一些功能时出现的一些缺点&#xff0c;比如在删除某个节点前面一个节点时就需要再开一个变量来存放前面一个节点的信息&#xff0c;这样就显得不灵活&#xff0c;为了使链表实现功…...

Leetcode_2:两数相加

题目描述&#xff1a; 给你两个 非空 的链表&#xff0c;表示两个非负的整数。它们每位数字都是按照 逆序 的方式存储的&#xff0c;并且每个节点只能存储 一位 数字。 请你将两个数相加&#xff0c;并以相同形式返回一个表示和的链表。 你可以假设除了数字 0 之外&#xff…...

Pytorch实战教程(一)-神经网络与模型训练

0. 前言 人工神经网络 (Artificial Neural Network, ANN) 是一种监督学习算法,其灵感来自人类大脑的运作方式。类似于人脑中神经元连接和激活的方式,神经网络接受输入,通过某些函数在网络中进行传递,导致某些后续神经元被激活,从而产生输出。函数越复杂,网络对于输入的数…...

【MySQL】手把手教你centos7下载MySQL

centos7下载MySQL 前言正式开始卸载不需要的环境&#xff08;如果你之前没有安装过数据库相关的东西可以跳过&#xff09;下载mysql登录mysql登陆⽅法⼀【不⾏就下⼀个】登陆⽅法⼆【不⾏就下⼀个】登录方式三 前言 安装和卸载MySQL都用系统的root权限&#xff0c;更方便一点&…...

openlayers

OpenLayers使用_openlayers中文官网-CSDN博客...

力扣每日一道系列 --- LeetCode 88. 合并两个有序数组

&#x1f4f7; 江池俊&#xff1a; 个人主页 &#x1f525;个人专栏&#xff1a; ✅数据结构探索 ✅LeetCode每日一道 &#x1f305; 有航道的人&#xff0c;再渺小也不会迷途。 文章目录 思路1&#xff1a;暴力求解思路2&#xff1a;原地合并 LeetCode 88. 合并两个有序数组…...

Android Studio(项目收获)

取消按钮默认背景色 像按钮默认背景色为深蓝色&#xff0c;即使使用了background属性指定颜色也不能生效。 参考如下的解决方法&#xff1a; 修改/res/values/themes.xml中的指定内容如下&#xff1a; <style name"Theme.TianziBarbecue" parent"Theme.Mater…...

MQ写满的情况如何处理?

**MQ&#xff08;Message Queue&#xff09;**写满的情况通常指消息队列中的存储空间已经被用尽&#xff0c;无法再接收新的消息。处理MQ写满的情况涉及到多个方面&#xff0c;包括监控、调整配置、增加资源、以及处理积压消息等。下面是一些处理MQ写满的 常见方法&#xff1a;…...

点名(缺失的数字),剑指offer,力扣

目录 我们直接看题解吧&#xff1a; 审题目事例提示&#xff1a; 方法&#xff1a; 解题思路&#xff08;二分法&#xff09;&#xff1a; 代码&#xff1a; 方法二&#xff1a;直接遍历 题目地址 LCR 173. 点名 - 力扣&#xff08;LeetCode&#xff09; 今天刷点名&#xff08…...

云安全—Dashboard 攻击面

0x00 前言 众所周知&#xff0c;如果只是一味的REST接口或者命令行话的操作方式&#xff0c;就会变相的提高操作门款&#xff0c;并且不会有很好的呈现方式&#xff0c;所以就有了web ui的方式&#xff0c;也就是Dashboar面板&#xff0c;本篇主要讨论一下关于Dashboar面板的概…...

FCOS难点记录

FCOS 中有计算 特征图&#xff08;Feature map中的每个特征点到gt_box的左、上、右、下的距离&#xff09; 1、特征点到gt_box框的 左、上、右、下距离计算 x coords[:, 0] # h*w&#xff0c;2 即 第一列y coords[:, 1] l_off x[None, :, None] - gt_boxes[..., 0][:, No…...

java通过FTP跨服务器动态监听读取指定目录下文件数据

背景&#xff1a; 1、文件数据在A服务器&#xff08;windows&#xff09;&#xff08;不定期在指定目录下生成&#xff09;&#xff0c;项目应用部署在B服务器&#xff08;Linux&#xff09;&#xff1b; 2、项目应用在B服务器&#xff0c;监听A服务器指定目录&#xff0c;有新…...

5G边缘计算网关的功能及作用

5G边缘计算网关具有多种功能。 首先&#xff0c;它支持智能云端控制&#xff0c;可以通过5G/4G/WIFI等无线网络将采集的数据直接上云&#xff0c;实现异地远程监测控制、预警通知、报告推送和设备连接等工作。 其次&#xff0c;5G边缘计算网关可以采集各种数据&#xff0c;包…...

阿里云AIGC小说生成【必得京东卡】

任务步骤 此文真实可靠不做虚假宣传&#xff0c;绝对真实&#xff0c;可截图为证。 领取任务 链接&#xff08;复制到wx打开&#xff09;&#xff1a;#小程序://ITKOL/1jw4TX4ZEhykWJd 教程实践 打开函数计算控制台 应用->创建应用->人工智能->通义千问 AI 助手-…...

数据结构之AVL树

map/multimap/set/multiset这几个容器有个共同点是: 其底层都是按照二叉搜索树来实现的,但是普通的二叉搜索树有其自身的缺陷, 假如往树中插入的元素有序或者接近有序, 二叉搜索树就会退化成单支树, 时间复杂度会退化成O(N),因此map、set等关联式容器的底层结构是对二叉树进行了…...

AI-调查研究-01-正念冥想有用吗?对健康的影响及科学指南

点一下关注吧&#xff01;&#xff01;&#xff01;非常感谢&#xff01;&#xff01;持续更新&#xff01;&#xff01;&#xff01; &#x1f680; AI篇持续更新中&#xff01;&#xff08;长期更新&#xff09; 目前2025年06月05日更新到&#xff1a; AI炼丹日志-28 - Aud…...

大型活动交通拥堵治理的视觉算法应用

大型活动下智慧交通的视觉分析应用 一、背景与挑战 大型活动&#xff08;如演唱会、马拉松赛事、高考中考等&#xff09;期间&#xff0c;城市交通面临瞬时人流车流激增、传统摄像头模糊、交通拥堵识别滞后等问题。以演唱会为例&#xff0c;暖城商圈曾因观众集中离场导致周边…...

FastAPI 教程:从入门到实践

FastAPI 是一个现代、快速&#xff08;高性能&#xff09;的 Web 框架&#xff0c;用于构建 API&#xff0c;支持 Python 3.6。它基于标准 Python 类型提示&#xff0c;易于学习且功能强大。以下是一个完整的 FastAPI 入门教程&#xff0c;涵盖从环境搭建到创建并运行一个简单的…...

【网络安全产品大调研系列】2. 体验漏洞扫描

前言 2023 年漏洞扫描服务市场规模预计为 3.06&#xff08;十亿美元&#xff09;。漏洞扫描服务市场行业预计将从 2024 年的 3.48&#xff08;十亿美元&#xff09;增长到 2032 年的 9.54&#xff08;十亿美元&#xff09;。预测期内漏洞扫描服务市场 CAGR&#xff08;增长率&…...

MODBUS TCP转CANopen 技术赋能高效协同作业

在现代工业自动化领域&#xff0c;MODBUS TCP和CANopen两种通讯协议因其稳定性和高效性被广泛应用于各种设备和系统中。而随着科技的不断进步&#xff0c;这两种通讯协议也正在被逐步融合&#xff0c;形成了一种新型的通讯方式——开疆智能MODBUS TCP转CANopen网关KJ-TCPC-CANP…...

04-初识css

一、css样式引入 1.1.内部样式 <div style"width: 100px;"></div>1.2.外部样式 1.2.1.外部样式1 <style>.aa {width: 100px;} </style> <div class"aa"></div>1.2.2.外部样式2 <!-- rel内表面引入的是style样…...

【HTTP三个基础问题】

面试官您好&#xff01;HTTP是超文本传输协议&#xff0c;是互联网上客户端和服务器之间传输超文本数据&#xff08;比如文字、图片、音频、视频等&#xff09;的核心协议&#xff0c;当前互联网应用最广泛的版本是HTTP1.1&#xff0c;它基于经典的C/S模型&#xff0c;也就是客…...

处理vxe-table 表尾数据是单独一个接口,表格tableData数据更新后,需要点击两下,表尾才是正确的

修改bug思路&#xff1a; 分别把 tabledata 和 表尾相关数据 console.log() 发现 更新数据先后顺序不对 settimeout延迟查询表格接口 ——测试可行 升级↑&#xff1a;async await 等接口返回后再开始下一个接口查询 ________________________________________________________…...

招商蛇口 | 执笔CID,启幕低密生活新境

作为中国城市生长的力量&#xff0c;招商蛇口以“美好生活承载者”为使命&#xff0c;深耕全球111座城市&#xff0c;以央企担当匠造时代理想人居。从深圳湾的开拓基因到西安高新CID的战略落子&#xff0c;招商蛇口始终与城市发展同频共振&#xff0c;以建筑诠释对土地与生活的…...

搭建DNS域名解析服务器(正向解析资源文件)

正向解析资源文件 1&#xff09;准备工作 服务端及客户端都关闭安全软件 [rootlocalhost ~]# systemctl stop firewalld [rootlocalhost ~]# setenforce 0 2&#xff09;服务端安装软件&#xff1a;bind 1.配置yum源 [rootlocalhost ~]# cat /etc/yum.repos.d/base.repo [Base…...