1.基本术语
2.抽象数据类型
/**
*
* 图的接口定义
*
*/
public interface Graph {
public static final int UndirectedGraph = 0;//无向图
public static final int DirectedGraph = 1;//有向图
//返回图的类型
public int getType();
//返回图的顶点数
public int getVexNum();
//返回图的边数
public int getEdgeNum();
//返回图的所有顶点
public Iterator getVertex();
//返回图的所有边
public Iterator getEdge();
//删除一个顶点v
public void remove(Vertex v);
//删除一条边e
public void remove(Edge e);
//添加一个顶点v
public Node insert(Vertex v);
//添加一条边e
public Node insert(Edge e);
//判断顶点u、v是否邻接,即是否有边从u到v
public boolean areAdjacent(Vertex u,Vertex v);
//返回从u指向v的边,不存在则返回null
public Edge edgeFromTo(Vertex u,Vertex v);
//返回从u出发可以直接到达的邻接顶点
public Iterator adjVertexs(Vertex u);
//对图进行深度优先遍历
public Iterator DFSTraverse(Vertex v);
//对图进行广度优先遍历
public Iterator BFSTraverse(Vertex v);
//求顶点v到其他顶点的最短路径
public Iterator shortestPath(Vertex v);
//求无向图的最小生成树,如果是有向图不支持此操作
public void generateMST() throws UnsupportedOperation;
//求有向图的拓扑序列,无向图不支持此操作
public Iterator toplogicalSort() throws UnsupportedOperation;
//求有向无环图的关键路径,无向图不支持此操作
public void criticalPath() throws UnsupportedOperation;
}
class UnsupportedOperation extends RuntimeException{
public UnsupportedOperation(String err) {
super(err);
}
}
3.图的存储方法
3.1 邻接矩阵
3.2 邻接表
3.3 双链式存储结构
/**
* 代码 7-3
* 双链式存储结构的顶点定义
*
*/
class Vertex{
private Object info;//顶点信息
private LinkedList adjacentEdges;//顶点的邻接边表
private LinkedList reAdjacentEdges;//顶点的逆邻接边表,无向图时为空
private boolean visited;//访问状态
private Node vexPosition;//顶点在顶点表中的位置
private int graphType;//顶点所在图的类型
private Object application;//应用。如求最短路径时为Path,求关键路径时为Vtime
//构造方法:在图G中引入一个新顶点
public Vertex(Graph g,Object info) {
this.info = info;
adjacentEdges = new LinkedListDLNode();
reAdjacentEdges = new LinkedListDLNode();
visited = false;
graphType = g.getType();
vexPosition = g.insert(this);
application = null;
}
//辅助方法:判断顶点所在图的类型
private boolean isUnDiGraphNode() {
return graphType == Graph.UndirectedGraph;
}
//获取或设置顶点信息
public Object getInfo() {
return info;
}
public void setInfo(Object info) {
this.info = info;
}
//与顶点的度相关的方法
public int getDeg() {
if(isUnDiGraphNode()){
return adjacentEdges.getSize();//无向图顶点的(出/入)度为邻接边表规模
}else{
return getOutDeg() + getInDeg();//有向图顶点的度为出度与入度之和
}
}
private int getOutDeg() {
return adjacentEdges.getSize();//有(无)向图顶点的出度为邻接表规模
}
private int getInDeg() {
if(isUnDiGraphNode()){
return adjacentEdges.getSize();//无向图顶点的入度就是它的度
}else{
return reAdjacentEdges.getSize();//有向图顶点入度为逆邻接表的规模
}
}
//获取与顶点关联的边
public LinkedList getAdjacentEdges() {
return adjacentEdges;
}
public LinkedList getReAdjacentEdges() {
if(isUnDiGraphNode()){
return adjacentEdges;//无向图顶点的逆邻接边表就是其邻接边表
}else{
return reAdjacentEdges;
}
}
//取顶点在所属图顶点集中的位置
public Node getVexPosition() {
return vexPosition;
}
//与顶点访问状态相关方法
public boolean isVisited() {
return visited;
}
public void setToVisited() {
visited = true;
}
public void setToUnvisited() {
visited = false;
}
//获取或设置顶点应用信息
protected Object getAppObj() {
return application;
}
protected void setAppObj(Object app) {
application = app;
}
//重置顶点状态信息
public void resetStatus() {
visited = false;
application = null;
}
}
/**
*
* 双链式存储结构的边定义
*
*/
class Edge{
public static final int NORMAL = 0;
public static final int MST = 1; //MST边
public static final int CRITICAL = 2;//关键路径中的边
private int weight;//权值
private Object info;//边的信息
private Node edgePosition;//边在边表中的位置
private Node firstVexPosition;//边的第一顶点与第二顶点
private Node secondVexPosition;//在顶点表中的位置
private Node edgeFirstPosition;//边在第一(二)顶点的邻接(逆邻接)边表中的位置
private Node edgeSecondPosition;//在无向图中就是在两个顶点的邻接边表中的位置
private int type;//边的类型
private int graphType;//所在图的类型
//构造方法:在图G中引入一条新边,其顶点为u、v
public Edge(Graph g, Vertex u,Vertex v,Object info) {
this(g,u,v,info,1);
}
public Edge(Graph g, Vertex u, Vertex v, Object info, int weight) {
this.info = info;
this.weight = weight;
edgePosition = g.insert(this);
firstVexPosition = u.getVexPosition();
secondVexPosition = v.getVexPosition();
type = Edge.NORMAL;
graphType = g.getType();
if(graphType == Graph.UndirectedGraph){
//如果是无向图,边应该加入其两个顶点的邻接边表
edgeFirstPosition = u.getAdjacentEdges().insertLast(this);
edgeSecondPosition = v.getAdjacentEdges().insertLast(this);
}else{
//如果是有向图,边加入起始点的邻接边表,终止点的逆邻接边表
edgeFirstPosition = u.getAdjacentEdges().insertLast(this);
edgeSecondPosition = v.getReAdjacentEdges().insertLast(this);
}
}
//get/set方法
public int getWeight() {
return weight;
}
public void setWeight(int weight) {
this.weight = weight;
}
public Object getInfo() {
return info;
}
public void setInfo(Object info) {
this.info = info;
}
public Vertex getFirVex(){
return (Vertex)firstVexPosition.getData();
}
public Vertex getSecondVex() {
return (Vertex)secondVexPosition.getData();
}
public Node getFirstVexPosition() {
return firstVexPosition;
}
public Node getSecondVexPosition() {
return secondVexPosition;
}
public Node getEdgeFirstPosition() {
return edgeFirstPosition;
}
public Node getEdgeSecondPosition() {
return edgeSecondPosition;
}
public Node getEdgePosition() {
return edgePosition;
}
//与边类型相关的方法
public void setToMST(){
type = Edge.MST;
}
public void setToCritical() {
type = Edge.CRITICAL;
}
public void resetType(){
type = Edge.NORMAL;
}
public boolean isMSTEdge() {
return type == Edge.MST;
}
public boolean isCritical() {
return type == Edge.CRITICAL;
}
}
4.图的ADT实现
5.图的遍历
5.1 深度遍历
5.2 广度遍历
6.图的连通性
6.1 无向图的连通分量和生成树
6.2 有向图的强连通分量
6.3 最小生成树
7.最短路径
7.1 单源最短路径
7.2 任意顶点间的最短路径
8.有向无环图及其应用
8.1 拓扑排序
8.2 关键路径