首先是vertex 和edge:
class Vertex {
public:
int id;
std::vector<Vertex*> neighbors;
};
储存图
邻接表和邻接矩阵
// 邻接表
// graph[x] 存储 x 的所有邻居节点
vector<vector<int>> graph;
// 邻接矩阵
// matrix[x][y] 记录 x 是否有一条指向 y 的边
vector<vector<bool>> matrix;
注意分析两种存储方式的空间复杂度,对于一幅有 V 个节点,E 条边的图,邻接表的空间复杂度是 O(V+E),而邻接矩阵的空间复杂度是 O(V2)。
DFS遍历图:
// 遍历图的所有节点
void traverse(const Graph& graph, int s, std::vector<bool>& visited) {
// base case
if (s < 0 || s >= graph.size()) {
return;
}
if (visited[s]) {
// 防止死循环
return;
}
// 前序位置
visited[s] = true;
std::cout << "visit " << s << std::endl;
for (const Graph::Edge& e : graph.neighbors(s)) {
traverse(graph, e.to, visited);
}
// 后序位置
}
所以如果一幅图的 E 远小于 V^2(稀疏图),那么邻接表会比邻接矩阵节省空间,反之,如果 E 接近 V^2(稠密图),二者就差不多了
有向加权图
有向加权图怎么实现?很简单呀:
-
如果是邻接表,我们不仅仅存储某个节点 x 的所有邻居节点,还存储 x 到每个邻居的权重,不就实现加权有向图了吗?
-
如果是邻接矩阵,matrix[x][y] 不再是布尔值,而是一个 int 值,0 表示没有连接,其他值表示权重。
// 邻接表
// graph[x] 存储 x 的所有邻居节点以及对应的权重
// 具体实现不一定非得这样,可以参考后面的通用实现
struct Edge {
int to;
int weight;
};vector<vector
> graph; // 邻接矩阵
// matrix[x][y] 记录 x 指向 y 的边的权重,0 表示不相邻
vector<vector> matrix;
浙公网安备 33010602011771号