您的位置:首页 > 其它

深度优先算法(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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐