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

【数据结构与算法——TypeScript】图结构(Graph)

【数据结构与算法——TypeScript】

图结构(Graph)

认识图结构以及特性

什么是图?

  • 在计算机程序设计中,图结构 也是一种非常常见的数据结构。
    • 但是,图论其实是一个非常大的话题
  • 认识一下关于图的一些内容
    • 图的抽象数据类型
    • 一些算法实现。
  • 什么是图?
    • 图结构是一种与树结构有些相似的数据结构。
    • 图论数学的一个分支,并且,在数学的概念上,树是图的一种。
    • 它以图为研究对象,研究 顶点 组成的图形的数学理论和方法
    • 主要研究的目的是事物之间的关系顶点代表事物代表两个事物间的关系
  • 我们知道树可以用来模拟很多现实的数据结构
    • 比如: 家谱/公司组织架构等等
  • 那么图长什么样子?
  • 或者什么样的数据使用图来模拟更合适呢?

图的现实案例

  • 人与人之间的关系网
    • 甚至科学家们在观察人与人之间的关系网时,还发现了六度空间理论
  • 六度空间理论
    • 理论上认为世界上任何两个互相不认识的两人。
    • 只需要很少的中间人就可以建立起联系。
    • 并非一定要经过6步,只是需要很少的步骤。
  • 地铁图

在这里插入图片描述

  • 村庄之间的关系网

在这里插入图片描述

再次 什么是图?

  • ❤️‍🔥 那么,什么是图呢?
    • 我们会发现,上面的节点(其实图中叫顶点Vertex)之间的关系,是不能使用树来表示
    • 使用任何的树结构都不可以模拟。
    • 这个时候,我们就可以使用图来模拟它们。
  • ❤️‍🔥 图通常有什么特点呢?
    • 💚 一组顶点:通常用 V (Vertex) 表示顶点的集合
    • 💚 一组边:通常用 E (Edge) 表示边的集合
      • ✓ 边是顶点和顶点之间的连线
      • ✓ 边可以是有向的,也可以是无向的。
      • ✓ 比如A — B,通常表示无向。 A --> B,通常表示有向

欧拉和七拉问题解法

历史故事

  • 8世纪著名古典数学问题之一。
    • 在哥尼斯堡的一个公园里,有七座桥普雷格尔河中两个岛岛与河岸连接起来(如图)。

      在这里插入图片描述

    • 有人提出问题: 一个人怎样才能不重复、不遗漏地一次走完七座桥,最后回到出发点。

  • 1735年,有几名大学生写信给当时正在俄罗斯的彼得斯堡科学院任职的瑞典天才数学家欧拉,请他帮忙解决这一问题。
    • 欧拉在亲自观察了哥伦斯堡的七桥后,认真思考走法,但是始终没有成功,于是他怀疑七桥问题是不是无解的。
    • 1736年29岁的欧拉向 彼得斯堡 科学院递交了《哥尼斯堡的七座桥》的论文,在解答问题的同时,开创了数学的一个新的分支——图论与几何拓扑,也由此展开了数学史上的新历程。

欧拉解答

  • 他不仅解决了该问题,并且给出了 连通图 可以一笔画的充要条件是:
    • 奇点的数目不是0个就是2 个
    • 连到一点的边的数目如果是奇数条,就称为奇点
    • 如果是偶数条就称为偶点
    • 要想一笔画成,必须中间点均是偶点
    • 也就是有来路必有另一条去路奇点只可能在两端,因此任何图能一笔画成,奇点要么没有,要么在两端
  • 个人思考:
    • 欧拉在思考这个问题的时候,并不是针对某一个特性的问题去考虑,而是将岛和桥抽象成了点和线
    • 抽象是数学的本质,而编程我们也一再强调抽象的重要性。
    • 汇编语言是对机器语言的抽象,高级语言是对汇编语言的抽象。
    • 操作系统是对硬件的抽象,应用程序在操作系统的基础上构建。

在这里插入图片描述

图结构的常见术语

关于术语的概述

  • 我们在学习树的时候,树有很多的相关术语

  • 了解这些术语有助于我们更好的理解树结构

  • 我们也来学习一下图相关的术语

    • 但是图的术语其实非常多,如果你找一本专门讲图的各个方面的书籍,会发现 只是术语 就可以 占据满满的一个章节。
    • 这里,我们先介绍几个比较常见的术语。
  • 我们先来看一个抽象出来的图
     用数字更容易我们从整体来观察整个图结构
    在这里插入图片描述

术语

  1. 顶点:

    • 顶点刚才我们已经介绍过了,表示图中的一个节点
    • 比如地铁站中某个站/多个村庄中的某个村庄/互联网中的某台主机/人际关系中的人
  2. 边:

    • 边刚才我们也介绍过了,表示顶点和顶点之间的连线
    • 比如地铁站中两个站点之间的直接连线,就是一个边。
    • ❗️ 注意: 这里的边不要叫做路径,路径有其他的概念,待会儿我们会介绍到。
    • 之前的图中: 0 - 1有一条边,1 - 2有一条边,0 - 2没有边。
  3. 相邻顶点:

    • 由一条边连接在一起的顶点称为相邻顶点
    • 比如0 - 1是相邻的,0 - 3是相邻的。 0 - 2是不相邻的。
  4. 度:

    • 一个顶点的度是相邻顶点的数量。
    • 比如0顶点和其他两个顶点相连,0顶点的度是2
    • 比如1顶点和其他四个顶点相连,1顶点的度是4
  5. 路径:

    • 路径是顶点v1,v2…,vn的一个连续序列,比如上图中0 1 5 9就是一条路径。
    • 简单路径: 简单路径要求不包含重复的顶点。 比如 0 1 5 9 是一条简单路径。
    • 回路: 第一个顶点和最后一个顶点相同的路径称为回路。 比如 0 1 5 6 3 0
  6. 无向图:

    • 上面的图就是一张无向图,因为所有的边都没有方向
    • 比如 0 - 1之间有变,那么说明这条边可以保证 0 -> 1,也可以保证 1 -> 0。
  7. 有向图:

    • 有向图表示的图中的边是有方向的。
    • 比如 0 -> 1,不能保证一定可以 1 -> 0,要根据方
      向来定。

在这里插入图片描述

  1. 无权图:

    • 我们上面的图就是一张无权图(边没有携带权重)
    • 我们上面的图中的边是没有任何意义
    • 不能说 0 - 1的边,比4 - 9的边更远或者用的时间更长。
  2. 带权图:

    • 带权图表示边有一定的权重
    • 这里的权重可以是任意你希望表示的数据
      ✓ 比如距离或者花费的时间或者票价

图的表示

  • 怎么在程序中表示图呢?
    • 我们知道一个图包含很多顶点,另外包含顶点和顶点之间的连线(边)
    • 这两个都是非常重要的图信息,因此都需要在程序中体现出来
  • 顶点的表示相对简单,我们先讨论顶点的表示。
    • 上面的顶点,我们抽象成了1 2 3 4,也可以抽象成A B C D。
    • 在后面的案例中,我们使用A B C D。
    • 那么这些A B C D我们可以使用一个数组来存储起来(存储所有的顶点)
    • 当然,A,B,C,D也可以表示其他含义的数据(比如村庄的名字).
  • 那么边怎么表示呢?
    • 因为边是两个顶点之间的关系,所以表示起来会稍微麻烦一些。
    • 下面,我们具体讨论一下变常见的表示方式。

邻接矩阵和邻接表

邻接矩阵

  • 一种比较常见的表示图的方式: 邻接矩阵
    • 邻接矩阵让每个节点和一个整数项关联,该整数作为数组的下标值
    • 我们用一个二维数组来表示顶点之间的连接
    • 二维数组 [0][2] -> A -> C
  • 画图演示:

在这里插入图片描述

  • 图片解析:
    • 在二维数组中,0表示没有连线,1表示有连线。
    • 通过二维数组,我们可以很快的找到一个顶点和哪些顶点有连线。(比如A顶点,只需要遍历第一行即可)
    • 另外,A - A,B - B(也就是顶点到自己的连线),通常使用0表示。
  • 邻接矩阵的问题:
    • 邻接矩阵还有一个比较严重的问题,就是如果图是一个稀疏图
    • 那么矩阵中将存在大量的0,这意味着我们浪费了计算机存储空间来表示根本不存在的边

邻接表

  • 另外一种常用的表示图的方式: 邻接表

    • 邻接表由图中每个顶点以及和顶点相邻的顶点列表组成。
    • 这个列表有很多种方式来存储: **数组/链表/字典(哈希表)**都可以。
  • 画图演示
    在这里插入图片描述

  • 图片解析:

    • 其实图片比较容易理解。
    • 比如我们要表示和A顶点有关联的顶点(边),A和B/C/D有边,
    • 那么我们可以通过A找到对应的数组/链表/字典,再取出其中的内容就可以啦。
  • 邻接表的问题:

    • 邻接表计算"出度"是比较简单的(出度: 指向别人的数量,入度: 指向自己的数量)
    • 邻接表如果需要计算有向图的"入度",那么是一件非常麻烦的事情。
    • 它必须构造一个**“逆邻接表”,才能有效的计算“入度”。但是开发中“入度”**相对用的比较少。

创建图类

  • 先创建Graph类
  • 👩🏻‍💻 代码解析
    • 创建Graph的构造函数,这个我们在封装其他数据结构的时候已经非常熟悉了。
  • 定义了两个属性:
    ✓ vertexes: 用于存储所有的顶点,我们说过使用一个数组来保存。
    ✓ adjList: adj是adjoin的缩写,邻接的意思。 adjList用于存储所有的边,我们这里采用邻接表的形式。
  • 之后,我们来定义一些方法以及实现一些算法就是一个完整的图类了。
    class Graph<T> {// 顶点vertexes: T[] = [];// 邻接表adjList: Map<T, T[]> = new Map();}

添加方法

  • 现在我们来增加一些添加方法。
    • 添加顶点: 可以向图中添加一些顶点。
    • 添加边: 可以指定顶点和顶点之间的边。
  • 添加顶点
    • 👩🏻‍💻 代码解析:
      • 我们将添加的顶点放入到数组中。
      • 另外,我们给该顶点创建一个数组[],该数组用于存储顶点连接的所有的边.(回顾邻接表的实现方式)
  • 添加边
    • 👩🏻‍💻 代码解析:
      • 添加边需要传入两个顶点,因为边是两个顶点之间的边,边不可能单独存在。
      • 根据顶点v取出对应的数组,将w加入到它的数组中。
      • 根据顶点w取出对应的数组,将v加入到它的数组中。
      • 因为我们这里实现的是无向图,所以边是可以双向的。
  // 添加顶点addVertex(vertex: T) {//   将顶点添加到顶点数组中保存this.vertexes.push(vertex);//   创建一个邻接表的数组this.adjList.set(vertex, []);}addEdge(v1: T, v2: T) {this.adjList.get(v1)?.push(v2);this.adjList.get(v2)?.push(v1);}

printEdges方法

  • 为了能够正确的显示图的结果,我们来实现一下Graph的printEdges方法

  • 测试代码:

      const graph = new Graph();graph.addVertex('A');graph.addVertex('B');graph.addVertex('C');graph.addVertex('D');graph.addVertex('E');graph.addVertex('F');graph.addVertex('G');graph.addVertex('H');graph.addVertex('I');graph.addEdge('A', 'B');graph.addEdge('A', 'C');graph.addEdge('A', 'D');graph.addEdge('C', 'D');graph.addEdge('C', 'G');graph.addEdge('D', 'G');graph.addEdge('D', 'H');graph.addEdge('B', 'E');graph.addEdge('B', 'F');graph.addEdge('E', 'I');graph.printEdges();
    • 运行结果:
      [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fK63qbI7-1692005552724)(/Volumes/web/数据结构与算法(ts)/截图/截屏2023-08-14 15.37.06.png “运行结果”)]
      在这里插入图片描述

图的遍历

图的遍历思想

图的遍历思想和树的遍历思想是一样的。
图的遍历意味着需要将图中每个顶点访问一遍,并且不能有重复的访问

  • 有两种算法可以对图进行遍历
    • 广度优先搜索(Breadth-First Search,简称BFS)
    • 深度优先搜索(Depth-First Search,简称DFS)
  • 两种遍历算法,都需要明确指定第一个被访问的顶点
    • 它们的遍历过程分别是怎么样呢?
    • 我们以一个迷宫中关灯为例。
    • 现在需要你进入迷宫,将迷宫中的灯一个个关掉,你会怎么关呢?

遍历的思想

  • 两种算法的思想:
    • BFS: 基于队列,入队列的顶点先被探索。
    • DFS: 基于栈或使用递归,通过将顶点存入栈中,顶点是沿着路径被探索的,存在新的相邻顶点就去访问。
  • 为了记录顶点是否被访问过,我们使用三种颜色来反应它们的状态
    • 白色: 表示该顶点还没有被访问。
    • 灰色: 表示该顶点被访问过,但并未被探索过。
    • 黑色: 表示该顶点被访问过且被完全探索过。
  • 或者我们也可以使用Set来存储被访问过的节点。

广度优先搜索

  • 广度优先搜索算法的思路 💡:

    • 广度优先算法会从指定的第一个顶点开始遍历图,先访问其所有的相邻点,就像一次访问图的一层
    • 换句话说,就是先宽后深的访问顶点
  • 图解BFS
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-mNFb1uIZ-1692005552726)(/Volumes/web/数据结构与算法(ts)/画图/图/广度优先搜索.png “广度优先搜索”)]
    在这里插入图片描述

    ◼ 广度优先搜索的实现:
    ◼ 创建一个队列Q。

  • 代码 💻 :

  // 广度优先bfs() {// 1. 判断是否有顶点if (this.vertexes.length === 0) return;// 2. 创建队列结构来访问每个顶点const queue: T[] = [];queue.push(this.vertexes[0]);// 3. 创建Set,来记录一个顶点是否被访问过const visited = new Set();visited.add(this.vertexes[0]);// 4. 遍历队列中每一个顶点while (queue.length) {//  4.1 访问队列中第一个顶点const vertex = queue.shift()!;console.log(vertex);//  4.2 取出相邻的顶点const neighbors = this.adjList.get(vertex);if (!neighbors) continue;for (const neighbor of neighbors) {if (!visited.has(neighbor)) {visited.add(neighbor);queue.push(neighbor);}}}}
  • 运行结果:

在这里插入图片描述

深度优先搜索

  • 深度优先搜索的思路:

    • 深度优先搜索算法将会从第一个指定的顶点开始遍历图,沿着路径知道这条路径最后被访问了。
    • 接着原路回退并探索下一条路径。
  • 深度优先搜索

    • 深度优先搜索算法的实现:
      • 广度优先搜索算法我们使用的是队列,这里可以使用完成,也可以使用递归。
  • 图DFS

    在这里插入图片描述

  • 代码 💻 :

  // 深度优先dfs() {// 1. 判断有没有顶点,没有直接返回if (this.vertexes.length === 0) return;// 2.创建栈结构const stack: T[] = [];stack.push(this.vertexes[0]);// 3. 创建Set结构const visited = new Set();visited.add(this.vertexes[0]);// 4. 从第一个顶点开始访问while (stack.length) {const vertex = stack.pop()!;console.log(vertex);// 取出相邻的顶点const neighbors = this.adjList.get(vertex);if (!neighbors) continue;for (let i = neighbors.length - 1; i >= 0; i--) {const nei = neighbors[i];if (!visited.has(nei)) {visited.add(nei);stack.push(nei);}}}}
  • 运行结果:

在这里插入图片描述

图结构的常见建模

  • 对交通流量建模
    • 顶点可以表示街道的十字路口,边可以表示街道。
    • 加权的边可以表示限速或者车道的数量或者街道的距离。
    • 建模人员可以用这个系统来判定最佳路线以及最可能堵车的街道。
  • 对飞机航线建模
    • 航空公司可以用图来为其飞行系统建模。
    • 将每个机场看成顶点,将经过两个顶点的每条航线看作一条边。
    • 加权的边可以表示从一个机场到另一个机场的航班成本,或两个机场间的距离。
    • 建模人员可以利用这个系统有效的判断从一个城市到另一个城市的最小航行成本。

相关文章:

【数据结构与算法——TypeScript】图结构(Graph)

【数据结构与算法——TypeScript】 图结构(Graph) 认识图结构以及特性 什么是图? 在计算机程序设计中&#xff0c;图结构 也是一种非常常见的数据结构。 但是&#xff0c;图论其实是一个非常大的话题 认识一下关于图的一些内容 图的抽象数据类型一些算法实现。 什么是图?…...

C语言字符串拷贝函数详解及示例代码

目录 简介字符串拷贝函数 strcpy字符串拷贝函数 strcpy_s使用示例注意事项结束语 1. 简介 字符串拷贝是C语言中常用的操作之一。当需要将一个字符串复制到另一个字符串数组中时&#xff0c;可以使用字符串拷贝函数来实现。C语言提供了多种字符串拷贝函数&#xff0c;其中最常…...

IntelliJ IDEA热部署:JRebel插件的安装与使用

热部署 概述JRebel 概述 热部署&#xff0c;指修改代码后&#xff0c;无需停止应用程序&#xff0c;即可使修改后的代码生效&#xff0c;其有利于提高开发效率。 热部署方式&#xff1a; 手动热部署&#xff1a;修改代码后&#xff0c;重新编译项目&#xff0c;然后启动应用程…...

iTOP-3568开发板使用OpenCV处理图像-颜色转换

本小节代码在配套资料“iTOP-3568 开发板\03_【iTOP-RK3568 开发板】指南教程 \04_OpenCV 开发配套资料\05”目录下&#xff0c;如下图所示&#xff1a; cv2.cvtColor()函数功能&#xff1a; 将一幅图像从一个色彩空间转换到另一个色彩空间。 函数原型&#xff1a; cv2.cvt…...

Python技巧----解压序列/可迭代对象赋值给多个变量

1 、解压序列赋值给多个变量 我们这里说的不是正常情况的一一赋值比如下面 >>> data = [ ACME, 5, 9, (2012, 12, 1) ] >>> name, shares, price, date = data >>> name ACME...

16.3.2 【Linux】程序的管理

程序之间是可以互相控制的。举例来说&#xff0c;你可以关闭、重新启动服务器软件&#xff0c;服务器软件本身是个程序&#xff0c; 你既然可以让她关闭或启动&#xff0c;当然就是可以控制该程序。 使用kill-l或者是man 7 signal可以查询到有多少个signal。主要的讯号代号与名…...

Linux命令200例:date用于显示和设置系统的日期和时间

&#x1f3c6;作者简介&#xff0c;黑夜开发者&#xff0c;全栈领域新星创作者✌。CSDN专家博主&#xff0c;阿里云社区专家博主&#xff0c;2023年6月csdn上海赛道top4。 &#x1f3c6;数年电商行业从业经验&#xff0c;历任核心研发工程师&#xff0c;项目技术负责人。 &…...

excel入门

上下左右移动 enter:换行&#xff0c;向下移动 shiftenter:向上移动 tab:向右移动 shifttab:向左移动 合并居中操作 开始-》合并居中 CtrlM 内容过长盖过了下一个单元格内容 双击列与列之间线 同时修改多行或者多列宽度或者高度 修改单行高度宽度 选中某一行拉取指定高…...

单模光纤模场强度分布以及高斯近似的MATLAB仿真

已知纤芯半径5um&#xff0c;数值孔径NA 0.1&#xff0c;波长 用波长和数值孔径计算归一化常数V 之前我们在单模光纤特征方程及其MATLAB数值求解中&#xff0c;用线性关系拟合过V和W&#xff0c;这里直接用拟合结果 U用V和W计算 clc clear close alla 5e-6;%纤芯半径 NA …...

Springboot 在 redis 中使用 BloomFilter 布隆过滤器机制

一、导入SpringBoot依赖 在pom.xml文件中&#xff0c;引入Spring Boot和Redis相关依赖 <!-- Google Guava 使用google的guava布隆过滤器实现--><dependency><groupId>com.google.guava</groupId><artifactId>guava</artifactId><vers…...

什么是管理的本质?

管理不是一门硬科学。与&#xff08;通常&#xff09;存在正确答案的化学或代数不同&#xff0c;管理是流动的&#xff0c;主观的&#xff0c;并且对于如何运用其原理存在不同的观点。但究竟什么是管理&#xff1f;大多数学者都有相同定义的变体&#xff0c;包括利用资源来实现…...

02:STM32--EXTI外部中断

目录 一:中断 1:简历 2:AFIO 3:EXTI ​编辑 4:NVIC基本结构 5:使用步骤 二:中断的应用 A:对外式红外传感计数器 1:连接图​编辑 2:函数介绍 3:硬件介绍 4:计数代码 B;旋转编码计数器 1:连接图 2:硬件介绍 3:旋转编码器代码: 一:中断 1:简历 中断&#xff1a;在主程…...

CLickhouse核心特性

目录 CLickhouse核心特性 1 完备的DBMS功能 2 列式存储与数据压缩 3 向量化执行引擎 4 关系模型与SQL查询 5 多样化的表引擎 6 多线程与分布式 7 多主架构 8 在线查询 9 数据分片与分布式查询 Clickhouse适用场景 Clickhouse不适用场景 Clickhouse名称含义 CLickh…...

如何运用小程序技术闭环运营链路?

如何通过线上小程序获取用户线索&#xff0c;提高企业抗风险能力&#xff0c;建立有效的营销数字化系统一直是困扰每一个小程序开发者与运营者的问题。 当我们选择使用小程序设计自己的运营流程时&#xff0c;从「推广」到「转化」&#xff0c;再到最终的「留存」都是运营过程…...

使用chatGPT-4 畅聊量子物理学(二)

Omer 量子力学的主导哲学或模型或解释是什么&#xff1f; ChatGPT 量子力学是一门描述微观世界中粒子行为的物理学理论&#xff0c;但它的解释和哲学观点在学术界存在多种不同的观点和争议。以下是几种主要的哲学观点或解释&#xff1a; 哥本哈根解释&#xff1a;这是最为广泛…...

读《Flask Web开发实战》(狼书)笔记 | 第1、2章

前言 2023-8-11 以前对网站开发萌生了想法&#xff0c;又有些急于求成&#xff0c;在B站照着视频敲了一个基于flask的博客系统。但对于程序的代码难免有些囫囵吞枣&#xff0c;存在许多模糊或不太理解的地方&#xff0c;只会照葫芦画瓢。 而当自己想开发一个什么网站的时&…...

Tomcat+Http+Servlet

文章目录 1.HTTP1.1 请求和响应HTTP请求&#xff1a;请求行请求头请求体HTTP响应&#xff1a;响应行&#xff08;状态行&#xff09;响应头响应体 2. Apache Tomcat2.1 基本使用2.2 IDEA中创建 Maven Web项目2.3 IDEA中使用Tomcat 3. Servlet3.1 Servlet快速入门3.2 Servlet执行…...

Leaflet入门,Leaflet如何实现vue双向绑定数据添加到图片标记物到地图上,动态根据vue数据更新到地图上以及鼠标经过标记物显示提示框

前言 本章使用Leaflet的vue2-leaflet或者vue-leaflet插件方式实现vue数据绑定地图数据,实现地图标记物与vue数据的双向联动更新,以及鼠标经过标记物显示提示框功能。 实现效果演示 vue如何使用Leaflet vue2如何使用:《Leaflet入门,如何使用vue2-leaflet实现vue2双向绑定…...

C++设计模式结构型之代理模式

一、概述 代理模式是一种结构型模式&#xff0c;在很多不同的场合具有广泛的分类和应用。其主要实现的思想是在客户端和真正要访问的对象之间引入一个 代理对象&#xff08;间接层&#xff09;&#xff0c;于是&#xff0c;以往客户端对真正对象的访问现在变成了通过代理对…...

使用PHP实现实时聊天功能的匿名聊天与加密传输

使用PHP实现实时聊天功能的匿名聊天与加密传输 随着互联网的发展&#xff0c;人与人之间的交流方式也发生了天翻地覆的变化。其中&#xff0c;实时聊天功能成为了一种越来越受欢迎的交流方式。对于很多网站来说&#xff0c;提供匿名聊天功能能够吸引更多的用户参与&#xff0c…...

谷歌浏览器插件

项目中有时候会用到插件 sync-cookie-extension1.0.0&#xff1a;开发环境同步测试 cookie 至 localhost&#xff0c;便于本地请求服务携带 cookie 参考地址&#xff1a;https://juejin.cn/post/7139354571712757767 里面有源码下载下来&#xff0c;加在到扩展即可使用FeHelp…...

Linux链表操作全解析

Linux C语言链表深度解析与实战技巧 一、链表基础概念与内核链表优势1.1 为什么使用链表&#xff1f;1.2 Linux 内核链表与用户态链表的区别 二、内核链表结构与宏解析常用宏/函数 三、内核链表的优点四、用户态链表示例五、双向循环链表在内核中的实现优势5.1 插入效率5.2 安全…...

Spring Boot 实现流式响应(兼容 2.7.x)

在实际开发中&#xff0c;我们可能会遇到一些流式数据处理的场景&#xff0c;比如接收来自上游接口的 Server-Sent Events&#xff08;SSE&#xff09; 或 流式 JSON 内容&#xff0c;并将其原样中转给前端页面或客户端。这种情况下&#xff0c;传统的 RestTemplate 缓存机制会…...

【Linux】C语言执行shell指令

在C语言中执行Shell指令 在C语言中&#xff0c;有几种方法可以执行Shell指令&#xff1a; 1. 使用system()函数 这是最简单的方法&#xff0c;包含在stdlib.h头文件中&#xff1a; #include <stdlib.h>int main() {system("ls -l"); // 执行ls -l命令retu…...

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;增长率&…...

【磁盘】每天掌握一个Linux命令 - iostat

目录 【磁盘】每天掌握一个Linux命令 - iostat工具概述安装方式核心功能基础用法进阶操作实战案例面试题场景生产场景 注意事项 【磁盘】每天掌握一个Linux命令 - iostat 工具概述 iostat&#xff08;I/O Statistics&#xff09;是Linux系统下用于监视系统输入输出设备和CPU使…...

[ICLR 2022]How Much Can CLIP Benefit Vision-and-Language Tasks?

论文网址&#xff1a;pdf 英文是纯手打的&#xff01;论文原文的summarizing and paraphrasing。可能会出现难以避免的拼写错误和语法错误&#xff0c;若有发现欢迎评论指正&#xff01;文章偏向于笔记&#xff0c;谨慎食用 目录 1. 心得 2. 论文逐段精读 2.1. Abstract 2…...

React19源码系列之 事件插件系统

事件类别 事件类型 定义 文档 Event Event 接口表示在 EventTarget 上出现的事件。 Event - Web API | MDN UIEvent UIEvent 接口表示简单的用户界面事件。 UIEvent - Web API | MDN KeyboardEvent KeyboardEvent 对象描述了用户与键盘的交互。 KeyboardEvent - Web…...

什么是Ansible Jinja2

理解 Ansible Jinja2 模板 Ansible 是一款功能强大的开源自动化工具&#xff0c;可让您无缝地管理和配置系统。Ansible 的一大亮点是它使用 Jinja2 模板&#xff0c;允许您根据变量数据动态生成文件、配置设置和脚本。本文将向您介绍 Ansible 中的 Jinja2 模板&#xff0c;并通…...