算法导论——24.2 DAG最短路径算法java实现
2017-05-08 23:43
549 查看
介绍
Bellman-Ford算法能在更普遍的情况下(存在负权边)解决单源点最短路径问题,但是对于DAG,可以有更加简化的算法去计算,使得时间复杂度更低。针对DAG的特点,以拓扑排序为基础,提出了解决DAG的最短路径问题的简单算法。通过理论分析,表明该算法具有理想的运算效率,其中,解决单源点问题的运算时间与E成正比,解决所有点对问题的运算时间与VE成正比。拓扑排序策略对于此类最短路径问题的研究,较传统的方法运算简单、求解直观。
适用条件&范围
1.单源最短路径(从源点s到其它所有顶点v);2.有向无环图(DAG)
3.边权可正可负;
算法描述
(1)初始化,入度为0的节点d为0,其他的节点d值为INF。(2)对DAG进行拓扑排序,得到拓扑序列。
(3)按照拓扑序列遍历DAG的点,进行松弛操作,对于每个点u,遍历其所有的出边<u,v>,如果d[v] > d[v] + length<u,v>,则更新。
时间复杂度
算法时间复杂度O(V+E)。Java代码实现
package algorithms; import util.AlgoGraph; /** * Created with IntelliJ IDEA. * Created by The_Sam on 2017/5/8 22:08 */ public class DAG extends ShortestAlgorithms { public static void main(String[] args) { ShortestAlgorithms dag = new DAG(); System.out.println(dag.analyse(AlgoGraph.defaultMap3())); } boolean analyse(AlgoGraph algoGraph) { dis = new int[algoGraph.getNodenum()];//dis[i] 为 i点到s的最短距离 pre = new int[algoGraph.getNodenum()];//pre[i] 为i搭配s的最短距离的上一个节点 ini(algoGraph, algoGraph.getNodenum()); int vertexs[] = topSort(algoGraph); relex(algoGraph, algoGraph.getNodenum(), algoGraph.getEdgenum(), vertexs); return true; } void ini(AlgoGraph algoGraph, int nodenum) { //初始化,将dis[s]设为0,其他的都设为无限大 int s = algoGraph.getOriginal();//原点 for (int i = 0; i < nodenum; i++) { dis[i] = i == s ? 0 : MAXN; } } void relex(AlgoGraph algoGraph, int nodenum, int edgenum, int vertexs[]) { //松弛操作,遍历每条边nodenum次,找到所有节点的对应dis和pre // 实际上就是暴力检测有没有更短的路径 for (int i = 0; i < nodenum; i++) { for (int j = 0; j < edgenum; j++) { int v = algoGraph.edge.get(j).v; if (v != vertexs[i]) continue;//对拓扑排序从前往后操作,省去后面很多多余的操作 int u = algoGraph.edge.get(j).u; int cost = algoGraph.edge.get(j).cost; if (dis[v] > dis[u] + cost) { dis[v] = dis[u] + cost; pre[v] = u; } } } } /** * @Description : 拓扑排序 * @Author : The_Sam * @Datetime : 2017/5/8 23:22 * @Params : AlgoGraph algoGraph * @Return : int[] */ int[] topSort(AlgoGraph algoGraph) { int nodeNum = algoGraph.getNodenum(); int result[] = new int[nodeNum]; int indegrees[] = algoGraph.getIndegrees(); for (int cnt = 0; cnt < nodeNum; ) { for (int i = 0; i < nodeNum; i++) { if (indegrees[i] == 0) result[cnt++] = i; if (indegrees[i] >= 0) indegrees[i]--; } } return result; } }
AlgoGraph.java 表示图的代码附上
package util; import lombok.Getter; import lombok.Setter; import java.util.ArrayList; /** * Created by The_Sam on 2017/5/8. * 图是从0到nodenum-1表示相应节点 */ public class AlgoGraph { @Getter @Setter private int original; @Getter @Setter private int nodenum; private int indegrees[]; // private int indegrees[];//indegree[i]表示i节点的入度 public ArrayList<AlgoEdge> edge; public int getEdgenum() { return edge.size(); } public AlgoGraph(int original, int nodenum, ArrayList<AlgoEdge> edge) { this.original = original; this.nodenum = nodenum; this.edge = edge; } /** * @Description :返回函数各个节点的入度 * @Author : The_Sam * @Datetime : 2017/5/8 23:04 * @Params : * @Return : int[] */ public int[] getIndegrees() { indegrees=new int[nodenum]; for (AlgoEdge e : edge) { indegrees[e.v]++; } return indegrees; } /** * @Description: 返回一个图,为算法导论图24-4,带负权无负权回路有向环图 * @Author: The_Sam * @Datetime: 2017/5/8 21:22 * @Params: [] * @Return: AlgoGraph */ static public AlgoGraph defaultMap1() { ArrayList<AlgoEdge> edge = new ArrayList<AlgoEdge>(); edge.add(new AlgoEdge(0, 1, 6)); edge.add(new AlgoEdge(0, 2, 7)); edge.add(new AlgoEdge(1, 2, 8)); edge.add(new AlgoEdge(1, 3, 5)); edge.add(new AlgoEdge(1, 4, -4)); edge.add(new AlgoEdge(2, 3, -3)); edge.add(new AlgoEdge(2, 4, 9)); edge.add(new AlgoEdge(3, 1, -2)); edge.add(new AlgoEdge(4, 0, 2)); edge.add(new AlgoEdge(4, 3, 7)); int original = 0; int nodenum = 5; return new AlgoGraph(original, nodenum, edge); } /** * @Description: 返回一个图,为算法导论图24-4改变版,有负权回路有向环图 * @Author: The_Sam * @Datetime: 2017/5/8 21:22 * @Params: [] * @Return: AlgoGraph */ static public AlgoGraph defaultMap2() { ArrayList<AlgoEdge> edge = new ArrayList<AlgoEdge>(); edge.add(new AlgoEdge(0, 1, 6)); edge.add(new AlgoEdge(0, 2, 7)); edge.add(new AlgoEdge(1, 2, 8)); edge.add(new AlgoEdge(1, 3, 5)); edge.add(new AlgoEdge(1, 4, -4)); edge.add(new AlgoEdge(2, 3, -3)); edge.add(new AlgoEdge(2, 4, 9)); edge.add(new AlgoEdge(3, 1, -2)); edge.add(new AlgoEdge(4, 0, 2)); edge.add(new AlgoEdge(4, 3, 5));//此处改变 edge.add(new AlgoEdge(4, 3, 7)); int original = 0; int nodenum = 5; return new AlgoGraph(original, nodenum, edge); } /** * @Description: 返回一个图,为算法导论图24-4改变版,有向无环图 * @Author: The_Sam * @Datetime: 2017/5/8 21:22 * @Params: [] * @Return: AlgoGraph */ static public AlgoGraph defaultMap3() { ArrayList<AlgoEdge> edge = new ArrayList<AlgoEdge>(); edge.add(new AlgoEdge(0, 1, 6)); edge.add(new AlgoEdge(0, 2, 7)); edge.add(new AlgoEdge(1, 2, 8)); edge.add(new AlgoEdge(1, 3, 5)); edge.add(new AlgoEdge(1, 4, -4)); edge.add(new AlgoEdge(2, 3, -3)); edge.add(new AlgoEdge(2, 4, 9)); //edge.add(new AlgoEdge(3, 1, -2)); //edge.add(new AlgoEdge(4, 0, 2)); //edge.add(new AlgoEdge(4, 3, 5));//此处改变 edge.add(new AlgoEdge(4, 3, 7)); int original = 0; int nodenum = 5; return new AlgoGraph(original, nodenum, edge); } /** * @Description: 返回一个图,为算法导论图24-4改变版,无负权有向环图 * @Author: The_Sam * @Datetime: 2017/5/8 21:22 * @Params: [] * @Return: AlgoGraph */ static public AlgoGraph defaultMap4() { ArrayList<AlgoEdge> edge = new ArrayList<AlgoEdge>(); edge.add(new AlgoEdge(0, 1, 6)); edge.add(new AlgoEdge(0, 2, 7)); edge.add(new AlgoEdge(1, 2, 8)); edge.add(new AlgoEdge(1, 3, 5)); edge.add(new AlgoEdge(1, 4, 4)); edge.add(new AlgoEdge(2, 3, 3)); edge.add(new AlgoEdge(2, 4, 9)); //edge.add(new AlgoEdge(3, 1, -2)); //edge.add(new AlgoEdge(4, 0, 2)); //edge.add(new AlgoEdge(4, 3, 5));//此处改变 edge.add(new AlgoEdge(4, 3, 7)); int original = 0; int nodenum = 5; return new AlgoGraph(original, nodenum, edge); } }
AlgoEdge.java表示边的代码附上
package util; /** * Created by The_Sam on 2017/5/8. */ public class AlgoEdge { public int u,v; public int cost; public AlgoEdge(int u, int v, int cost) { this.u = u; this.v = v; this.cost = cost; } }
相关文章推荐
- 无向图的最短路径算法JAVA实现
- 最短路径算法之Dijkstra算法_Java实现
- 去哪网笔试 最短路径算法(词梯) Java实现
- 算法——数据结构图的最短路径实现JAVA代码
- java实现城市间最短路径算法
- 最短路径算法之Dijkstra算法(java实现)
- 无权最短路径算法java实现
- Dijkstra最短路径算法浅析及java实现
- 迪杰斯特拉(Dijkstra)算法求解单源最短路径及其相应长度(java实现)
- Dijkstra最短路径算法的java实现
- 算法java实现--分支限界法--单源最短路径问题
- 算法java实现--贪心算法--单源最短路径问题--Dijkstra算法
- 基于java最短路径算法公交查询系统的设计与实现
- 【连载】Dijkstra求最短路径算法设计—Java实现
- 最短路径A*算法原理及java代码实现(看不懂是我的失败)
- java实现图的最短路径(SP)的贝尔曼福特(Bellman-Ford)算法
- 无向图的最短路径算法JAVA实现(转)
- java实现图的最短路径(SP)的迪杰斯特拉(Dijkstra)算法
- Java实现求最短路径算法——————Dijkstra(迪杰斯特拉)
- 最短路径算法Dijkstra思路及java实现