1. 树与图的存储
(1).邻接矩阵
解释:
在二维数组中,0表示没有连线,1表示有连线.
通过二维数组,我们可以很快的找到一个顶点和哪些顶点有连线(比如A顶点,只需要遍历第一行即可)
另外,A-A,B-B(也就是顶点到自己的连线),通常使用0表示.
邻接矩阵的问题:
邻接矩阵还有一个比较严重的问题,就是如果图是一个稀疏图
那么矩阵中将存在大量的0,这意味着我们浪费了计算机存储空间来表示根本不存在的边。
(2)邻接表
加入有向边,权值为w
// 对于每个点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 ++ ;
}
2.树与图的深搜与宽搜
(1) 深度优先遍历
int dfs(int u)
{
st[u] = true; // st[u] 表示点u已经被遍历过
for (int i = h[u]; i != -1; i = ne[i])
{
int j = e[i];
if (!st[j]) dfs(j);
}
}
(2) 宽度优先遍历
queue<int> q;
st[1] = true; // 表示1号点已经被遍历过
q.push(1);
while (q.size())
{
int t = q.front();
q.pop();
for (int i = h[t]; i != -1; i = ne[i])
{
int j = e[i];
if (!s[j])
{
st[j] = true; // 表示点j已经被遍历过
q.push(j);
}
}
}
拓扑排序
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;
}