遍历有向无环图,寻找最优路径:
1、假设我们从A点走到B点,可以经过不同的地方,分别用1,2,3,4,5,6表示,A用0表示,B用7表示,从一个地方到另一个地方,中间的路好走的程度用w表示,w越大表示越好走,因此我们可以建立数学模型如下图1所示:
图1
2、根据数学模型,我们判断这是一个有向无环图遍历问题,有向无环图遍历有两种方法,(1)、广度优先(BFS)、(2)、深度优先(DFS)而我们需要的结果是从A到B那个路径的w值最大,即输出结果是路径:0->1->3->7,权值1+3+7=11。最后我们只需要选出权值和最大的路径即可,DFS正好适合这种输出结果,而且时间复杂度为O(V+E)。java代码实现如下:
3、创建有向无环图节点
package answer.graph.model;
import java.util.ArrayList;
import java.util.List;
/**
* 节点
* @author willWang
* @Date 2017-11-23
*/
public class GraphNode {
public List<GraphEdge> edgeList = null;
private String label = "";
public GraphNode(String label) {
this.label = label;
if (edgeList == null) {
edgeList = new ArrayList<GraphEdge>();
}
}
/**
* 给节点添加边
* @author willWang
* @date 2017-11-23
* @param edge
*/
public void addEdgeList(GraphEdge edge) {
edgeList.add(edge);
}
/**
* 获取节点标签
* @author willWang
* @date 2017-11-23
* @return
*/
public String getLabel() {
return label;
}
}
4、创建有向无环图的边
package answer.graph.model;
/**
* 创建有向无环图边
* @author willWang
*
*/
public class GraphEdge {
//左侧节点
private GraphNode nodeLeft;
//右侧节点
private GraphNode nodeRight;
//权重
private int weight;
/**
* 初始化边
* @author wwy
* @date 2017-11-23
* @param nodeLeft
* @param nodeRight
* @param weight
*/
public GraphEdge(GraphNode nodeLeft, GraphNode nodeRight, int weight) {
this.nodeLeft = nodeLeft;
this.nodeRight = nodeRight;
this.weight = weight;
}
public GraphNode getNodeLeft() {
return nodeLeft;
}
public GraphNode getNodeRight() {
return nodeRight;
}
public int getWeight() {
return weight;
}
}
5、根据设计初始化有向无环图
package answer.graph.model;
import java.util.ArrayList;
import java.util.List;
/**
* 按照设计图构造有向无环图
* @author willWang
* @Date 2017-11-23
*/
public class MyGraph {
private List<GraphNode> nodes = null;
public void initGraph(int n) {
if (nodes == null) {
nodes = new ArrayList<GraphNode>();
}
GraphNode node = null;
for (int i = 0; i < n; i++) {
node = new GraphNode(String.valueOf(i));
nodes.add(node);
}
}
public void initGraph(int n, boolean b) {
initGraph(n);
GraphEdge edge01 = new GraphEdge(nodes.get(0), nodes.get(1), 1);
GraphEdge edge02 = new GraphEdge(nodes.get(0), nodes.get(2), 2);
GraphEdge edge13 = new GraphEdge(nodes.get(1), nodes.get(3), 3);
GraphEdge edge14 = new GraphEdge(nodes.get(1), nodes.get(4), 4);
GraphEdge edge25 = new GraphEdge(nodes.get(2), nodes.get(5), 5);
GraphEdge edge26 = new GraphEdge(nodes.get(2), nodes.get(6), 6);
GraphEdge edge37 = new GraphEdge(nodes.get(3), nodes.get(7), 7);
GraphEdge edge47 = new GraphEdge(nodes.get(4), nodes.get(7), 8);
GraphEdge edge57 = new GraphEdge(nodes.get(5), nodes.get(7), 9);
GraphEdge edge67 = new GraphEdge(nodes.get(6), nodes.get(7), 10);
nodes.get(0).addEdgeList(edge01);
nodes.get(0).addEdgeList(edge02);
nodes.get(1).addEdgeList(edge13);
nodes.get(1).addEdgeList(edge14);
nodes.get(2).addEdgeList(edge25);
nodes.get(2).addEdgeList(edge26);
nodes.get(3).addEdgeList(edge37);
nodes.get(4).addEdgeList(edge47);
nodes.get(5).addEdgeList(edge57);
nodes.get(6).addEdgeList(edge67);
}
public void initGraph() {
initGraph(8, false);
}
public List<GraphNode> getGraphNodes() {
return nodes;
}
}
6、重点来了,根据深度优先算法遍历有向无环图,并计算出最优路径
package answer.graph.traversing;
import java.util.List;
import answer.graph.model.GraphEdge;
import answer.graph.model.GraphNode;
/**
* 采用深度优先算法获取最佳路径
* @author wwy
* @Date 2017-11-23
*/
public class DFSGetBestPath {
private int tempWeight = 0;
int maxWeight = 0;
String result = "";
private StringBuffer wsb = new StringBuffer();
private StringBuffer lsb = new StringBuffer();
public String getResult() {
return result;
}
/**
* 采用深度优先算法递归遍历有向无环图
* @param node
* @param visited
* @return
*/
public GraphNode searchTraversing(GraphNode node,List<GraphNode> visited) {
// 如果已经查看过该节点,返回该节点
if (visited.contains(node)) {
return node;
}
visited.add(node);
//添加节点示例
if(lsb.length() > 0){
lsb.append("->");
}
lsb.append(node.getLabel());
// System.out.println("节点:" + node.getLabel());
if(node.edgeList.size() > 0){
for (int i = 0; i < node.edgeList.size(); i++) {
GraphEdge gEdge = node.edgeList.get(i);
int weight = gEdge.getWeight();
//计算当前路径权重
tempWeight += weight;
//添加权重示例
if(wsb.length() > 0){
wsb.append("+");
}
wsb.append(weight);
GraphNode nextNode = searchTraversing(gEdge.getNodeRight(), visited);
if(nextNode.getLabel() != null && nextNode.getLabel() != ""){
//减去退出路径的权重
tempWeight -= weight;
//删除退出路径的权重示例
if(wsb.length() <= 1){
wsb.delete(wsb.length()-1, wsb.length());
}else{
wsb.delete(wsb.length()-2, wsb.length());
}
//删除退出路径的节点示例
if(lsb.length() <= 1){
lsb.delete(lsb.length()-1, lsb.length());
}else{
lsb.delete(lsb.length()-3, lsb.length());
}
}
//删除当前节点,为遍历其他路径上的节点做准备
visited.remove(nextNode);
}
}else{
if(maxWeight < tempWeight){
maxWeight = tempWeight;//更细最大权重
//更新最有路径结果
result = maxWeight+"(最优路径是:"+lsb.toString()+"权重之和是:"+wsb.toString()+"="+maxWeight+")";
}
}
return node;
}
}
7、测试代码
public class Main {
private static MyGraph graph = null;
/**
* 初始化有向无环图
* @author willWang
* @date 2017-11-23
*/
private static void initGraph() {
if (graph == null) {
graph = new MyGraph();
}
graph.initGraph();
}
public static void main(String[] args) {
//初始化有向无环图
initGraph();
List<GraphNode> visited = new ArrayList<GraphNode>();
System.out.println("深度优先算法");
graph.getGraphNodes().get(0)
DFSGetBestPath mdfs = new DFSGetBestPath();
GraphNode result = mdfs.searchTraversing(graph.getGraphNodes().get(0), visited);
System.out.println(mdfs.getResult());
}
}
8、输出结果:
起点:
0
输出:18(最优路径是:0->2->6->7权重之和是:2+6+10=18)
源码下载地址:http://download.csdn.net/download/wwy1219787539/10135173