链式前向星是图存储的方式之一。
首先回顾我们已知的存储方式,主要是邻接矩阵和邻接表。
邻接矩阵复杂度
查询是否存在某条边: O ( 1 ) O(1) O(1)
遍历一个点的所有出边: O ( n ) O(n) O(n)
遍历整张图: O ( n 2 ) O(n^2) O(n2)
空间复杂度: O ( n 2 ) O(n^2) O(n2)
邻接表复杂度
查询是否存在 u − − > v u-->v u−−>v: O ( d + ( u ) ) O(d^+(u)) O(d+(u))
遍 u u u的所有出边: O ( d + ( u ) ) O(d^+(u)) O(d+(u))
遍历整张图: O ( n + m ) O(n+m) O(n+m)
空间复杂度: O ( n + m ) O(n+m) O(n+m)
链式前向星
链式前向星的前身是前向星
前向星是一种特殊的边集数组,我们把边集数组中的每一条边按照起点从小到大排序,如果起点相同就按照终点从小到大排序,并记录下以某个点为起点的所有边在数组中的起始位置和存储长度,那么前向星就构造好了
由于前向星有排序操作,所以时间复杂度并不理想。采用链式前向星,就可以降到线性时间复杂度
// C++ Version
// head[u] 和 cnt 的初始值都为 -1
void add(int u, int v) {
nxt[++cnt] = head[u]; // 当前边的后继
head[u] = cnt; // 起点 u 的第一条边
to[cnt] = v; // 当前边的终点
}
// 遍历 u 的出边
for (int i = head[u]; ~i; i = nxt[i]) { // ~i 表示 i != -1
int v = to[i];
}
h
e
a
d
[
i
]
head[i]
head[i] 代表起点为
i
i
i的第一条边的编号
t
o
[
i
]
to[i]
to[i] 边
i
i
i的终点
n
x
t
[
i
]
nxt[i]
nxt[i] 边
i
i
i的后继,当值为
−
1
-1
−1时代表无后继
c
n
t
cnt
cnt 代表当前边的编号
链式前向星复杂度
查询是否存在 u − − > v u-->v u−−>v: O ( d + ( u ) ) O(d^+(u)) O(d+(u))
遍 u u u的所有出边: O ( d + ( u ) ) O(d^+(u)) O(d+(u))
遍历整张图: O ( n + m ) O(n+m) O(n+m)
空间复杂度: O ( n + m ) O(n+m) O(n+m)