如何在 Java 中实现图数据结构
本文将详细介绍如何在 Java 中实现图数据结构,特别是如何使用 HashMap
实现图的邻接表,并通过两个示例演示图的实现与操作。
一. 图的基本概念
图是一种数据结构,用于表示节点(顶点)之间的连接关系。图可以是有向图或无向图,节点可以有多个边连接。以下是图的一些基本概念:
-
节点(Vertex):图中的基本元素,表示一个点。 -
边(Edge):连接两个节点的线,表示两个节点之间的关系。 -
邻接表(Adjacency List):一种图的表示方法,使用列表存储每个节点及其相邻节点。
二. 使用 HashMap
实现图的邻接表
1. 基本代码示例
以下是一个使用 HashMap
实现图的邻接表的示例代码:
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
public class Graph {
// 定义图的邻接表,使用 HashMap 存储每个节点及其相邻节点
private Map<Integer, Set<Integer>> adjacencyList;
// 构造函数初始化邻接表
public Graph() {
adjacencyList = new HashMap<>();
}
// 添加一个节点到图中
public void addVertex(int vertex) {
adjacencyList.putIfAbsent(vertex, new HashSet<>());
}
// 添加一条边
public void addEdge(int source, int destination) {
adjacencyList.putIfAbsent(source, new HashSet<>());
adjacencyList.putIfAbsent(destination, new HashSet<>());
adjacencyList.get(source).add(destination);
adjacencyList.get(destination).add(source); // 无向图
}
// 打印图的邻接表
public void printGraph() {
for (int vertex : adjacencyList.keySet()) {
System.out.print(vertex + " -> ");
for (int neighbor : adjacencyList.get(vertex)) {
System.out.print(neighbor + " ");
}
System.out.println();
}
}
public static void main(String[] args) {
// 创建一个图对象
Graph graph = new Graph();
// 添加节点
graph.addVertex(1);
graph.addVertex(2);
graph.addVertex(3);
graph.addVertex(4);
graph.addVertex(5);
// 添加边
graph.addEdge(1, 2);
graph.addEdge(1, 3);
graph.addEdge(1, 4);
graph.addEdge(2, 4);
graph.addEdge(2, 5);
graph.addEdge(3, 4);
graph.addEdge(3, 5);
graph.addEdge(4, 5);
// 打印图的邻接表
graph.printGraph();
}
}
代码说明
-
import java.util.HashMap;
:导入HashMap
类,用于实现邻接表。 -
import java.util.HashSet;
:导入HashSet
类,用于存储每个节点的相邻节点。 -
import java.util.Map;
:导入Map
接口,用于定义邻接表的类型。 -
import java.util.Set;
:导入Set
接口,用于定义相邻节点的集合。 -
private Map<Integer, Set<Integer>> adjacencyList;
:定义一个HashMap
作为图的邻接表,其中每个节点(Integer
类型)映射到一个包含相邻节点的集合(Set<Integer>
类型)。 -
public Graph()
:构造函数初始化邻接表。 -
public void addVertex(int vertex)
:向图中添加一个节点。如果节点不存在,则创建一个新的HashSet
以存储相邻节点。 -
public void addEdge(int source, int destination)
:向图中添加一条边。如果源节点和目标节点不存在,则创建它们;否则,将目标节点添加到源节点的邻接列表中,并将源节点添加到目标节点的邻接列表中(无向图)。 -
public void printGraph()
:打印图的邻接表。遍历每个节点及其相邻节点,并输出结果。 -
public static void main(String[] args)
:主函数用于测试图的创建、节点和边的添加以及邻接表的打印。
三. 使用类封装边信息
在这个示例中,我们将图的边信息封装到一个 Edge
类中,并演示如何在图中管理和显示这些边。
1. 基本代码示例
以下是一个封装边信息的图实现示例:
public class Graph {
// 内部类 Edge 用于存储边的信息
class Edge {
int source, destination;
}
int vertices, edges; // 节点数和边数
Edge[] edge; // 存储边的数组
// 构造函数初始化图的边
Graph(int vertices, int edges) {
this.vertices = vertices;
this.edges = edges;
edge = new Edge[edges];
for (int i = 0; i < edges; i++) {
edge[i] = new Edge();
}
}
// 打印图的边信息
static void print(Graph graph_object, int edges_count) {
System.out.println("图的边连接关系为:");
for (int i = 0; i < edges_count; i++) {
System.out.println(graph_object.edge[i].source + " - " + graph_object.edge[i].destination);
}
}
// 连接图的边
static void connect_edges(Graph graph_object) {
graph_object.edge[0].source = 1;
graph_object.edge[0].destination = 2;
graph_object.edge[1].source = 1;
graph_object.edge[1].destination = 3;
graph_object.edge[2].source = 1;
graph_object.edge[2].destination = 4;
graph_object.edge[3].source = 2;
graph_object.edge[3].destination = 4;
graph_object.edge[4].source = 2;
graph_object.edge[4].destination = 5;
graph_object.edge[5].source = 3;
graph_object.edge[5].destination = 4;
graph_object.edge[6].source = 3;
graph_object.edge[6].destination = 5;
graph_object.edge[7].source = 4;
graph_object.edge[7].destination = 5;
}
public static void main(String[] args) {
int vertices_count = 5;
int edges_count = 8;
Graph graph_object = new Graph(vertices_count, edges_count);
System.out.println("图对象已定义。");
connect_edges(graph_object);
print(graph_object, edges_count);
}
}
代码说明
-
class Edge
:定义一个内部类Edge
,用于存储边的源节点和目标节点。 -
Graph(int vertices, int edges)
:构造函数初始化图的节点数和边数,并创建一个Edge
类型的数组来存储边。 -
static void print(Graph graph_object, int edges_count)
:静态方法用于打印图的边信息。 -
static void connect_edges(Graph graph_object)
:静态方法用于连接图的边,手动设置每条边的源节点和目标节点。 -
public static void main(String[] args)
:主函数用于测试图的创建、边的连接以及边信息的打印。
通过以上两个示例,我们展示了如何在 Java 中实现图的数据结构。使用 HashMap
可以高效地表示和操作图的邻接表,而通过封装边信息的方式可以使图的边管理更加直观。