Dijkstra实现

江枫思渺然 提交于 2020-02-03 12:27:06

参考视频
存放边的距离信息,使用优先队列PriorityQueue;
存放最短距离的点,使用ArrayList;

import java.io.*;
import java.util.*;
import java.lang.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.PriorityQueue;
import java.util.Queue;
import java.util.stream.Collectors;

class Edge{
    public Node from;
    public Node to;
    public int weight;

    public Edge(Node from,Node to,int weight)
    {
        this.from=from;
        this.to=to;
        this.weight=weight;
    }

}

class Node
{
    public String value;
    public Node(String value)
    {
        this.value=value;
    }
    public boolean isVisited=false;
}

class EdgeDist{
    public Edge edge;
    public int dist;
}

class TreeNode
{
    public List<Node> parents;
    public Node node;
    public int dist;
    public TreeNode(Node parent,Node node,int dist)
    {
       if(this.parents==null)
           this.parents=new ArrayList<>();
       this.parents.add(parent);
        this.node=node;
        this.dist=dist;
    }
}

public class Dijkstra{
    public static List<TreeNode> tree;
    public static void main(String[] args) throws Exception {
        tree=new ArrayList<>();

        Node nodeA=new Node("A");
        Node nodeB=new Node("B");
        Node nodeC=new Node("C");
        Node nodeD=new Node("D");
        Node nodeE=new Node("E");
        Node nodeF=new Node("F");

        Edge edgeA_B=new Edge(nodeA,nodeB,1);
        Edge edgeA_D=new Edge(nodeA,nodeD,2);
        Edge edgeB_C=new Edge(nodeB,nodeC,3);
        Edge edgeD_E=new Edge(nodeD,nodeE,3);
        Edge edgeC_E=new Edge(nodeC,nodeE,1);
        Edge edgeC_F=new Edge(nodeC,nodeF,4);
        Edge edgeE_F=new Edge(nodeE,nodeF,1);

        List<Edge> edges=new ArrayList<>(Arrays.asList(edgeA_B,edgeA_D,edgeB_C,edgeD_E,edgeC_E,edgeC_F,edgeE_F));
        List<Node> nodes=new ArrayList<>(Arrays.asList(nodeA,nodeB,nodeC,nodeD,nodeE,nodeF));

        run(nodes,edges);
        println();

    }

    private static void println()
    {
        TreeNode root=tree.remove(0);
        printDist(root,root.node.value,1);
    }

    private static void printDist(TreeNode curr,String path,int tagCount)
    {
        if(tagCount==tree.size()) return;

        //是否
        int finalTagCount = tagCount;
        tree.stream().filter(treeNode ->{
          Optional<Node> parent=  treeNode.parents.stream().filter(p->p.equals(curr.node)).findAny();
          if(!parent.isEmpty())
          {
              parent.get().isVisited=true;
              return true;
          }
          return false;
        }) .forEach(sub->{
                        String pathSub=path+"->"+sub.node.value;
                        int subDist=sub.dist;
                        System.out.println(pathSub+": "+subDist);
                        boolean parentAllVisited=sub.parents==null||sub.parents.stream().allMatch(p->p.isVisited);
                        final int count= parentAllVisited? finalTagCount +1: finalTagCount;
                        printDist(sub,pathSub,count);
        });
    }

    private static void run(List<Node> nodes,List<Edge> edges)
    {
        Node fromNode=nodes.remove(0);
        tree.add(new TreeNode(null,fromNode,0));

        PriorityQueue<EdgeDist> queue=new PriorityQueue(new Comparator<EdgeDist>(){
            @Override
            public int compare(EdgeDist c1, EdgeDist c2) {

                int compare=c1.dist-c2.dist;
                if(compare==0)
                {
                    boolean isInTree1=tree.stream().anyMatch(node->node.node.equals(c1.edge.to));
                    boolean isInTree2=tree.stream().anyMatch(node->node.node.equals(c2.edge.to));

                    if(isInTree1&&isInTree2)
                        throw new RuntimeException("node is in the tree : "+c1.edge.to.value);

                    return (isInTree1?1:0)-(isInTree2?1:0);
                }
                return compare;

            }
        });

        do{
            addElements(fromNode,edges,queue);
            EdgeDist edgeDist=queue.poll();
            fromNode=edgeDist.edge.to;
            nodes.remove(fromNode);
            tree.add(new TreeNode(edgeDist.edge.from,fromNode,edgeDist.dist));
        }while (!nodes.isEmpty());

    }

    private static void addElements(Node fromNode,List<Edge> edges,PriorityQueue<EdgeDist> queue)
    {
        List<Edge> outEdges=edges.stream().filter(e->e.from.equals(fromNode)).collect(Collectors.toList());
        if(outEdges.size()>0)
        {
            outEdges.forEach(e->{
                EdgeDist edgeDist=new EdgeDist();
                edgeDist.edge=e;
                edgeDist.dist=getCurrentDist(e);
                queue.add(edgeDist);
            });
        }
    }

    private static int getCurrentDist(Edge edge)   {
        Node curr=edge.to;
        int dist=edge.weight;

            Optional<TreeNode> optional=tree.stream().filter(treeNode -> treeNode.node.equals(edge.from)).findFirst();
            if(optional.isEmpty())
                throw new RuntimeException("no treenode found in tree !" + edge.from.value);
            dist+=optional.get().dist;
        return dist;
    }

}

 

关于正确性的证明:    网上的归纳法看不下去,把过程又演练了遍。

    发现其实很像“触角”,哪里短往哪儿延伸。

    这样的画面终于说服了自己,好像关节被打通了,舒畅!

 

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!