什么是图?
图(Graph)是一种数据结构,用于表示对象及其相互关系。图由顶点(Vertex)和边(Edge)组成:
- 顶点:图中的点,表示对象或元素。
- 边:连接两个顶点的线,表示顶点之间的关系。
图的类型
- 无向图(Undirected Graph):边没有方向,表示双向连接。
- 有向图(Directed Graph):边有方向,表示单向连接。
- 加权图(Weighted Graph):边带有权重,表示连接的强度或距离。
图的表示方法
图的表示方法有两种常见方式:邻接矩阵和邻接表。选择哪种表示方法取决于图的性质和应用场景。
邻接矩阵
邻接矩阵是一种用二维数组表示图的方法,矩阵的行和列分别对应图的顶点。如果顶点 (i) 和顶点 (j) 之间有边,则矩阵的元素 ([i][j]) 为1;否则为0。
示例
假设我们有一个无向图,顶点集合为 ({A, B, C, D}),边集合为 ({(A, B), (A, C), (B, D), (C, D)})。这意味着顶点之间的连接关系如下:
- A 和 B 之间有一条边
- A 和 C 之间有一条边
- B 和 D 之间有一条边
- C 和 D 之间有一条边
用邻接矩阵表示这个图如下:
A B C D
A [ 0 1 1 0 ]
B [ 1 0 0 1 ]
C [ 1 0 0 1 ]
D [ 0 1 1 0 ]
矩阵中,1表示两个顶点之间有边,0表示没有边。
邻接矩阵的特点
- 优点:判断两个顶点是否相连的时间复杂度为 (O(1))。
- 缺点:需要 (O(V^2)) 的空间,其中 (V) 是顶点的数量。对于稀疏图(边很少的图),空间利用率较低。
邻接表
邻接表是一种用链表数组表示图的方法,每个顶点都有一个链表,链表中存储的是与该顶点相邻的顶点。
示例
用邻接表表示上面的无向图如下:
A: B -> C
B: A -> D
C: A -> D
D: B -> C
每个顶点后面的箭头表示与该顶点相邻的顶点。
邻接表的特点
- 优点:需要 (O(V + E)) 的空间,其中 (V) 是顶点的数量,(E) 是边的数量。对于稀疏图,空间利用率较高。
- 缺点:判断两个顶点是否相连的时间复杂度为 (O(V))(需要遍历链表)。
邻接矩阵的实现
下面是用Java实现邻接矩阵表示图的代码:
public class Graph {
private int[][] adjMatrix; // 邻接矩阵
private int numVertices; // 顶点数量
// 构造函数
public Graph(int numVertices) {
this.numVertices = numVertices;
adjMatrix = new int[numVertices][numVertices];
}
// 添加边
public void addEdge(int i, int j) {
adjMatrix[i][j] = 1;
adjMatrix[j][i] = 1; // 无向图
}
// 删除边
public void removeEdge(int i, int j) {
adjMatrix[i][j] = 0;
adjMatrix[j][i] = 0;
}
// 打印邻接矩阵
public void printMatrix() {
for (int i = 0; i < numVertices; i++) {
for (int j = 0; j < numVertices; j++) {
System.out.print(adjMatrix[i][j] + " ");
}
System.out.println();
}
}
public static void main(String[] args) {
Graph graph = new Graph(4);
graph.addEdge(0, 1);
graph.addEdge(0, 2);
graph.addEdge(1, 3);
graph.addEdge(2, 3);
graph.printMatrix();
}
}
邻接矩阵图解
邻接表的实现
下面是用Java实现邻接表表示图的代码:
import java.util.LinkedList;
public class Graph {
private LinkedList<Integer>[] adjLists; // 邻接表数组
private int numVertices; // 顶点数量
// 构造函数
public Graph(int numVertices) {
this.numVertices = numVertices;
adjLists = new LinkedList[numVertices];
for (int i = 0; i < numVertices; i++) {
adjLists[i] = new LinkedList<>();
}
}
// 添加边
public void addEdge(int i, int j) {
adjLists[i].add(j);
adjLists[j].add(i); // 无向图
}
// 删除边
public void removeEdge(int i, int j) {
adjLists[i].remove((Integer) j);
adjLists[j].remove((Integer) i);
}
// 打印邻接表
public void printAdjLists() {
for (int i = 0; i < numVertices; i++) {
System.out.print(i + ": ");
for (int j : adjLists[i]) {
System.out.print(j + " ");
}
System.out.println();
}
}
public static void main(String[] args) {
Graph graph = new Graph(4);
graph.addEdge(0, 1);
graph.addEdge(0, 2);
graph.addEdge(1, 3);
graph.addEdge(2, 3);
graph.printAdjLists();
}
}
邻接表图解
结论
通过上述讲解和实例代码,我们详细展示了图的定义、表示方法及其两种常用表示方式:邻接矩阵和邻接表。图是一种重要的数据结构,广泛应用于各种领域。希望这篇博客对您有所帮助!
如果您觉得这篇文章对您有帮助,请关注我的CSDN博客,点赞并收藏这篇文章,您的支持是我持续创作的动力!
关键内容总结:
- 图的定义和分类
- 图的两种常用表示方法:邻接矩阵和邻接表
- 邻接矩阵和邻接表的优缺点及适用场景
- 邻接矩阵和邻接表的Java实现及其图