020无环加权有向图的最短路径实现

无环加权有向图的最短路径实现

  • 图学习笔记索引
  • 本文参考《算法(第4版)》
    • 1.依赖类
    • 2.无环加权有向图的最短路径

图学习笔记索引

001自定义输入流In类实现
002背包数据类型Bag实现
003无向图数据类型实现
004基于图的深度优先搜索
005使用深度优先搜索找图中的所有连通分量
005-1基于深度优先搜索查找图中连通路径
006基于深度优先搜索判断图中是否存在环
007基于深度优先搜索判断一个无向图图是否是一个二分图
008广度优先搜索查找连通图中的最短路径
009有向图数据类型实现
010有向图的可达性
011带权重的无向边数据类型Edge实现
012加权无向图数据类型实现
013寻找有向环
014有向图中基于深度优先搜索的顶点排序
015查找、排序、符号表、散列表等算法实现(1)
016最小生成树Prim算法延时实现
017最小生成树Prim算法即时实现
018加权有向边及加权有向图的实现
019有向图的最短路径Dijkstra算法实现

本文参考《算法(第4版)》

1.依赖类

从文件中读取图的顶点关系。
tinyEWDAG.txt中的内容:
8
13
5 4 0.35
4 7 0.37
5 7 0.28
5 1 0.32
4 0 0.38
0 2 0.26
3 7 0.39
1 3 0.29
7 2 0.34
6 2 0.40
3 6 0.52
6 0 0.58
6 4 0.93

点击文字获取:001自定义输入流In类实现

2.无环加权有向图的最短路径

判断有向图是否有环代码:

package algorithms.graph; 
import java.io.IOException; 
import java.util.Deque;
import java.util.LinkedList; 
/*
 * 寻找有向环;判定是否有环
 * */
public class EdgeWeightDirectedCycle {
    private boolean marked[];
    private int edgeTo[];
    private Deque<Integer> cycle;
    private boolean onStack[];
    public EdgeWeightDirectedCycle(EdgeWeightedDigraph D){
    	marked = new boolean[D.V()];
    	edgeTo = new int[D.V()];
    	onStack = new boolean[D.V()];
    	for(int s = 0; s < D.V(); s++)
    		if(!marked[s])
    		   dfs(D, s);
    }
    public void dfs(EdgeWeightedDigraph D, int v){
    	onStack[v] = true;
    	marked[v] = true; 
    	for(DirectedEdge e : D.adj(v)) {
    		int w = e.to();
    		if(this.hasCycle()) return;
    		else if(!marked[w]){
    			edgeTo[w] = v;
    			dfs(D, w);
    		} 
    		else if(onStack[w]){
    			cycle = new LinkedList<Integer>();
    			for(int x = v; x != w; x = edgeTo[x]) 
    				cycle.push(x); 
    			cycle.push(w);
    			cycle.push(v); 
    		}
    	}
    	onStack[v] = false; //递归每层返回前每个顶点onStack[v] = false
    }
    public boolean hasCycle(){
    	return cycle != null;
    }
    public Iterable<Integer> getCycle(){
		return cycle; 
    }
    public boolean getOnStack(int v){
    	return this.onStack[v];
    }
	public static void main(String[] args) throws IOException {
		In in = new In("D:\\tinyEWD.txt"); 
		EdgeWeightedDigraph D = new EdgeWeightedDigraph(in);
		System.out.println(D); 
		EdgeWeightDirectedCycle dCycle = new EdgeWeightDirectedCycle(D);
		System.out.println(dCycle.hasCycle());
		for(int v : dCycle.getCycle())
			System.out.print(v+"-");
		System.out.println();
		for(int v = 0; v < D.V(); v++)
			System.out.println(v + ": "+ dCycle.getOnStack(v));
	}
}

无环加权有向图的最短路径 Java实现代码:

package algorithms.graph;
import java.io.IOException;
import java.math.BigDecimal;
import java.util.Deque;
import java.util.LinkedList;
/*
 * 无环加权有向图的最短路径
 */
public class AcyclicSP {
    private DirectedEdge[] edgeTo;
    private double[] distTo;
    private Deque reversePost;
    private boolean[] marked;
    public AcyclicSP(EdgeWeightedDigraph G, int s){
    	edgeTo = new DirectedEdge[G.V()];
    	distTo = new double[G.V()];
    	reversePost = new LinkedList();
    	marked = new boolean[G.V()];
    	for(int v = 0; v < G.V(); v++) 
    		distTo[v] = Double.POSITIVE_INFINITY; 
    	distTo[s] = 0.00;
    	EdgeWeightDirectedCycle dcycle = new EdgeWeightDirectedCycle(G);
    	System.out.println(dcycle.hasCycle());
    	if(!dcycle.hasCycle()){
    		for(int v = 0; v < G.V(); v++) 
	    		if(!marked[v])
	    			dfs(G, v); 
    		for(int v : reversePost)
        	    relax(G, v);
    	} 
    }
    private void dfs(EdgeWeightedDigraph G, int v){
    	marked[v] = true;
    	for(DirectedEdge e : G.adj(v)){
    		int w = e.to();
    		if(!marked[w])
    			dfs(G, w);
    	}
    	reversePost.push(v);
    }
    private void relax(EdgeWeightedDigraph G, int v){
    	for(DirectedEdge e : G.adj(v)){
    		int w = e.to();
    		if(distTo[v] + e.weight() < distTo[w]){
    			 distTo[w] = distTo[v] + e.weight();
    			 edgeTo[w] = e;
    		}
    	}
    }
    public double distTo(int v){
    	BigDecimal bd = new BigDecimal(distTo[v]);
    	double d = bd.setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
    	return d;
    }
    public Iterable pathTo(int v){
    	Deque dq = new LinkedList();
    	for(DirectedEdge e = edgeTo[v]; e != null; e = edgeTo[e.from()])
    		dq.push(e);
    	return dq;
    }
    public boolean hasPathTo(int v){
    	return distTo[v] != Double.POSITIVE_INFINITY;
    }
	public static void main(String[] args) throws IOException {
		In in = new In("D:\\tinyEWDAG.txt"); 
		 System.out.println("图文件:");
		 for(String v : in.getStr())
				System.out.print(v + " "); 
		 System.out.println();
		 System.out.println("图邻接表:");
		 EdgeWeightedDigraph EWD = new EdgeWeightedDigraph(in);
		 System.out.println(EWD); 
		 AcyclicSP sp = new AcyclicSP(EWD, 5);
		 System.out.println("起点到每个顶点的最短路径:"); 
		 for(int v = 0; v < EWD.V(); v++){
			 System.out.print("5到达" + v + "的最短路径: "); 
			 for(DirectedEdge e : sp.pathTo(v))
				 System.out.print(e + " ");
			 System.out.println(" 总路径 " + sp.distTo(v));
		 } 

	}

}


输出:

图文件:
8 13 5 4 0.35 4 7 0.37 5 7 0.28 5 1 0.32 4 0 0.38 0 2 0.26 3 7 0.39 1 3 0.29 7 2 0.34 6 2 0.40 3 6 0.52 6 0 0.58 6 4 0.93 
图邻接表:
0 : 0-2 0.26  
1 : 1-3 0.29  
2 : 
3 : 3-6 0.52  3-7 0.39  
4 : 4-0 0.38  4-7 0.37  
5 : 5-1 0.32  5-7 0.28  5-4 0.35  
6 : 6-4 0.93  6-0 0.58  6-2 0.40  
7 : 7-2 0.34  

false
起点到每个顶点的最短路径:
5到达0的最短路径: 5-4 0.35 4-0 0.38  总路径 0.73
5到达1的最短路径: 5-1 0.32  总路径 0.32
5到达2的最短路径: 5-7 0.28 7-2 0.34  总路径 0.62
5到达3的最短路径: 5-1 0.32 1-3 0.29  总路径 0.61
5到达4的最短路径: 5-4 0.35  总路径 0.35
5到达5的最短路径:  总路径 0.0
5到达6的最短路径: 5-1 0.32 1-3 0.29 3-6 0.52  总路径 1.13
5到达7的最短路径: 5-7 0.28  总路径 0.28

你可能感兴趣的:(笔记)