一般的表示方法
- 矩阵表示法:将所有点对的关系存储到一个矩阵中,如果树有
N
个点,那么需要开辟
N∗N 大小的矩阵 - 基于地址(或者vector容器)的链表法:将与点
A
有关的边存储到
A 的链表。一般选择这种方法,但是该方法需要不断的重新开辟新空间。随着图的节点增加时,需要为新节点创建空间,并添加到对应的链表中。
在需要重复构建不同的图的问题中,上面两种传统的方法,或者(图的数据结构)显得效率不高。分析原因:第一种方法开辟了许多空间,但是利用率低;方法二随着图的改变而增减空间,但是在任何语言中,空间的开辟和释放都是需要时间的,因此,如果你需要重复构建图,且图的规模具有上限,那么可以考虑本文的方法,如下。
基于数组的前插表示法
一般地,下面的图都是有向图,因为无向图可以当做有向图。
根据图的节点数上限开辟足够的空间,存储以下信息:
1.
Arry:head[u]
head
存储与节点
u
相关联的边序号集合中的某一个。ps:通过
2.
struct Edge{
int v; //(u,v)边终点
int w; //(u,v)边的权值
int next; //与u相关的下一边(非边(u,v))
}
3.
Arry:edges[id]
id
表示边的序号,将图的所有边都按照
Edge
结构体存到这个数组中
下面用代码说话:
/*基于前插表法的图(graph)结构,所有边都是有向的*/
//记录与节点相关的边编号
int head[MAX_N];
//边结构:指向点序号,权值,下一条边序号
struct Edge{
int v;
int w;
int next;
}edge[2*MAX_N];
//插入新边(u->v)到u的链表(用数组表示链表)
void addEdge(int u, int v, int w, int id){
edge[id].v = v;
edge[id].w = w;
edge[id].next = head[u];
head[u] = id;
return;
}
void buildTree(int N){
int u, v, w;
for(int i = 0; i < N-1; ++i){
scanf("%d%d%d", &u, &v, &w);
addEdge(u, v, w, i);
addEdge(v, u, w, i+N-1);
}
return;
}
练习题目:
http://blog.csdn.net/u010232171/article/details/49703557