圖論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
英文地址,請注明出處:http://en.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 工作區的變量信息詳…