图的存储
图,在C++中是一种非常重要的数据结构,本章就先来讲一下图的存储。
1.邻接矩阵:
直接定义二维数组
2.邻接表:
邻接表使用的存储方式是链表,即每个节点只储存它的直连邻居。因为非直联的节点不用储存,所以节省了空间,储存效率非常高,空间复杂度为
常用 STL vector 来实现邻接表:
struct edge{
int from,to,w;
edge(int a,int b,int c){
from=a,to=b,w=c;//对边赋值
}
};
vector<edge>e[N]; //e[i]:存储第i个节点连接的所有边
//初始化:
for(int i=1;i<=n;i++)e[i].clear();
//存边:
e[a].push_back(edge(a,b,c));
//遍历节点u的所有邻居:
for(int i=0;i<e[u].size();i++){
int v=e[u][i].to,w=e[u][i].u;
......
}
(用
3.链式前向星:
链式前向星是一种常用的图存储结构,用于表示稀疏图,尤其适用于大规模图的存储和遍历。本文将介绍链式前向星的概念、实现方式以及常见应用场景。
链式前向星是一种以链表形式组织的图存储结构。它使用两个数组,分别为"头结点数组"和"边结点数组",来表示图中的顶点和边。
- 头结点数组:每个顶点对应一个头结点,头结点包含连接到该顶点的第一条边的指针。
- 边结点数组:每条边对应一个边结点,边结点包含起始顶点、终止顶点和下一条以相同起始顶点的边的指针。
通过这样的存储方式,可以有效地表示各个顶点之间的关系,并支持高效的图遍历和查询操作。
下面是用 C++ 实现链式前向星的代码示例:
#include <iostream>
#include <vector>
using namespace std;
// 边结点
struct EdgeNode {
int to; // 终止顶点
int weight; // 权重(如果有权重的话)
int nextEdgeIndex; // 下一条以相同起始顶点的边的索引
};
// 头结点
struct HeadNode {
int firstEdgeIndex; // 第一条边的索引
};
int main() {
int numVertices, numEdges;
cin >> numVertices >> numEdges;
vector<HeadNode> heads(numVertices); // 头结点数组
vector<EdgeNode> edges(numEdges); // 边结点数组
for (int i = 0; i < numEdges; i++) {
int from, to, weight;
cin >> from >> to >> weight;
edges[i].to = to;
edges[i].weight = weight;
edges[i].nextEdgeIndex = heads[from].firstEdgeIndex;
heads[from].firstEdgeIndex = i;
}
// 遍历图,输出每个顶点的相邻顶点和权重(如果有权重的话)
for (int i = 0; i < numVertices; i++) {
cout << "Vertex " << i << ": ";
int edgeIndex = heads[i].firstEdgeIndex;
while (edgeIndex != -1) {
EdgeNode edge = edges[edgeIndex];
cout << "(" << edge.to << ", " << edge.weight << ") ";
edgeIndex = edge.nextEdgeIndex;
}
cout << endl;
}
return 0;
}
链式前向星适用于大规模稀疏图的存储和遍历。由于只存储实际存在的边,因此可以减少存储空间的消耗。常见的应用场景包括:
- 网络流算法:链式前向星能有效地表示网络流中的图结构,并进行相关算法操作,如最大流、最小割等。
- 最短路径算法:链式前向星可以用于实现 Dijkstra 算法和 Bellman-Ford 算法等最短路径算法,以提高计算效率。
- 拓扑排序:链式前向星可以用于拓扑排序算法,通过遍历有向无环图的顶点和边来确定他们之间的依赖关系。
链式前向星是一种高效的图存储方法,适用于大规模稀疏图的存储与遍历。通过合理利用头结点数组和边结点数组的组织,可以快速访问图中的顶点和边,从而支持各种图算法的应用。