图需要存储的信息有以下这些
1、顶点信息
2、边或弧的信息,如果有权,也需要表示出来
3、顶点个数、边(弧)的个数
邻接矩阵及其实现
顶点数据存储:
一维数组
边(弧)信息存储
邻接矩阵
图中n个顶点之间相邻关系的n阶矩阵(即二维数组a[n][n])
下面举例说明
无向图邻接矩阵,中间斜着的一条线上的0,代表的意义是同一顶点,其余部分,1代表2顶点之间有边,0代表无边。
无向网邻接矩阵,中间斜着的一条线上的0,代表的意义是同一顶点,其余部分,用一个大于所有边的权值的值来表示没有没有边,具体的值表示边上的权值。
有向图邻接矩阵,有几个特点,不一定对称,行方向上的非0元素的个数意味着该顶点的出度,列方向上的非0元素的个数意味着该顶点的入度。
邻接矩阵法的优点:
容易实现图的操作,如:求某顶点的度、判断顶点之间是否有边(弧)、找顶点的邻接点
邻接矩阵法的缺点:
n个顶点,需要n*n个单元存储边(弧),空间效率为O(n2),
对于稀疏图的话,尤其浪费空间
图的java定义,图当中顶点类型为int,然后有4个顶点,6条边(弧),该定义既可以表示有向图,也可以表示无向图,同时也可以表示有整形权的网。
public class Graph {
int vn;
int en;
int[] vex;
int[][] arc;
public static void main(String[] args){
Graph graph = new Graph();
graph.vn = 10;
graph.en = 20;
graph.vex = new int[graph.vn];
graph.arc = new int[graph.vn][graph.vn];
}
}
建图运算,我们设置了1,2,3,4一共四个顶点,然后,在所有不同顶点之间画上了边,其实这里我们就是做了一个完全图(至于是有向还是无向,全看你怎么理解和使用了)
for (int i = 1; i <= 4; i ++){
graph.vex[i - 1] = i;
}
for (int i = 1; i <= 4; i ++){
for (int j = 1; j <= 4; j ++) {
graph.arc[i - 1][j - 1] = i == j ? 0 : 1;
}
}
邻接表及其实现
是顺序与链接相结合的图的存储方式
所有顶点组成一个数组,为每个顶点建立一个单向链表
下面还是举例说明
无向图邻接表
无向网邻接表,增加了每一条边的权值信息
有向图邻接表
邻接表的优点:
空间效率高;容易寻找顶点的邻接点
邻接表的缺点:
对于有向图而言,查询顶点的出度很容易,但是要查询入度,就需要遍历整个表。
邻接表的java定义,这里我们跟前面的概念部分有所不同,不过问题不大,需要注意的是,如果是网的存储的话,这样的做法就不行了,可能需要针对边,再做一个类。
public class GraphWithLink {
Vex[] vex;
List<Vex> arc = new LinkedList<Vex>();
int vn;
int en;
}
public class Vex {
int i;
}
建图运算,我们还是建一个4个顶点的完全图
public static void main(String[] args){
GraphWithLink graph = new GraphWithLink();
graph.vn = 4;
graph.en = 6;
graph.vex = new Vex[graph.vn];
for (int i = 1; i <= 4; i ++){
Vex vex = new Vex();
vex.i = i;
graph.vex[i - 1] = vex;
}
for (int i = 1; i <= 4; i++) {
graph.arc.add(graph.vex[i - 1]);
for (int j = 1; j <= 4; j++) {
if (i != j){
graph.arc.add(graph.vex[j - 1]);
}
}
}
}