深度优先算法(DFS)遍历有向无环图计算最优路径

来源:互联网 发布:k歌之王65首歌名知乎 编辑:程序博客网 时间:2024/06/14 13:48

遍历有向无环图,寻找最优路径:

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;

 

/**

 * 节点

 * @authorwillWang

 * @Date 2017-11-23

 */

public class GraphNode {

 

    public List<GraphEdge>edgeList = null;

   

    private Stringlabel = "";

   

    public GraphNode(Stringlabel) {

       this.label =label;

       if (edgeList ==null) {

           edgeList = new ArrayList<GraphEdge>();

       }

    }

   

    /**

     * 给节点添加边

     * @authorwillWang

     * @date 2017-11-23

     * @param edge

     */

    public void addEdgeList(GraphEdge edge) {

       edgeList.add(edge);

    }

   

    /**

     * 获取节点标签

     * @authorwillWang

     * @date 2017-11-23

     * @return

     */

    public String getLabel() {

       returnlabel;

    }

}

         4、创建有向无环图的边

package answer.graph.model;

 

/**

 * 创建有向无环图边

 * @author willWang

 *

 */

public class GraphEdge {

 

    //左侧节点

    private GraphNodenodeLeft;

    //右侧节点

    private GraphNodenodeRight;

    //权重

    private int weight;

 

    /**

     * 初始化边

     * @authorwwy

     * @date 2017-11-23

     * @param nodeLeft

     * @param nodeRight

     * @param weight

     */

    public GraphEdge(GraphNodenodeLeft, GraphNode nodeRight, int weight) {

       this.nodeLeft =nodeLeft;

       this.nodeRight =nodeRight;

       this.weight =weight;

    }

 

    public GraphNode getNodeLeft() {

       returnnodeLeft;

    }

 

    public GraphNode getNodeRight() {

       returnnodeRight;

    }

   

    public int getWeight() {

       returnweight;

    }

}

    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(intn) {

       if (nodes ==null) {

           nodes = new ArrayList<GraphNode>();

       }

      

       GraphNode node = null;

       for (inti = 0; i < n; i++) {

           node = new GraphNode(String.valueOf(i));

           nodes.add(node);

       }

    }

   

    public void initGraph(intn, booleanb) {

       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() {

       returnnodes;

    }

}

         6、重点来了,根据深度优先算法遍历有向无环图,并计算出最优路径

package answer.graph.traversing;

 

import java.util.List;

 

import answer.graph.model.GraphEdge;

import answer.graph.model.GraphNode;

 

/**

 * 采用深度优先算法获取最佳路径

 * @authorwwy

 * @Date 2017-11-23

 */

public class DFSGetBestPath {

   

    private int tempWeight = 0;

    int maxWeight = 0;

    String result = "";

    private StringBufferwsb = new StringBuffer();

    private StringBufferlsb = new StringBuffer();

   

    public String getResult() {

       returnresult;

    }

 

    /**

     * 采用深度优先算法递归遍历有向无环图

     * @param node

     * @param visited

     * @return

     */

    public GraphNode searchTraversing(GraphNodenode,List<GraphNode> visited) {

       // 如果已经查看过该节点,返回该节点

       if (visited.contains(node)) {

           returnnode;

       }

      

       visited.add(node);

       //添加节点示例

       if(lsb.length() > 0){

           lsb.append("->");

       }

       lsb.append(node.getLabel());

//     System.out.println("节点:" + node.getLabel());

       if(node.edgeList.size() > 0){

           for (inti = 0; i < node.edgeList.size(); i++) {

              GraphEdge gEdge =node.edgeList.get(i);

              intweight = 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+"";

           }

       }

       returnnode;

    }

}

    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

原创粉丝点击