前向星是存图存树的工具.
存图可以用矩阵-二维数组,比如:
![5c71aaf0796002822ca52ff0c2e970f8.png](https://img-blog.csdnimg.cn/img_convert/5c71aaf0796002822ca52ff0c2e970f8.png)
简单易懂,确定节点关系直接edge[i][j]即可.
但是,也存在问题,如果要找i的所有临近节点,需要遍历完i行;
此外,对于稀疏图,矩阵存储会存在大量的空间浪费.
可以用邻接链表存储图:
为每个顶点建立一个链表,第i个链表表示从节点i出发的所有节点,例如
![b2627ff45442cae4477ea28f538a6d50.png](https://img-blog.csdnimg.cn/img_convert/b2627ff45442cae4477ea28f538a6d50.png)
![d0aadc884763b4f45e8f9a8ea71800c2.png](https://img-blog.csdnimg.cn/img_convert/d0aadc884763b4f45e8f9a8ea71800c2.png)
邻接链表在查找结点i的(全部)邻接节点时比较有效;
存储空间也是O(N+E)节点数+边数.
适合稀疏图,需要大量遍历临近节点的算法.
*以上来自王道论坛.
前向星
前向星是一个存图的工具,一种特殊的边集数组
所以前向星数组对应的其实是边的信息,下标就是边的下标
把边集数组中的每一条边按照起点从小到大排序,如果起点相同就按照终点从小到大
并且记录下以某个点为起点的所有边在数组中的起始位置和存储长度
len[i]数组记录以i为起点的边在数组中的储存长度
head[i]数组记录以i为边集在数组中的第一个存储位置(哪条边)
![f641bfa6ab954fd77091033a6341e83a.png](https://img-blog.csdnimg.cn/img_convert/f641bfa6ab954fd77091033a6341e83a.png)
输入
1 2
2 3
3 4
1 3
4 1
1 5
4 5
排序得到的
编号 1 2 3 4 5 6 7
起点 1 1 1 2 3 4 4
终点 2 3 5 3 4 1 5
len[1]=3 head[1]=1
len[2]=1 head[2]=4
len[3]=1 head[3]=5
len[4]=2 head[4]=6
但是前向星会有排序操作,快排时间O(nlog(n)).
#include
以上参考:https://www.cnblogs.com/Emcikem/p/11541489.html
链式前向星其实就是静态建立的邻接表,时间效率为O(m),空间效率也为O(m)。遍历效率也为O(m).m是边数
对于下面的数据,第一行5个顶点,7条边。接下来是边的起点,终点和权值。也就是边1 -> 2 权值为1。
5 7
1 2 1
2 3 2
3 4 3
1 3 4
4 1 5
1 5 6
4 5 7
链式前向星存的是以[1,n]为起点的边的集合.
对于上面的数据输出就是:
1 //以1为起点的边的集合
1 5 6
1 3 4
1 2 1
2 //以2为起点的边的集合
2 3 2
3 //以3为起点的边的集合
3 4 3
4 //以4为起点的边的集合
4 5 7
4 1 5
5 //以5为起点的边不存在
我们先对上面的7条边进行编号第一条边是0以此类推编号[0~6].
边的结构:
struct
然后我们要知道两个变量的含义:
- Next,表示与这个边起点相同的上一条边的编号。
- head[ i ]数组,表示以 i 为起点的最后一条边的编号。
添加边的函数:
void
head数组一般初始化为-1.
遍历寻找以 i 为起点的所有边:
head[i]->起点一致的上一条->...->-1则停止
首先等于head[ i ],注意head[ i ]中存的是以 i 为起点的最后一条边的编号。然后通过edge[ j ].next来找起点相同的上一条边的编号。我们初始化head为-1,所以找到edge[ j ].next为 -1时终止。
for
具体实例-加黑的表示寻找节点1出发的边:
重点注意head[] next
对于1 2 1这条边:edge[0].to = 2; edge[0].next = -1; head[1] = 0;
对于2 3 2这条边:edge[1].to = 3; edge[1].next = -1; head[2] = 1;
对于3 4 3这条边:edge[2].to = 4; edge[2],next = -1; head[3] = 2;
对于1 3 4这条边:edge[3].to = 3; edge[3].next = 0; head[1] = 3;
对于4 1 5这条边:edge[4].to = 1; edge[4].next = -1; head[4] = 4;
对于1 5 6这条边:edge[5].to = 5; edge[5].next = 3; head[1] = 5;
对于4 5 7这条边:edge[6].to = 5; edge[6].next = 4; head[4] = 6;
具体代码:
#include
以上参考:https://blog.csdn.net/sugarbliss/article/details/86495945
具体练习例子:
【模板】最近公共祖先(LCA) - 洛谷www.luogu.com.cn洛谷P3379, LCA最近公共祖先问题.