我们都知道图的存储有两种方法,邻接矩阵以及邻接表,邻接矩阵是将每一对点之间是否存在边以及边的权值记录下来,优点是可以快速的访问任意两点之间的边,但是缺点是对空间的消耗太大,适用于点不太多的稀疏图;而邻接表则是采用类似链表的方式 ,以每个点为头节点来记录从该点出发的所有边,这样的好处是减少了很多的无谓消耗,每一次的存储都是有意义的,但是缺点是遇到一条边只能去遍历它的起点所在的链表来找到这条边,也就是说不能快速的访问任一的一条边。
邻接矩阵的实现非常简单,只需要开一个足够大的map二维数组,map[i][j]表示的是点i和j之间的边的情况。
这里重点要说的是邻接表的 实现,我们一般采用的是链式前向星来实现。前向星指的是一种边集数组,把边集数组中的每一条边按照起点从小到大排序,如果起点相同就按照终点从小到大排序,并记录下以某个点为起点的所有边在数组中的起始位置和存储长度,那么前向星就构造好了.但是这个方式需要额外的排序操作,所以我们还引进了链式前向星,这样就可以按照编号的逆序直接存储边而不用排序了。来看具体实现。
#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
const int maxn = 10;
int head[maxn],no;
struct node
{
int from; //起点
int to; //终点
int w; //权值
int next; //下一条边的编号
}e[maxn];
void init()
{
memset(head, -1, sizeof(head)); //将-1作为终结
no = 0;
}
void add(int u, int v, int w)
{
e[no].from = u;
e[no].to = v;
e[no].w = w;
e[no].next = head[u]; //将本条边的next值指向该起点之前记录的最后一条边
head[u] = no++; //将该起点的最后一条边变为本边,并对编号no自加以便下一次使用
}
int main()
{
int u, v, w,n;
scanf("%d",&n);
init();
while (n--)
{
scanf("%d%d%d", &u, &v, &w);
add(u, v, w);
}
int target_u;
scanf("%d", &target_u);
for (int i = target_u; i != -1; i = e[i].next)
{
//process
}
return 0;
}
用head数组来记录起点为i的所有边中最大的编号,之后逐条访问next就可以遍历所有的同起点的边。
链式前向星的实现相当于是链表的插入操作。