数据结构、算法总述:数据结构/算法 C/C++-CSDN博客
树与图的存储
树是一种特殊的图,与图的存储方式相同。
对于无向图中的边ab,存储两条有向边a->b, b->a。
因此我们可以只考虑有向图的存储。
(1) 邻接矩阵:g[a][b] 存储边a->b
(2) 邻接表:
// 对于每个点k,开一个单链表,存储k所有可以走到的点。h[k]存储这个单链表的头结点
int h[N], e[N], ne[N], idx;
// 添加一条边a->b
void add(int a, int b)
{
e[idx] = b, ne[idx] = h[a], h[a] = idx ++ ;
}
// 初始化
idx = 0;
memset(h, -1, sizeof h);
拓扑排序
拓扑排序是针对有向无环图(DAG,Directed Acyclic Graph)的一种排序算法。在这种图中,从一个顶点出发,顺着有向边的关系,可以到达其他的顶点,但是图中不存在环,即不能回到出发点的路径。拓扑排序的目的是将图中的所有顶点进行排序,使得对于任意的有向边(u, v),u都排在v的前面。
思路:
- 一个有向图,如果图中有入度为 0 的点,就把这个点删掉,同时也删掉这个点所连的边。
- 一直进行上面出处理,如果所有点都能被删掉,则这个图可以进行拓扑排序。
步骤:
- 首先记录各个点的入度(有多少条边指向它)。
- 然后将入度为 0 的点放入队列。
- 将队列里的点依次出队列,然后找出所有出队列这个点发出的边,删除边,同时边的另一侧的点的入度 -1。
- 如果所有点都进过队列,则可以拓扑排序,输出所有顶点。否则输出-1,代表不可以进行拓扑排序。
算法模板:
解释代码bool topsort()
{
int hh = 0, tt = -1;
// d[i] 存储点i的入度
for (int i = 1; i <= n; i ++ )
if (!d[i])
q[ ++ tt] = i;
while (hh <= tt)
{
int t = q[hh ++ ];
for (int i = h[t]; i != -1; i = ne[i])
{
int j = e[i];
if (-- d[j] == 0)
q[ ++ tt] = j;
}
}
// 如果所有点都入队了,说明存在拓扑序列;否则不存在拓扑序列。
return tt == n - 1;
}
题目:
848. 有向图的拓扑序列 - AcWing题库https://www.acwing.com/problem/content/description/850/