【总结】图的储存于遍历

图的基本概念

  • 定义
    图 (Graph) 是由若干给定的 顶点(vertex) 及连接两顶点的 边(edge) 所构成的图形。

  • 功能
    用来描述某些事物之间的某种特定关系
    例如:顶点用于代表事物,而边用于表示两个事物间所具有某种关系。

  • 组成
    二元组:\(G = (V(G), E(G))\)

    • \(V(G)\):点集,对于集合 \(V\) 中的每个元素,我们称其为 顶点节点,简称
    • \(E(G)\):为 \(V(G)\) 中各结点之间边的集合,称为 边集
  • 种类

    • 无向图
      边没有指定的方向。
    • 有向图:
      边有指定的方向。
    • 带权图
      边上带有权值的图:
    • 正权图
      边权没有负数的图
    • 负权图
      边权有负数的图
  • 其它术语

    • 连通图 (connected graph) : 任意两点之间都有路径连接的图。

    • 自环 (loop): 对 \(E\) 中的边 \(e = (u, v)\),若 \(u = v\),则 \(e\) 被称作一个自环。

    • 度 (degree) : 与一个顶点 \(v\) 关联的边的条数,记作。
      特别的,在有向图中有出度和入度。

      • 入度 (in-degree): 以点 \(v\)弧头 的边的数目称为该顶点的入度 。

      • 出度 (out-degre): 以点 \(v\)弧尾 的边的数目称为该顶点的出度。

    • 有向无环图 (DAG): 没有环的有向图。

图的存储及遍历

邻接矩阵

这是最简单的存储方式,我们定义一个二位 bool 数组 \(G\), 若 \(G_{i, j}\)\(1\),表示有边,否则无边。如果是无向图,则要双向存边。

const int MAXN = 1005;
bool G[MAXN][MAXN];
void dfs(int k) {
	printf("%d ", k);
	vis[k] = 1;
	for (int i = 1; i <= n; i++)
		if (G[k][i] && !vis[i])
			dfs(i);
}
int n, m;
scanf("%d %d", &n, &m);
for (int i = 1; i <= m; i++) {
	int x, y;
	scanf("%d %d", &x, &y);
	G[x][y] = 1;
}
dfs(1);

对于带权图我们就会换成 \(int\) 类型,\(G_{i, j}\) 的值,就是 \(i\)\(j\) 的边权。

const int MAXN = 1005;
int G[MAXN][MAXN];
int n, m;
scanf("%d %d", &n, &m);
for (int i = 1; i <= m; i++) {
	int x, y, w;
	scanf("%d %d %d", &x, &y, &w);
	G[x][y] = w;
}

邻接表

我们一边使用 vector 实现。

用来记录与每个点相邻的点。

const int MAXN = 1e4 + 5;
vector<int> G[MAXN];
for (int i = 1, u, v; i <= m; i++) {
    scanf("%d %d", &u, &v);
    G[u].push_back(v);
    G[v].push_back(u);
}
for (int i = 1; i <= n; i++) {
	sort(v[i].begin(), v[i].end(), cmp);
	for (int j = 0; j < v[i].size(); j++)
		printf("%d ", v[i][j]);
	printf("\n");
}

链式前向星

链式前向星就是数组实现的邻接表。

我个人还是喜欢用链式前向星。

const int MAXN = 2005, MAXM = 20005;
int n, m;
int head[MAXN], next[MAXM], ver[MAXM], edge[MAXM], tot;
void add(int x, int y, int z) {
	next[++tot] = head[x], head[x] = tot, ver[tot] = y, edge[tot] = z;
}
void dfs(int k) {
	vis[k] = 1;
	printf("%d ", k);
	for (int i = head[k]; i; i = next[i]) {
		int v = ver[i];
		if (!vis[v])
			dfs(v);
	}
}
scanf("%d %d", &n, &m);
for (int i = 1; i <= m; i++) {
	int x, y, z;
	scanf("%d %d %d", &x, &y, &z);
	add(x, y, z), add(y, x, z);
}
dfs(1);
posted @ 2022-07-28 08:05  zhou_ziyi  阅读(39)  评论(0)    收藏  举报