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

算法-图论(建图,拓扑排序)

文章目录

    • 建图的三种方式
      • 邻接矩阵
      • 邻接表
      • 链式前向星
    • 拓扑排序
      • 拓扑排序基础原理介绍
      • 拓扑排序步骤解析
      • 拓扑排序模板leetcode-课程表

建图的三种方式

我们建图的三种方式分别是邻接矩阵, 邻接矩阵, 链式前向星

邻接矩阵

假设我们的点的个数为N个, 我们就把他们的下标依次标为1, 2 ,…, 然后在一个矩阵表上进行边的添加, 比如我要在点2和点4之间添加一个权值为5的边, 那么我就在矩阵matrix[2][4] = 5即可, 唯一注意的就是如果是无向图, 就需要把matrix[4][2]位置也设置为5, 所以这个方法的弊端是十分明显的, 就是消耗的空间过大, 所以我们在大厂的笔试或者是比赛, 不会用这种方式进行建图, 下面是邻接矩阵法的代码实现

public class day23 {public static void main(String[] args) {int[][] edges = {{1,2,5},{5,3,1},{1,4,4},{2,5,2}};//测试一下使用邻接矩阵法建图GraphUseMatrix graphUseMatrix = new GraphUseMatrix();graphUseMatrix.build(5);graphUseMatrix.directGraph(edges);//graphUseMatrix.unDirectGraph(edges);graphUseMatrix.showGraph();}
}/*** 邻接矩阵建图的方法* 下面我们介绍的所用的图都是带权值的图, 不带权的更简单就不说了*/
class GraphUseMatrix{//设置一个最大的点数(根据题意)private static final int MAXN = 11;//设置一个最大的边数(根据题意, 无向图 * 2)private static final int MAXM = 21;//构建一个当前的点数curnprivate static int curN = 0;//设置一个邻接的矩阵(大小就是(点数 + 1) * (点数 + 1), 这里我们保证是够用的)private static final int[][] matrix = new int[MAXN][MAXN];//初始化矩阵的方法(传入的点的数量)public void build(int n){curN = n;//清空矩阵的脏数据for(int i = 1; i <= n; i++){for(int j = 1; j <= n; j++){//把邻接矩阵中的数据刷为最大值(因为权值可能为0)matrix[i][j] = Integer.MAX_VALUE;}}}//添加边的方法private void addEdge(int from, int to, int weight){matrix[from][to] = weight;}//在有向带权图中添加边public void directGraph(int[][] edges){for(int[] edge : edges){addEdge(edge[0], edge[1], edge[2]);}}//在无向带权图中添加边public void unDirectGraph(int[][] edges){for(int[] edge : edges){addEdge(edge[0], edge[1], edge[2]);addEdge(edge[1], edge[0], edge[2]);}}//展示图的方式public void showGraph(){System.out.println("邻接矩阵法建图展示");for(int i = 1; i <= curN; i++){for(int j = 1; j <= curN; j++){if(matrix[i][j] == Integer.MAX_VALUE){System.out.print("∞  ");}else{System.out.print(matrix[i][j] + "  ");}}System.out.println();}}
}

上述代码的测试结果见下
在这里插入图片描述
在这里插入图片描述

测试结果也是很明显的, 证明我们之前的代码是没有问题的, 无向图总体是按照正对角线呈对称分布

邻接表

邻接表是一种动态的建图的方式, 关于大厂的笔试面试题, 邻接表以及完全够用了, 如果涉及到比赛内容的话, 我们会使用链式前向星建图法, 等会我们会介绍到这种算法, 说回来邻接表, 其实就是一个
ArrayList<ArrayList<int(无权)/int>的结构, 也就是顺序表套顺序表的结构, 假如我们要建立一个从点2到点4的边,如果不带权值, 我们就让外层顺序表2下标对应的顺序表添加一个元素4, 如果同时带有一个权值的话, 我们就添加一个数组(假设权值是8)我们就让2下标对应的顺序表添加一个[4,8]数组, 下面是邻接表的代码实现

public class day23 {public static void main(String[] args) {int[][] edges = {{1, 2, 5}, {5, 3, 1}, {1, 4, 4}, {2, 5, 2}};
//        //测试一下使用邻接矩阵法建图
//        GraphUseMatrix graphUseMatrix = new GraphUseMatrix();
//        graphUseMatrix.build(5);
//        graphUseMatrix.unDirectGraph(edges);
//        graphUseMatrix.showGraph();//测试一下邻接表法建图GraphUseList graphUseList = new GraphUseList();graphUseList.build(5);graphUseList.directGraph(edges);//graphUseList.unDirectGraph(edges);graphUseList.showGraph();}
}/*** 邻接表建图的方法(是一种动态的结构)* 和邻接矩阵一样, 我们在这里介绍的都是带权的图*/
class GraphUseList {//构建一个当前的点数private static int curN = 0;//邻接表的主体private static ArrayList<ArrayList<int[]>> list = new ArrayList<>();//初始化邻接表(传入一个点的数量)public void build(int n) {//设置当前的点数curN = n;//上来直接清空邻接表list.clear();//开始构建顺序表(新添加n+1个列表)for (int i = 0; i <= n; i++) {list.add(new ArrayList<>());}}//添加边的方法private void addEdge(int from, int to, int weight) {list.get(from).add(new int[]{to, weight});}//构建一个有向的图public void directGraph(int[][] edges) {for (int[] edge : edges) {addEdge(edge[0], edge[1], edge[2]);}}//构建一个无向的图public void unDirectGraph(int[][] edges) {for (int[] edge : edges) {addEdge(edge[0], edge[1], edge[2]);addEdge(edge[1], edge[0], edge[2]);}}//展示邻接表图的方式public void showGraph() {System.out.println("邻接表法建图展示");for (int i = 1; i <= curN; i++) {System.out.print("点" + i + "(邻点/权值) : ");for (int[] elem : list.get(i)) {System.out.print("[" + elem[0] + "," + elem[1] + "]");}System.out.println();}}
}

执行结果如下图所示
在这里插入图片描述
在这里插入图片描述

链式前向星

前两种建图的方式都有着明显的缺点, 第一个虽然是静态空间但是空间的大小过大, 第二个虽然使用的空间不是很大但是是一种动态的结果, 就会在时间上大打折扣, 所以我们就想要一种既可以是静态空间又可以做到省空间省时间的结构, 我们就需要下面的链式前向星建图法, 这个方法有点类似与前缀树的静态空间建树法(之前有)和链表头插法的结合, 下面我们分析一下建图的过程

准备过程 :
我们准备三个数组, 把每一个加入的边都设置一个编号(从1开始逐渐增加)

数组数组解释
head数组下标表示点的编号, head[i]表示这个点的’头边’的编号
next数组下标表示边的编号, next[i]表示这个边的下一条边的编号
to数组下标表示边的编号, to[i]表示这条边到达的点的编号
weight数组下标表示边的编号, weight[i]表示这条边的权值

具体的例子
假设此时我们准备了五个点, 然后执行4次加边的操作
head数组长度准备为 6 (5 + 1) , next, to, weight 数组的长度都准备 5 (4 + 1)
下面执行加边的过程

[3,1,2], 这条边编号为1, 出发点是3, 终点是1, 权值是2, 在head中插入头边head[3] = 1(这里就是用的头插法, 这里是首条边), next[1] = 0 (头边所以是0) , to[1] = 1, weight[1] = 2

代码实现如下

public class day23 {public static void main(String[] args) {int[][] edges = {{1, 2, 5}, {5, 3, 1}, {1, 4, 4}, {2, 5, 2}};
//        //测试一下使用邻接矩阵法建图
//        GraphUseMatrix graphUseMatrix = new GraphUseMatrix();
//        graphUseMatrix.build(5);
//        graphUseMatrix.unDirectGraph(edges);
//        graphUseMatrix.showGraph();//        //测试一下邻接表法建图
//        GraphUseList graphUseList = new GraphUseList();
//        graphUseList.build(5);
//        graphUseList.unDirectGraph(edges);
//        graphUseList.showGraph();//测试一下链式前向星建图GraphUseLinkedStar graphUseLinkedStar = new GraphUseLinkedStar();graphUseLinkedStar.build(5);graphUseLinkedStar.unDirectGraph(edges);graphUseLinkedStar.showGraph();}
}/*** 链式前向星建图法(静态的建图法)*/
class GraphUseLinkedStar {//定义点最大值private static final int MAXN = 11;//定义边最大值private static final int MAXM = 22;//构建head数组(以点为准)private static final int[] head = new int[MAXN];//构建next数组(以边为准)private static final int[] next = new int[MAXM];//准备to数组(以边为主)private static final int[] to = new int[MAXM];//准备weight数组(以边为主)private static final int[] weights = new int[MAXM];//定义一下当前点的个数private static int curN = 0;//定义一个计数器用于给边编号private static int cnt = 0;//传入一个点数n用来初始化图结构public void build(int n){//更新计数器cnt = 1;//初始化当前节点个数curN = n;//清除head即可(这里不用重置to, weights, next)Arrays.fill(head, 1, n + 1, 0);}//添加边的方法(其实就是链表的头插法)private void addEdge(int from, int ton, int weight){next[cnt] = head[from];to[cnt] = ton;weights[cnt] = weight;head[from] = cnt++;}//构建一个有向带权图public void directGraph(int[][] edges){for(int[] edge : edges){addEdge(edge[0], edge[1], edge[2]);}}//构建一个无向带权图public void unDirectGraph(int[][] edges){for(int[] edge : edges){addEdge(edge[0],edge[1],edge[2]);addEdge(edge[1],edge[0],edge[2]);}}//展示图的方法(类似于链表的遍历)public void showGraph(){System.out.println("链式前向星建图展示");for(int i = 1; i <= curN; i++){System.out.print("点" + i + "(邻点/权值) : ");for(int ei = head[i]; ei != 0; ei = next[ei]){System.out.print("[" + to[ei] + "," + weights[ei] + "]");}System.out.println();}}
}

执行结果如下
在这里插入图片描述

在这里插入图片描述

拓扑排序

拓扑排序基础原理介绍

拓扑排序的存在条件是在一个有向且无环图中的排序, 拓扑排序在某种程度上反应的是一件事的执行的先后顺序, 请看下图

在这里插入图片描述
这张图中, 黑色的字符表示节点的名称, 蓝色的数字指的是该位置的入度是多少, 上面我们提到过, 拓扑排序的过程可以视为完成某一件事的先后顺序, 假设我们最终想要完成的任务是f, 那我们下面的字符的序列也就是完成最终事件的顺序
拓扑排序不是唯一的, 比如下面的图
在这里插入图片描述
在这张图中, 先完成a还是先完成b都是可以的, 所以产生的拓扑排序的情况就有两种, 这就说明拓扑排序的结果可能有多种, 只要满足每一个节点的前面所需要的节点都完成了就可以
拓扑排序的应用举例 :
比如在计算机编译程序的过程中, 编译一个程序需要另外的程序结果才能编译完成, 所以很自然的就会出现程序编译的先后顺序问题, 见下图, 左侧的表格是编译一个程序所需要的已经完成的编译结果, 右面是完成a的编译过程的图, 右下角的两串字符串都是完成的顺序, 这同样说明拓扑排序不是唯一的
在这里插入图片描述
拓扑排序要求一个图有向, 这个很好理解, 做事情的步骤肯定是有先后的顺序的, 而且要无环, 这个我们就拿上面的编译过程理解, 假如a的编译过程依赖b, b的编译过程依赖a, 那这不就是矛盾了吗, 两者互相依赖谁也完成不了

拓扑排序步骤解析

实现拓扑排序用的是零入度删除法, 需要用到队列(特殊状况下用小根堆), 核心就是删除0入度的节点和因为该节点所造成的入度影响
这就解释了上面的图为什么我们要进行入度的标记, 首先图解一下0入度删除法的步骤
在这里插入图片描述
最终组合出来的删除节点的步骤就是最终的拓扑排序的答案

拓扑排序模板leetcode-课程表

leetcode210-课程表题目链接
在这里插入图片描述

class Solution {//我们采用邻接表建图就已经够用了private static ArrayList<ArrayList<Integer>> list = new ArrayList<>();//课的最大数目private static final int MAXN = 2001;//同时定义一个入读表private static final int[] indegree = new int[MAXN];//当前的数据个数private static int curN = 0;public int[] findOrder(int numCourses, int[][] prerequisites) {build(numCourses);directGraph(prerequisites);//定义一个计数器看一看队列弹出了多少次(建议使用数组形式队列)int cntNum = 0;Queue<Integer> queue = new ArrayDeque<>();//首先遍历入度数组加入入度为0的节点for (int i = 0; i < numCourses; i++) {if (indegree[i] == 0) {queue.offer(i);}}//从队列中逐渐弹出元素进行判断int[] res = new int[numCourses];while (!queue.isEmpty()) {int index = queue.poll();//在返回数组中添加上该元素res[cntNum++] = index;//遍历其所属的列表删除这个元素造成的入度for(int elem : list.get(index)){if(--indegree[elem] == 0){queue.offer(elem);}}}return cntNum == res.length ? res : new int[0];}//初始化图结构private static void build(int n) {//更新当前的数据个数curN = n;//更新顺序表list.clear();for (int i = 0; i < n; i++) {list.add(new ArrayList<>());}//更新入度表Arrays.fill(indegree, 0, n, 0);}//建图的主函数(本质是有向无权图), 建图的过程中同时完成入度的统计private static void directGraph(int[][] edges) {for (int[] edge : edges) {addEdge(edge[1], edge[0]);indegree[edge[0]]++;}}//插入边的函数private static void addEdge(int from, int to) {list.get(from).add(to);}
}

相关文章:

算法-图论(建图,拓扑排序)

文章目录 建图的三种方式邻接矩阵邻接表链式前向星 拓扑排序拓扑排序基础原理介绍拓扑排序步骤解析拓扑排序模板leetcode-课程表 建图的三种方式 我们建图的三种方式分别是邻接矩阵, 邻接矩阵, 链式前向星 邻接矩阵 假设我们的点的个数为N个, 我们就把他们的下标依次标为1, …...

天童教育:课外阅读图书推荐

新学期开始了&#xff0c;现在正是孩子培养良好的阅读习惯的关键时期。让孩子感受阅读&#xff0c;爱上阅读&#xff0c;无疑会丰富孩子的日常生活&#xff0c;开阔孩子的视野&#xff0c;帮助孩子更好地生活。今天西安天童教育就和大家推荐几本适合孩子看的课外阅读书目&#…...

“汉语新解” Prompt新高度,火爆的李继刚

“汉语新解” prompt 是由李继刚设计的一个用于启发人工智能模型进行创意性文本生成的指令模板。这个 prompt 的设计初衷是为了让AI能够以一种独特的方式解析和重新诠释常见的中文词汇&#xff0c;从而产生出具有深刻洞察力和幽默感的文本内容&#xff0c;仿佛是由鲁迅或林语堂…...

论文:AOP框架安全框架-系统架构师(六十六)

1详细论述安全架构设计中鉴别框架和访问控制框架设计内容&#xff0c;并论述鉴别框架和访问控制所面临的主要威胁&#xff0c;说明其危害。 解析&#xff1a; 鉴别框架有用户密码鉴别、生物特征鉴别和多因素鉴别。 用户密码鉴别可以采用验证登入的用户账号是否正确。 生物特…...

用Unity2D制作一个人物,实现移动、跳起、人物静止和动起来时的动画:下(人物动画)

上个博客我们做出了人物的动画机和人物移动跳跃&#xff0c;接下来我们要做出人物展现出来的动画了 我们接下来就要用到动画机了&#xff0c;双击我们的动画机&#xff0c;进入到这样的页面&#xff0c;我这是已经做好的页面&#xff0c;你们是没有这些箭头的 依次像我一样连接…...

Android 优雅封装Glide

文章目录 Android 优雅封装Glide核心思想定义策略接口定义图片选项实现Glide策略图片管理类使用 Android 优雅封装Glide 核心思想 使用策略模式实现不同图片加载框架的切换&#xff0c;使用建造者设计模式处理不同参数&#xff0c;最后通过 ImageLoader 进行管理。 定义策略…...

智能优化算法-粒子群优化算法(PSO)(附源码)

目录 1.内容介绍 2.部分代码 3.实验结果 4.内容获取 1.内容介绍 粒子群优化算法 (Particle Swarm Optimization, PSO) 是一种基于群体智能的元启发式优化算法&#xff0c;由Kennedy和Eberhart于1995年提出。PSO模拟了鸟群或鱼群的觅食行为&#xff0c;通过粒子之间的相互作用…...

vue系统获取授权平台授权码实现单点登录、注销功能

公司平台需要对接别的平台 实现单点登录 注销。简而言之&#xff0c;不需要在自己公司系统登录 统一在别的平台登录后获取到登录凭证&#xff08;授权码&#xff09; 在本公司系统实现免密登录的功能。 流程&#xff1a; 跳转授权页面和保存授权码的代码&#xff1a; hrefLog…...

Java之枚举

目录 枚举 引入 定义 代码示例 常用方法 代码示例 枚举的优缺点 枚举和反射 面试题 枚举 引入 枚举是在JDK1.5以后引入的。主要用途是&#xff1a;将一组常量组织起来&#xff0c;在这之前表示一组常量通常使用定义常量的方式&#xff1a; publicstaticintfinalRED1;…...

八、适配器模式

适配器模式&#xff08;Adapter Pattern&#xff09;是一种结构型设计模式&#xff0c;它允许不兼容的接口之间进行合作。适配器模式通过创建一个适配器类来转换一个接口的接口&#xff0c;使得原本由于接口不兼容无法一起工作的类可以一起工作。 主要组成部分&#xff1a; 目标…...

关于E-R图

一 什么是E-R图 E-R图&#xff08;Entity-Relationship Diagram&#xff09;是一种数据建模工具&#xff0c;用于描述数据库中实体之间的关系。它使用实体&#xff08;Entity&#xff09;、属性&#xff08;Attribute&#xff09;和关系&#xff08;Relationship&#…...

DVWA通关教程

Brute Force Low 先进行一下代码审计 <?php // 检查是否通过GET请求传递了Login参数&#xff08;注意&#xff1a;这里应该是username或类似的&#xff0c;但代码逻辑有误&#xff09; if( isset( $_GET[ Login ] ) ) { // 从GET请求中获取用户名 $user $_GET[ us…...

网络学习-eNSP配置VRRP

虚拟路由冗余协议(Virtual Router Redundancy Protocol&#xff0c;简称VRRP) VRRP广泛应用在边缘网络中&#xff0c;是一种路由冗余协议&#xff0c;它的设计目标是支持特定情况下IP数据流量失败转移不会引起混乱&#xff0c;允许主机使用单路由器&#xff0c;以及即使在实际…...

Kafka【九】如何实现数据的幂等性操作

为了解决Kafka传输数据时&#xff0c;所产生的数据重复和乱序问题&#xff0c;Kafka引入了幂等性操作&#xff0c;所谓的幂等性&#xff0c;就是Producer同样的一条数据&#xff0c;无论向Kafka发送多少次&#xff0c;kafka都只会存储一条。注意&#xff0c;这里的同样的一条数…...

JavaScript知识点1

目录 1.JavaScript中常用的数组方法有哪些&#xff1f; 2.JavaScript的同源策略&#xff1f; 3.JavaScript中的 NaN 是什么&#xff1f; 4.JavaScript中的split、slice、splice函数区别&#xff1f; 1.JavaScript中常用的数组方法有哪些&#xff1f; 在 JavaScript 中&…...

51单片机个人学习笔记11(AT24C02-I2C总线)

前言 本篇文章属于STC89C52单片机&#xff08;以下简称单片机&#xff09;的学习笔记&#xff0c;来源于B站教学视频。下面是这位up主的视频链接。本文为个人学习笔记&#xff0c;只能做参考&#xff0c;细节方面建议观看视频&#xff0c;肯定受益匪浅。 [1-1] 课程简介_哔哩…...

创建Java项目,可实现main方法运行,实现对性能数据的处理

1、Android Studio无法执行Java类的main方法问题及解决方法 Android Studio无法执行Java类的main方法问题及解决方法_delegatedbuild-CSDN博客 D:\workspaces\performanceTools\.idea 文件夹下&#xff0c;gardle.xml ,添加依赖 <option name"delegatedBuild"…...

JavaWeb(后端)

MVC MVC 就是 Model View Controller 的缩写&#xff0c;属于一种软件架构设计模式一种思想&#xff0c;把我们的项目分为控制器&#xff08;Controller&#xff09;、模型&#xff08;Model&#xff09;、视图&#xff08;view&#xff09;三个部分&#xff0c;model就是处理…...

828华为云征文 | 华为云Flexusx实例,高效部署Servas书签管理工具的优选平台

前言 华为云Flexus X实例&#xff0c;Servas书签管理工具部署的优选平台&#xff01;828节日特惠&#xff0c;让高效管理您的知识宝藏触手可及。Flexus X实例以其卓越的算力、灵活的资源配置和智能调优技术&#xff0c;为Servas提供了稳定、高效的运行环境。无论是快速访问、安…...

分治法和动态规划法

一、分治法&#xff08;Divide and Conquer&#xff09; 定义 分治法是一种将大问题分解成若干个小问题&#xff0c;递归地解决这些小问题&#xff0c;然后将这些小问题的解合并起来得到原问题的解的算法策略。&#xff08;子问题之间相互独立&#xff09; 基本步骤 1.分解…...

基于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;积分&…...

Oracle查询表空间大小

1 查询数据库中所有的表空间以及表空间所占空间的大小 SELECTtablespace_name,sum( bytes ) / 1024 / 1024 FROMdba_data_files GROUP BYtablespace_name; 2 Oracle查询表空间大小及每个表所占空间的大小 SELECTtablespace_name,file_id,file_name,round( bytes / ( 1024 …...

(二)TensorRT-LLM | 模型导出(v0.20.0rc3)

0. 概述 上一节 对安装和使用有个基本介绍。根据这个 issue 的描述&#xff0c;后续 TensorRT-LLM 团队可能更专注于更新和维护 pytorch backend。但 tensorrt backend 作为先前一直开发的工作&#xff0c;其中包含了大量可以学习的地方。本文主要看看它导出模型的部分&#x…...

Go 语言接口详解

Go 语言接口详解 核心概念 接口定义 在 Go 语言中&#xff0c;接口是一种抽象类型&#xff0c;它定义了一组方法的集合&#xff1a; // 定义接口 type Shape interface {Area() float64Perimeter() float64 } 接口实现 Go 接口的实现是隐式的&#xff1a; // 矩形结构体…...

1688商品列表API与其他数据源的对接思路

将1688商品列表API与其他数据源对接时&#xff0c;需结合业务场景设计数据流转链路&#xff0c;重点关注数据格式兼容性、接口调用频率控制及数据一致性维护。以下是具体对接思路及关键技术点&#xff1a; 一、核心对接场景与目标 商品数据同步 场景&#xff1a;将1688商品信息…...

【HTML-16】深入理解HTML中的块元素与行内元素

HTML元素根据其显示特性可以分为两大类&#xff1a;块元素(Block-level Elements)和行内元素(Inline Elements)。理解这两者的区别对于构建良好的网页布局至关重要。本文将全面解析这两种元素的特性、区别以及实际应用场景。 1. 块元素(Block-level Elements) 1.1 基本特性 …...

多模态大语言模型arxiv论文略读(108)

CROME: Cross-Modal Adapters for Efficient Multimodal LLM ➡️ 论文标题&#xff1a;CROME: Cross-Modal Adapters for Efficient Multimodal LLM ➡️ 论文作者&#xff1a;Sayna Ebrahimi, Sercan O. Arik, Tejas Nama, Tomas Pfister ➡️ 研究机构: Google Cloud AI Re…...

重启Eureka集群中的节点,对已经注册的服务有什么影响

先看答案&#xff0c;如果正确地操作&#xff0c;重启Eureka集群中的节点&#xff0c;对已经注册的服务影响非常小&#xff0c;甚至可以做到无感知。 但如果操作不当&#xff0c;可能会引发短暂的服务发现问题。 下面我们从Eureka的核心工作原理来详细分析这个问题。 Eureka的…...

LeetCode - 199. 二叉树的右视图

题目 199. 二叉树的右视图 - 力扣&#xff08;LeetCode&#xff09; 思路 右视图是指从树的右侧看&#xff0c;对于每一层&#xff0c;只能看到该层最右边的节点。实现思路是&#xff1a; 使用深度优先搜索(DFS)按照"根-右-左"的顺序遍历树记录每个节点的深度对于…...

云原生安全实战:API网关Kong的鉴权与限流详解

&#x1f525;「炎码工坊」技术弹药已装填&#xff01; 点击关注 → 解锁工业级干货【工具实测|项目避坑|源码燃烧指南】 一、基础概念 1. API网关&#xff08;API Gateway&#xff09; API网关是微服务架构中的核心组件&#xff0c;负责统一管理所有API的流量入口。它像一座…...