深度优先算法(DFS)遍历有向无环图计算最优路径
2017-11-27 22:28
260 查看
遍历有向无环图,寻找最优路径:
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
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
相关文章推荐
- Network Saboteur 简单dfs(), 计算怎样分两个集合 最优问题 用flag[] 数组标记
- Java实现利用广度优先遍历(BFS)计算最短路径的方法
- leetcode 404. Sum of Left Leaves 所有左孩子叶节点之和计算 + 深度优先遍历DFS
- leetcode 687. Longest Univalue Path 二叉树最长相等路径+ 深度优先遍历DFS
- 在图上寻找最优路径(DFS)
- 图的深度优先和广度优先遍历及两点间最优路径实现
- 图的遍历(搜索)算法(深度优先算法DFS和广度优先算法BFS)
- leetcode 222. Count Complete Tree Nodes 计算满二叉树的节点数量 + DFS深度优先遍历 + 公式计算
- HDU1539Shredding Company(DFS+保存最优路径)
- 最优匹配,增广路径dfs几乎与二分匹配一摸一样 --不过就是多了调整过程而已 【转自旧博】
- 图的遍历(搜索)算法(深度优先算法DFS和广度优先算法BFS)
- Dijkstra 最短路算法(只能计算出一条最短路径,所有路径用dfs)
- 飞越原野 DFS寻找最优路径
- leetcode 282. Expression Add Operators 任意添加运算符计算结果 +深度优先遍历DFS
- 图的遍历(搜索)算法(深度优先算法DFS和广度优先算法BFS)
- 利用广度优先遍历(BFS)计算最短路径 - Java实现
- 待解决)leetcode 路径和 dfs 线序遍历
- 【二叉树】DFS计算路径和,保存路径【113. Path Sum II】【112. Path Sum】
- PAT 1018. Public Bike Management (30)(Dijkstra,dfs根据pre[]输出路径,双向计算)
- 第十二周项目4——利用遍历思想求解图问题(2)-输出简单路径