图论2 图的数据结构表示

目录

一 图的数据结构表示

1 邻接矩阵(Adjacency Matrix)

2 邻接表(Adjacency List)

3 边列表(Edge List)

4 十字链表(Orthogonal List / Cross-linked List, 十字链表)

5 邻接多重表(Adjacency Multilist / Incidence List for Undirected Graphs)

6 关联矩阵(Incidence Matrix / 关联矩阵)

二 图的 RDBMS 建模

1 建模基本思路

2 表结构设计

(1)顶点表设计

(2)边表设计(适用于有向图)

(3)标签元数据表设计

(4)无向图处理方法

三 图算法基础数据结构-邻接表

1 邻接表建模思路

2 代码实现

(1) 标签类 Label

(2) 顶点类 Vertex

(3) 边类 Edge

(4) 图类 AdjacencyGraph

3 说明


在上文已经介绍图的基本概念之后,本节将围绕图的数据结构表示展开,系统介绍常见的在内存中表示图的几种经典数据结构:邻接矩阵、邻接表、边列表、十字链表、邻接多重表、关联矩阵,并给出每种表示的定义、存储结构、优缺点、适用场景、复杂度分析与Java朴素实现。最后讨论如何在关系型数据库(RDBMS)中建模图结构。

一 图的数据结构表示

1 邻接矩阵(Adjacency Matrix)

定义与结构 邻接矩阵用于表示顶点集合为 V=\{v_0,\dots,v_{n-1}\} 的图。构造一个 n\times n 的二维矩阵 A,对于无向图,A[i][j]=1 表示顶点 v_i 与 v_j 之间存在边;若有权图则放权值 A[i][j]=w;无边时可用 0null 表示,取决于实现。

举例(无向无权) 顶点 0 与 2 有边,则 A[0][2] = A[2][0] = 1

优点

  • 随机访问边存在性:判断两顶点是否相邻为 O(1)。

  • 矩阵代数便于做图论中的一些理论运算。

  • 实现简单,适合顶点数 n 较小或图密集(边数接近 n^2)时使用。

缺点

  • 空间复杂度为 O(n^2),对稀疏图非常浪费。

  • 枚举某一顶点的邻居需要 O(n) 扫描整行(即使度很小也要扫描)。

  • 动态插入大量顶点成本高(需要扩展矩阵)。

复杂度

  • 空间:O(n^2)

  • 判断边存在:O(1)

  • 枚举邻居:O(n)

  • 插入/删除边:O(1)

适用场景

  • n 小或图密集(dense graph)。

  • 需要频繁 O(1) 边查找或矩阵运算(例如某些线性代数方法)。

Java朴素实现

/*** 图的邻接矩阵表示*/
public class MatrixGraph<V,E,ED> {
​// 最大顶点个数public static final int MAX_VERTEX_NUM = 20;// 顶点向量集合,用来存储顶点信息,数组索引作为数据索引,用来构建邻接矩阵private Vertex<V>[] vexs;// 邻接矩阵private AdjMatrix<E,ED> arcs = new AdjMatrix<>();// 图的当前顶点数和弧数public int vexnum;public int arcnum;// 图的种类标志public GraphKind kind;
​@SuppressWarnings("unchecked")public MatrixGraph() {vexs = (Vertex<V>[])new Vertex<?>[MAX_VERTEX_NUM];// 初始化邻接矩阵的每个单元格for (int i = 0; i < MAX_VERTEX_NUM; i++) {for (int j = 0; j < MAX_VERTEX_NUM; j++) {arcs.cells[i][j] = new ArcCell<>();}}}
​// 图的种类 {有向图,有向网,无向图,无向网}public enum GraphKind { DG, DN, UDG, UDN }
​public static class Vertex<V>{public V data;}
​// 弧单元定义public static class ArcCell<E,ED> {// 顶点关系类型。对无权图,用 1 或 0 表示相邻否;对带权图,则为权值类型public E adj;
​// 该弧相关信息public ED info;}
​// 邻接矩阵类型public static class AdjMatrix<E,ED> {public ArcCell<E,ED>[][] cells = new ArcCell[MAX_VERTEX_NUM][MAX_VERTEX_NUM];}
​// 提供访问vexs和arcs的公共方法public Vertex<V>[] getVexs() {return vexs;}
​public AdjMatrix<E,ED> getArcs() {return arcs;}
​
}

2 邻接表(Adjacency List)

定义与结构 邻接表为每个顶点维护一个邻居列表(通常链表、动态数组或向量),每个列表包含该顶点的所有出/入(或无向)邻接顶点及可选的边权和边属性。

举例(有向有权) adj[u] 列表中存储 (v, weight, metadata) 表示从 uv 的边。

优点

  • 空间友好:空间复杂度为 O(n + m),其中 m 是边数,适用于稀疏图。

  • 枚举某一顶点的所有出边非常高效,时间与该顶点度数成正比。

  • 插入边易,删除边在双向链表或带索引结构中也较为方便。

缺点

  • 判断任意两顶点是否有边不是 O(1)(需要扫描较短列表或使用辅助哈希)。

  • 若需要高并发、并行访问单个顶点的邻居,需考虑同步和锁策略。

复杂度

  • 空间:O(n + m)

  • 枚举某一顶点邻居:O(\deg(v))

  • 判断边存在(线性扫描):O(\deg(u))

  • 插入边:均摊 O(1)

  • 删除边:O(\deg(u))(可借辅助索引优化)

适用场景

  • 大多数实际稀疏图(社交网络、道路网络、依赖图等)。

  • 常配合图遍历(BFS、DFS)、最短路径算法(Dijkstra、Bellman-Ford)使用。

Java朴素实现

/*** 图的邻接表数据结构表示*/
public class AdjacencyListGraph<V, E> {public static final int MAX_VERTEX_NUM = 20;public VNode<V, E>[] vertices;         // 邻接表public int vexnum;                     // 图的当前顶点数public int arcnum;                     // 图的当前弧数public GraphKind kind = GraphKind.UDG; // 图的种类标志
​@SuppressWarnings("unchecked")public AdjacencyListGraph() {vertices = (VNode<V, E>[]) new VNode<?,?>[MAX_VERTEX_NUM];vexnum = 0;arcnum = 0;}
​// 图的种类 {有向图,有向网,无向图,无向网}public enum GraphKind { DG, DN, UDG, UDN }
​// 弧节点类public static class ArcNode<E> {public int adjvex;            // 该弧所指向的顶点的位置public ArcNode<E> nextarc;    // 指向下一条弧的指针public E info;                // 该弧相关信息的指针(泛型类型)
​public ArcNode(int adjvex, E info) {this.adjvex = adjvex;this.info = info;this.nextarc = null;}}
​// 顶点节点类public static class VNode<V, E> {public V data;                // 顶点信息(泛型类型)public ArcNode<E> firstarc;   // 指向第一条依附该顶点的弧的指针
​public VNode(V data) {this.data = data;this.firstarc = null;}}
​// 示例使用方法public void addVertex(int index, V data) {if (index >= 0 && index < MAX_VERTEX_NUM) {vertices[index] = new VNode<>(data);vexnum++;}}
​public void addArc(int fromIndex, int toIndex, E info) {if (fromIndex >= 0 && fromIndex < MAX_VERTEX_NUM && toIndex >= 0 && toIndex < MAX_VERTEX_NUM) {ArcNode<E> newArc = new ArcNode<>(toIndex, info);newArc.nextarc = vertices[fromIndex].firstarc;vertices[fromIndex].firstarc = newArc;arcnum++;}}
}

3 边列表(Edge List)

定义与结构 边列表把图表示为一组边的集合,每条边表示为二元组(或三元组带权):(u, v)(u, v, w)。通常用数组 edges[] 存储。

优点

  • 表示简单、紧凑,易于序列化与外部存储。

  • 适合做基于边的批处理算法(如 Kruskal 最小生成树需要排序边)。

  • 插入边非常简单(append)。

缺点

  • 判断边是否存在需要 O(m)(除非配合索引或哈希)。

  • 枚举某一顶点的邻居低效(需扫描全部边或建立额外索引)。

复杂度

  • 空间:O(m)

  • 遍历所有边:O(m)

  • 判断边存在:O(m)(可建哈希加速)

  • 插入边:O(1)(append)

适用场景

  • 批量边处理(排序、过滤、图转化)。

  • 构建初始图数据后再转换为邻接表进行算法处理。

  • 文件格式与数据交换(如 CSV、边列表文件)。

Java朴素实现

/*** 图的边列表表示*/
public class EdgeListGraph<V,E> {public static final int MAX_EDGE_NUM = 20;public Edge<V,E>[] edges;public int edgenum;
​public EdgeListGraph(){this.edges = (Edge<V,E>[])new Edge<?,?>[MAX_EDGE_NUM];this.edgenum = 0;}
​// 边类包含顶点数据,不包含顶点对象引用public static class Edge<V,E>{V fromData;  // 直接存储顶点数据V toData;E data;public Edge(V fromData, V toData, E data){this.fromData = fromData;this.toData = toData;this.data = data;}}
}

4 十字链表(Orthogonal List / Cross-linked List, 十字链表)

定义与结构 十字链表是面向有向图的一种链式表示,期望同时高效访问每个顶点的入边和出边。结构通常包含顶点节点数组,每个顶点维护两个链首:出边链表和入边链表;每条边节点包含 hlink 指向相同弧在出链中的下一个弧,tlink 指向相同弧在入链中的下一个弧,以及 tailvex(弧尾顶点)、headvex(弧头顶点)和边权等信息。

示意结构

Vertex {firstout; // 指向以该顶点为尾的第一条弧firstin;  // 指向以该顶点为头的第一条弧
}
Edge {tailvex, headvex;tlink; // 在尾链(出链)上hlink; // 在头链(入链)上weight, info;
}

优点

  • 同时支持对入边和出边的高效遍历:枚举出边或入边都只需沿对应链表遍历。

  • 适合需要频繁双方访问(入边和出边)的有向图算法(如强连通分量、反向遍历等)。

缺点

  • 较邻接表实现更复杂(边维护两个链指针)。

  • 空间开销较邻接表稍大(每条边额外的指针字段)。

  • 在无向图上不适用(无向图可用邻接多重表替代)。

复杂度

  • 空间:O(n + m)

  • 枚举出边/入边:O(\deg_{out}(v)) 或 O(\deg_{in}(v))

  • 插入边:O(1)

  • 删除边:需要维护两条链,复杂度 O(1) 在已知前驱时,否则需要搜索。

适用场景

  • 有向图且经常需要访问入边与出边。

  • 图分析。

Java朴素实现

/*** 有向图的十字链表存储表示*/
public class OrthogonalListGraph<V, E> {public static final int MAX_VERTEX_NUM = 20;public VexNode<V,E>[] xlist;        // 表头向量(顶点数组)public int vexnum;             // 有向图的当前顶点数public int arcnum;             // 有向图的当前弧数
​@SuppressWarnings("unchecked")public OrthogonalListGraph() {xlist = (VexNode<V,E>[]) new VexNode<?,?>[MAX_VERTEX_NUM];vexnum = 0;arcnum = 0;}
​public static class ArcBox<E> {public int tailvex;        // 该弧的尾顶点的位置public int headvex;        // 该弧的头顶点的位置public ArcBox<E> hlink;    // 弧头相同的弧的链域public ArcBox<E> tlink;    // 弧尾相同的弧的链域public E info;             // 该弧相关信息的指针}
​public static class VexNode<V,E> {public V data;             // 顶点数据public ArcBox<E> firstin;  // 指向该顶点第一条入弧public ArcBox<E> firstout; // 指向该顶点第一条出弧}
}

5 邻接多重表(Adjacency Multilist / Incidence List for Undirected Graphs)

定义与结构 邻接多重表主要为无向图服务,目的是避免在无向图中对同一条边做两次独立记录(在普通邻接表中无向边常被记录两次:u->v 和 v->u)。邻接多重表为每条无向边只创建一个边结点,边结点有两个指针分别连接到两个端点的邻接链表中。

示意结构

Edge {iVex, jVex;       // 两端点iLink, jLink; // 分别连接到 v1 的邻接链及 v2 的邻接链weight, info;
}
Vertex {firstedge; // 指向该顶点的第一条边(EdgeNode)
}

优点

  • 每条无向边仅存储一次,节省空间(对某些实现与场景)。

  • 删除边时只需操作一个边节点,便于维护一致性。

  • 遍历顶点邻居仍然高效,时间随度增长。

缺点

  • 实现稍复杂(边节点需要两个邻接指针)。

  • 在需要为边赋予方向属性或在有向图上使用时不适用。

复杂度

  • 空间:O(n + m)

  • 枚举邻居:O(\deg(v))

  • 插入边:O(1)

  • 删除边:在已知位置可为 O(1),否则需找到前驱。

适用场景

  • 无向图中希望使每条边只存一次的场景。

  • 图操作(删除、修改边)要求单点一致性的场景。

Java朴素实现

/*** 无向图的邻接多重表存储表示*/
public class AdjacencyMultilistGraph<V,E> {public static final int MAX_VERTEX_NUM = 20;
​public VexBox<V,E>[] adjmulist; // 邻接多重表public int vexnum;          // 当前顶点数public int edgenum;         // 当前边数
​@SuppressWarnings("unchecked")public AdjacencyMultilistGraph() {this.adjmulist = (VexBox<V, E>[]) new VexBox<?,?>[MAX_VERTEX_NUM];this.vexnum = 0;this.edgenum = 0;}
​public static class EBox<E> {public int iVex;        // 该边依附的两个顶点的位置public int jVex;        // 该边依附的两个顶点的位置public EBox<E> iLink;   // 指向依附顶点iVex的下一条边public EBox<E> jLink;   // 指向依附顶点jVex的下一条边public E info;          // 该边信息指针}
​public static class VexBox<V,E> {public V data;              // 顶点数据public EBox<E> firstedge;   // 指向第一条依附该顶点的边}
​
}

6 关联矩阵(Incidence Matrix / 关联矩阵)

定义与结构 关联矩阵是 n \times m 的矩阵,行表示顶点,列表示边。对于无向图,如果边 e_j 连接顶点 v_i,则 B[i][j] = 1(或其他标记,如端点编号);对于有向图可以用 1 表示出端点,-1 表示入端点(或用 1/0 和方向表述)。

举例(有向图) 若第 j 条边从 v_p 指向 v_q,则 B[p][j] = 1B[q][j] = -1,其他行为 0。

优点

  • 适合处理边与顶点之间的“关系”分析(如网络流基础理论、线性代数方法)。

  • 在某些数学分析(如图的循环空间、切空间)中方便用线性代数处理。

缺点

  • 空间复杂度 O(nm),对大型图不友好(尤其当边数 m 很大时)。

  • 枚举邻接关系较为低效(需要扫描对应列或行)。

  • 一般用于理论分析或非常特殊的算法场景,在工程实现中较少单独使用。

复杂度

  • 空间:O(nm)

  • 通过矩阵计算可得到路径关系等,但代价昂贵。

适用场景

  • 图的代数性质分析(如环空间、基循环、切空间)。

  • 网络流中部分数学建模。

Java朴素实现

/*** 图的关联矩阵表示*/
public class IncidenceMatrixGraph<V,E> {public static final int MAX_VERTEX_NUM = 20;public static final int MAX_EDGE_NUM = 100;
​// 顶点数组public Vertex<V>[] vertices;
​// 边数组(只存储边数据,不存储端点信息)public Edge<E>[] edges;
​// 关联矩阵:表达顶点与边的关联关系public int[][] matrix;
​// 当前顶点数和边数public int vernum;public int edgenum;
​// 图类型:0-无向图,1-有向图public int graphType;
​public IncidenceMatrixGraph(int graphType) {this.vertices = (Vertex<V>[])new Vertex<?>[MAX_VERTEX_NUM];this.edges = (Edge<E>[])new Edge<?>[MAX_EDGE_NUM];this.matrix = new int[MAX_VERTEX_NUM][MAX_EDGE_NUM];this.vernum = 0;this.edgenum = 0;this.graphType = graphType;}
​public static class Vertex<V> {V data;public Vertex(V data) {this.data = data;}}
​// 边只存储自身数据,端点信息由矩阵表达public static class Edge<E> {E data;public Edge(E data) {this.data = data;}}
}

二 图的 RDBMS 建模

虽然图结构在本质上是非关系型的,但在没有图数据库(如 Neo4j、JanusGraph)可用的场景下,我们仍可以通过关系型数据库(RDBMS)来表达图的数据结构与连接关系。

1 建模基本思路

图在 RDBMS 中建模的核心思想是将顶点和边分别表示为关系表(Relation)

  • 顶点表(Vertex Table):存储图中的所有节点;

  • 边表(Edge Table):存储图中所有的边(连接关系);

  • 标签表(Label Table): 存储顶点和边的标签信息;

2 表结构设计

(1)顶点表设计
CREATE TABLE vertex (id INT PRIMARY KEY,         -- 顶点唯一标识label_id INT NOT NULL,      -- 顶点类型properties JSON,            -- 顶点属性FOREIGN KEY (label_id) REFERENCES label(id)
);

properties 字段可以灵活地以 JSON 形式存储各类属性,适合属性异构的图场景。如果属性固定,也可将其展开为单独的列。

(2)边表设计(适用于有向图)
CREATE TABLE edge (id INT PRIMARY KEY,              -- 边的唯一标识from_vertex INT NOT NULL,        -- 起点to_vertex INT NOT NULL,          -- 终点label_id INT NOT NULL,           -- 边的类型weight DECIMAL(10,2),            -- 权重properties JSON,                 -- 边的属性FOREIGN KEY (from_vertex) REFERENCES vertex(id),FOREIGN KEY (to_vertex) REFERENCES vertex(id),FOREIGN KEY (label_id) REFERENCES label(id)
);
  • 该结构适用于有向图(Directed Graph)

  • 支持为每条边添加类型、权重或其他灵活的属性;

  • 使用外键约束维护边和顶点之间的完整性。

(3)标签元数据表设计
CREATE TABLE label (id INT PRIMARY KEY,            -- 标签唯一标识label VARCHAR(100),            -- 标签名称category INT NOT NULL          -- 标签分类:标识顶点标签还是边标签(例如:1=顶点,2=边)
);
(4)无向图处理方法

对于无向图(Undirected Graph),可使用以下两种策略之一:

  1. 对称存储:每条边存储两次,分别是 (u → v)(v → u)

  2. 约束存储顺序:强制存储一次,并约定 from_vertex < to_vertex,查询时统一处理对称性。

三 图算法基础数据结构-邻接表

在前文我们已经介绍了图的多种数据结构表示方式(邻接矩阵、邻接表、边列表、十字链表、邻接多重表、关联矩阵),并且给出了其Java的朴素实现。在进入后续的图算法部分之前,有必要确定一种在算法实现中最常用的数据结构作为统一输入。实践中,邻接表(Adjacency List) 因其存储效率高、空间利用率好、便于图遍历与路径搜索,被广泛用于图算法的实现。因此,本节我们将详细介绍一个面向后续算法实现的邻接表对象建模与代码示例。

1 邻接表建模思路

在图的抽象建模中,我们至少需要三个核心要素:

  1. 顶点(Vertex):表示对象实体,可以附带标签(如类型)和属性信息。

  2. 边(Edge):表示对象之间的关系,通常包含权重、方向、标签和属性。

  3. 图(Graph):由一组顶点和边构成,提供统一的访问与管理接口。

此外,还需要一个标签类(Label),用来区分不同类型的顶点和边。这种抽象设计不仅符合图论的基本定义,同时为后续复杂算法(如最短路径、拓扑排序、强连通分量分解等)的实现提供了良好的扩展性。

2 代码实现

下面的 Java 代码示例展示了如何用面向对象方式构建邻接表:

(1) 标签类 Label
import java.util.concurrent.atomic.AtomicInteger;
​
public class Label {private static final AtomicInteger labelIdCounter = new AtomicInteger(0);
​private Integer id;        // 隐式ID,自增private String label;      // 标签名称private Integer category;  // 1-顶点  2-边
​public Label(String label, Integer category) {this.id = genId();this.label = label;this.category = category;}
​public int getId() {return id;}
​public String getLabel() {return label;}
​public void setLabel(String label) {this.label = label;}
​public Integer getCategory() {return category;}
​public void setCategory(Integer category) {this.category = category;}
​private int genId() {return labelIdCounter.getAndIncrement();}
​// 分类枚举enum Category {VERTEX(1), EDGE(2);Integer id;Category(int id) {this.id = id;}}
}

该类为顶点和边赋予标签及唯一 ID,方便后续分类和检索。

(2) 顶点类 Vertex
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;
​
public class Vertex {private static final AtomicInteger nodeIdCounter = new AtomicInteger(0);
​private Integer id;               // 顶点IDprivate String name;              // 顶点显示名称private Label label;              // 顶点标签private Map<String, Object> properties; // 顶点属性private Map<Integer, Edge> edgeList;    // 邻接边列表
​public Vertex(String name, Label label) {this.id = genId();this.name = name;this.label = label;this.properties = new HashMap<>();this.edgeList = new HashMap<>();}
​public Integer getId() {return id;}
​public String getName() {return name;}
​public Label getLabel() {return label;}
​public Map<String, Object> getProperties() {return properties;}
​public List<Edge> getEdgeList() {return new ArrayList<>(this.edgeList.values());}
​public Object getProperty(String key) {return this.properties.get(key);}public void setProperty(String key, Object value) {this.properties.put(key, value);}
​private int genId() {return nodeIdCounter.getAndIncrement();}
​// 添加邻接边public void addEdge(Edge edge) {this.edgeList.put(edge.getId(), edge);}
​public void addEdge(Vertex to, int weight, Label label) {Edge edge = new Edge(this, to, weight, label);this.edgeList.put(edge.getId(), edge);}
}

顶点类不仅保存了名称与标签,还维护了与其相连的边集合(邻接表的核心结构)。

(3) 边类 Edge
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;
​
public class Edge {private static final AtomicInteger edgeIdCounter = new AtomicInteger(0);
​private Integer id;             // 边IDprivate Vertex from;            // 起始顶点private Vertex to;              // 目标顶点private Label label;            // 边标签private Integer weight;         // 边权重private Map<String, Object> properties; // 边属性
​public Edge(Vertex from, Vertex to, int weight, Label label) {this.id = genId();this.from = from;this.to = to;this.label = label;this.weight = weight;this.properties = new HashMap<>();}
​public Integer getId() {return id;}
​public Vertex getFrom() {return from;}
​public Vertex getTo() {return to;}
​public Label getLabel() {return label;}
​public Integer getWeight() {return weight;}
​public Map<String, Object> getProperties() {return properties;}
​public Object getProperty(String key) {return this.properties.get(key);}
​public void setProperty(String key, Object value) {this.properties.put(key, value);}
​private int genId() {return edgeIdCounter.getAndIncrement();}
}

该类定义了边的基本信息,包括权重与属性信息,支持灵活扩展。

(4) 图类 AdjacencyGraph
import java.util.HashMap;
import java.util.Map;
​
public class AdjacencyGraph {private Map<Integer, Vertex> vertices;private Integer vertexNum;private Integer edgeNum;
​public AdjacencyGraph() {vertices = new HashMap<>();vertexNum = 0;edgeNum = 0;}
​public Map<Integer, Vertex> getVertices() {return vertices;}
​public Integer getVertexNum() {return vertexNum;}
​public Integer getEdgeNum() {return edgeNum;}
​// 添加顶点public void addVertex(Vertex v) {vertices.put(v.getId(), v);vertexNum++;}
​// 添加边public void addEdge(Edge edge) {edge.getFrom().addEdge(edge);edgeNum++;}
}

图类 AdjacencyGraph 用来维护全局的顶点与边集合,并且通过邻接表结构保证每个顶点能快速访问其邻接点。

3 说明

邻接表不仅是算法输入的常用数据结构,同时也非常贴合现实世界的图数据存储需求。通过 LabelVertexEdgeAdjacencyGraph 的建模,我们能够清晰地表达图的各个组成部分,并为后续的图算法实现(如深度优先搜索、广度优先搜索、Dijkstra 最短路径、Prim/Kruskal 最小生成树等)提供了统一的数据接口。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/pingmian/96524.shtml
繁体地址,请注明出处:http://hk.pswp.cn/pingmian/96524.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

在Excel中删除大量间隔空白行

在 Excel 中删除大量间隔空白行&#xff0c;可使用定位空值功能来快速实现。以下是具体方法&#xff1a;首先&#xff0c;选中包含空白行的数据区域。可以通过点击数据区域的左上角单元格&#xff0c;然后按住鼠标左键拖动到右下角最后一个单元格来实现。接着&#xff0c;按下快…

【C 学习】10-循环结构

“知道做不到就是不知道”一、条件循环1. while只要条件为真&#xff08;true&#xff09;&#xff0c;就会重复执行循环体内的代码。while (条件) {// 循环体&#xff08;要重复执行的代码&#xff09; }//示例 int i 1; while (i < 5) {printf("%d\n", i);i; …

音视频的下一站:协议编排、低时延工程与国标移动化接入的系统实践

一、引言&#xff1a;音视频的基础设施化 过去十年&#xff0c;音视频的两条主线清晰可辨&#xff1a; 娱乐驱动&#xff1a;直播、电商、短视频把“实时观看与互动”变成高频日常。 行业扩展&#xff1a;教育、会议、安防、政务逐步把“可用、可管、可控”引入产业系统。 …

SAM-Med3D:面向三维医疗体数据的通用分割模型(文献精读)

1) 深入剖析:核心方法与图示(Figure)逐一对应 1.1 单点三维提示的任务设定(Figure 1) 论文首先将3D交互式分割的提示形式从“2D逐片(每片1点,共N点)”切换为“体素级单点(1个3D点)”。Figure 1直观对比了 SAM(2D)/SAM-Med2D 与 SAM-Med3D(1点/体) 的差异:前两者…

【Spring】原理解析:Spring Boot 自动配置进阶探索与优化策略

一、引言在上一篇文章中&#xff0c;我们对 Spring Boot 自动配置的基本原理和核心机制进行了详细的分析。本文将进一步深入探索 Spring Boot 自动配置的高级特性&#xff0c;包括如何进行自定义扩展、优化自动配置的性能&#xff0c;以及在实际项目中的应用优化策略。同时&…

OpenCV:图像直方图

目录 一、什么是图像直方图&#xff1f; 关键概念&#xff1a;BINS&#xff08;区间&#xff09; 二、直方图的核心作用 三、OpenCV 计算直方图&#xff1a;calcHist 函数详解 1. 函数语法与参数解析 2. 基础实战&#xff1a;计算灰度图直方图 代码实现 结果分析 3. 进…

docke笔记下篇

本地镜像发布到阿里云 本地镜像发布到阿里云流程 镜像的生成方法 基于当前容器创建一个新的镜像&#xff0c;新功能增强 docker commit [OPTIONS] 容器ID [REPOSITORY[:TAG]] OPTIONS说明&#xff1a; OPTIONS说明&#xff1a; -a :提交的镜像作者&#xff1b; -m :提交时的说…

《大数据之路1》笔记2:数据模型

一 数据建模综述 1.1 为什么要数据建模背景&#xff1a; 随着DT时代的来临&#xff0c;数据爆发式增长&#xff0c;如何对数据有序&#xff0c;有结构地分类组织额存储是关键定义&#xff1a; 数据模型时数据组织和存储的方法&#xff0c;强调从业务、数据存取、使用角度 合理存…

“量子能量泵”:一种基于并联电池与电容阵的动态直接升压架构

“量子能量泵”&#xff1a;一种基于并联电池与电容阵的动态直接升压架构摘要&#xff1a;本文揭示了一种革命性的高效电源解决方案&#xff0c;旨在彻底解决低电压、大功率应用中的升压效率瓶颈与电池一致性难题。该方案摒弃传统磁性升压拓扑&#xff0c;创新性地采用并联电池…

DeepSeek实战--自定义工具

1. 背景 当前已经有很多AI基础平台&#xff08;比如&#xff1a;扣子、Dify&#xff09;&#xff0c;用户可以快速搭建Agent&#xff0c;那怎样将已有的接口能力给大模型调用呢 &#xff1f; 今天我们来探索一个&#xff0c;非常高效、快捷的方案&#xff1a;将http接口做成Dif…

“移动零”思路与题解

给定一个数组 nums&#xff0c;编写一个函数将所有 0 移动到数组的末尾&#xff0c;同时保持非零元素的相对顺序。请注意 &#xff0c;必须在不复制数组的情况下原地对数组进行操作。思路讲解&#xff1a;举例如下&#xff1a;实现代码是&#xff1a;class Solution { public:v…

关于行内元素,行内块元素和块级元素

1、什么是行内元素&#xff0c;什么是行内块元素&#xff0c;什么是块级元素行内元素的特点&#xff1a;不独占一行&#xff0c;相邻元素会在同一行显示&#xff0c;直到一行排不下才换行。宽度和高度由内容本身决定&#xff0c;无法通过width&#xff0c;height手动设置&#…

⽹络请求Axios的概念和作用

Axios 是一个基于 ​​Promise​​ 的轻量级、高性能 ​​HTTP 客户端库​​&#xff0c;主要用于在浏览器和 Node.js 环境中发起 HTTP 请求&#xff08;如 GET、POST、PUT、DELETE 等&#xff09;。它通过简洁的 API 和强大的功能&#xff0c;简化了前端与后端之间的数据交互过…

在AgentScope中实现结构化输出

在AgentScope中实现结构化输出 概述 在AgentScope框架中&#xff0c;结构化输出功能允许开发者定义明确的输出模式&#xff0c;确保AI模型的响应符合预期的格式和约束。本教程将介绍如何使用AgentScope的structured_model参数来实现结构化输出。 结构化输出的优势 数据一致性&a…

Linux 磁盘I/O高占用进程排查指南:从定位到分析的完整流程

在Linux服务器运维工作中&#xff0c;磁盘I/O瓶颈是导致系统性能下降的常见原因之一。当服务器出现响应缓慢、应用卡顿等问题时&#xff0c;及时定位并解决高I/O占用进程就显得尤为重要。本文将从核心思路出发&#xff0c;通过“确认问题-定位磁盘-锁定进程-深入分析”四个步骤…

解决React中通过外部引入的css/scss/less文件更改antDesign中Modal组件内部的样式不生效问题

不生效原因Ant Design 的 Modal 默认通过 ReactDOM.createPortal 挂在 <body> 下&#xff0c;与你的组件树平级&#xff0c;所以写在 .module.css / scoped less 里的选择器根本匹配不到它&#xff0c;就算写全局样式&#xff0c;也可能因为权重不足或异步挂载时机而“看…

day41 51单片机最小系统、GPIO控制、时序逻辑器件(74HC138/595)与LED点阵驱动原理

day41 51单片机最小系统、GPIO控制、时序逻辑器件&#xff08;74HC138/595&#xff09;与LED点阵驱动原理一、嵌入式系统基础概念 1.1 嵌入式系统定义先设计硬件&#xff0c;基于硬件设计软件实现一个具体的功能 —— 专用的计算机系统硬件/软件可剪裁&#xff1a;根据功能需求…

html列表总结补充

1.有序列表的type属性不同的type值表示不同的排序标号1 表示列表项目用数字标号&#xff08;1,2,3...&#xff09; 1 a 表示列表项目用小写字母标号&#xff08;a,b,c...&#xff09; 2 A 表示列表项目用大写字母标号&#xff08;A,B,C...&#xff09; 3 i 表示列表项目用小写罗…

smartctl Current_Pending_Sector 硬盘待处理扇区

smartctl -a /dev/sdae当前值: 312 个待处理扇区 严重警告信号&#xff0c;硬盘发现了 312 个可疑扇区&#xff0c;正在等待重新分配 197 Current_Pending_Sector 0x0022 100 100 000 Old_age Always - 312读取错误频发 错误计数: 38 次 ATA 错误 …

MATLAB1-基本操作和矩阵输入-台大郭彦甫

目录 基础的指令 format 矩阵和向量 找出某行某列的矩阵元素 快速打出多个矩阵或者向量 矩阵连接 矩阵计算 一些特殊矩阵fuction 矩阵相关函数 基础的指令 clc 清空命令行窗口 clear all 清空工作区的全部变量 who 将工作区的全部变量显示出来 whos 工作区的变量信息详…