1 : 图: Graph:
图: 无向图, 有向图
2: 图表示: 图的邻接矩阵 和 图的邻接表
主要以 图的 邻接表为主:
邻接表表示法将图以邻接表(adjacency lists)的形式存储在计算机中。所谓图的邻接表,也就是图的所有节点的邻接表的集合;而对每个节点,它的邻接表就是它的所有出弧。邻接表表示法就是对图的每个节点,用一个单向链表列出从该节点出发的所有弧,链表中每个单元对应于一条出弧。为了记录弧上的权,链表中每个单元除列出弧的另一个端点外,还可以包含弧上的权等作为数据域。图的整个邻接表可以用一个指针数组表示。例如,例7所示的图,邻接表表示为
可以很方便的知道 点的邻接点
这种结构适合查找顶点及邻接点的信息,查顶点的度,增加或删除顶点和边(弧)也很方便,
但因指针多占用了存储空间,另外,某两顶点间是否有边(弧)也不如邻接矩阵那么清楚。
对有向图的邻接表,查顶点出度容易,而查顶点入度却困难,要遍历整个邻接表。
要想查入度象查出度那样容易,
就要建立逆邻接表
package com.algorithm.common.graph;
import com.algorithm.common.Bag;
/**
* 无权重无向图 (邻接表表示)
* @author lijunqing
*/
public class Graph {
/**
* 顶点数
*/
private int V;
/**
* 边数
*/
private int E;
/**
* 邻接表
*/
private Bag<Integer>[] adj;
public Graph(int v) {
this.V=v;
this.E=0;
adj=(Bag<Integer>[])new Bag[V];
for(int i=0; i < V; i++) { // 初始化邻接表
adj[i]=new Bag<Integer>();
}
}
public void addEdge(int v, int w) {
if(v < 0 || v > V) {
throw new IndexOutOfBoundsException();
}
if(w < 0 || w > V) {
throw new IndexOutOfBoundsException();
}
E++;
adj[v].add(w);
adj[w].add(v);
}
/**
* 返回Iterable可以遍历
* @param v
* @return
*/
public Iterable<Integer> adj(int v) {
if(v < 0 || v > V) {
throw new IndexOutOfBoundsException();
}
return adj[v];
}
public int V() {
return V;
}
public int E() {
return E;
}
}