最短路径问题

 单源最短路径

package s23;

import java.util.ArrayList;
import java.util.List;
import java.util.Stack;

public class ShortestRoute {
    private static final  int max = Integer.MAX_VALUE;
    class Node{ //结点类
        Node father;//父节点
        int d; //最短路径
        private Node(){}
    }

    private int[][] graph;//有向图二维数组,有边则=权重,无边=max
    private char[] arr;  //节点字符数组
    private List<Node> list; //节点类集合

    public ShortestRoute(int[][] graph,char[] arr){
        this.graph = graph;
        this.arr = arr;
        list = new ArrayList<>();
        initializeSingleSource();
    }
    /*单源初始化
    源节点为第一个节点,源节点d=0,其他d=max
     */
    private void initializeSingleSource(){
        for(int i=0;i<graph.length;i++){
            Node node = new Node();
            node.father = null;
            if(i==0)//源节点d=0
                node.d=0;
            else
                node.d=Integer.MAX_VALUE;
            list.add(node);
        }
    }

    public boolean dijkstra(){
        //dijkstra算法是从源节点开始进行进出栈操作,找出当前出栈结点为起点的所有边,更新终点并进栈,循环操作
        Stack<Integer> stack = new Stack<>(); //结点序号栈,先进先出,取每个节点的后续j
        stack.push(0);
        /*
        BellmanFord算法此处不使用进出栈方式而是对每条边进行arr.size()-1次循环
        while语句换成如下语句,取消进出栈操作
        for(int k = 1; k < arr.size;k++)
        for(int i = 1; i < graph.length;i++)
         */
        while(!stack.isEmpty()) {
            int i = stack.pop(); //出栈
            if(graph[i][i] != 0) {
                list.clear();
                return false;
            }
            /*
            判断是否存在边w(ij),如果存在则判断w(j) > w(ij) + w(i)
            如果成立则更新w(j),j的父结点更新为i
            j进站
             */
            for (int j = 0; j < graph[i].length; j++) {
              if(graph[i][j] != 0 && graph[i][j] != max){
                  if(list.get(j).d > graph[i][j] + list.get(i).d) {
                      list.get(j).d = graph[i][j] + list.get(i).d;
                      list.get(j).father = list.get(i);
                      stack.push(j);
                  }
              }
            }
        }
        //判断是否存在负数的闭环,如果存在则不可能有最大路径
        for(int i=0;i<graph.length;i++)
            for (int j = 0; j < graph[i].length; j++) {
                if(graph[i][j] != 0 && graph[i][j] != max){
                    if(list.get(j).d > graph[i][j] + list.get(i).d) {
                        list.clear();
                        return false;
                    }
                }
        }
        return true;
    }
    public void printDijkstra(){
        if(list == null || list.size() == 0){
            System.out.println("存在路径为负数的闭环");
            return;
        }
        for(int i = 1; i< arr.length; i++){
            Node node = list.get(i);
            StringBuffer sb = new StringBuffer();
            while(node != null){
                sb.insert(0,"["+arr[list.indexOf(node)]+":"+node.d+"]");
               node = node.father;
               if(node!=null)
                   sb.insert(0,"——");
            }
            System.out.println(sb);
        }
    }

    public static void main(String[] args) {

        int[][] graph = new int[][]{
            {0,6,max,max,7},
            {max,0,5,-4,8},
            {max,-2,0,max,max},
            {2,max,7,0,max},
            {max,max,-3,9,0}
        };
        char[] node = {'a','b','c','d','e'};
        ShortestRoute route = new ShortestRoute(graph,node);
        route.dijkstra();
        route.printDijkstra();
    }
}

输出

[a:0]——[e:7]——[c:4]——[b:2]
[a:0]——[e:7]——[c:4]
[a:0]——[e:7]——[c:4]——[b:2]——[d:-2]
[a:0]——[e:7]


所有结对最短路径



import java.util.ArrayList;
import java.util.List;

public class AllPairShortestRouter {
    private static final int max = Integer.MAX_VALUE;
    private int[][] graph;//有向图二维数组,有边则=权重,无边=max

    private List<int[][]> dMatrixList; //路径权重矩阵
    private List<int[][]> fatherMatrixList; //父节点矩阵
    private char[] node; //节点数组
    private int[][] finalFatherMatrix; //最终父节点矩阵
    private int[][] finalMatrix;  //最终路径权重矩阵

    public AllPairShortestRouter(int[][] graph,char[] node){
        this.graph = graph;
        this.node = node;
        dMatrixList = new ArrayList<>();
        fatherMatrixList = new ArrayList<>();
    }

    public void floydWarshall(){
        if(graph == null && graph.length==0)
            return;
        dMatrixList.add(graph); //初始权重矩阵
        int n = graph.length;

        //初始父节点矩阵,没有边的为-1
        int[][] fatherMatrix = new int[n][n];
        for(int i = 0; i < n; i++)
            for(int j = 0; j < n; j++){
                if(graph[i][j] != 0 && graph[i][j] != max)
                    fatherMatrix[i][j] = i;
                else
                    fatherMatrix[i][j] = -1;
            }
        fatherMatrixList.add(fatherMatrix);

        /*
        每个结对d[ij],循环所有节点作为中间节点的情况
        第k个节点作为中间节点,权重矩阵dk‘,父节点矩阵fk’
        前一个权重矩阵dk,前一个父节点矩阵fk
        dk'[ij] = min(dk[ij], dk[ik] + dk[kj])
        如果dk[ij]小,fk'[ij] = fk[ij]
        如果 dk[ik] + dk[kj] 小,fk'[ij] = fk[kj]
         */
        for(int k = 0; k < n; k++){ //中间节点
            int[][] matrix = new int[n][n];
            int[][] fMatrix = new int[n][n];
            for(int i = 0; i < n; i++)
                for(int j = 0; j < n; j++){
                    if(dMatrixList.get(k)[i][j] == max && (dMatrixList.get(k)[i][k]==max || dMatrixList.get(k)[k][j]==max)) {
                        matrix[i][j] = max;
                        fMatrix[i][j] = fatherMatrixList.get(k)[i][j];
                    }
                    else if(dMatrixList.get(k)[i][j] == max) {
                        matrix[i][j] = dMatrixList.get(k)[i][k] + dMatrixList.get(k)[k][j];
                        fMatrix[i][j] = fatherMatrixList.get(k)[k][j];
                    }
                    else if(dMatrixList.get(k)[i][k]==max || dMatrixList.get(k)[k][j]==max) {
                        matrix[i][j] = dMatrixList.get(k)[i][j];
                        fMatrix[i][j] = fatherMatrixList.get(k)[i][j];
                    }
                    else {
                        matrix[i][j] = Math.min(dMatrixList.get(k)[i][j], dMatrixList.get(k)[i][k] + dMatrixList.get(k)[k][j]);
                        if (matrix[i][j] < dMatrixList.get(k)[i][j])
                            fMatrix[i][j] = fatherMatrixList.get(k)[k][j];
                        else
                            fMatrix[i][j] = fatherMatrixList.get(k)[i][j];
                    }
                }
            dMatrixList.add(matrix);
            fatherMatrixList.add(fMatrix);

        }
        finalFatherMatrix = fatherMatrixList.get(n);
        finalMatrix = dMatrixList.get(n);
    }

    public void print(int i,int j){
        if(finalFatherMatrix == null || finalFatherMatrix.length == 0)
            return;
        if(i==j) 
            System.out.print(node[i]);
        else if(finalFatherMatrix[i][j] == -1)
            System.out.println("没有路径");
        else {
            print(i,finalFatherMatrix[i][j]);
            System.out.print(node[j]);
        }
    }

    public static void main(String[] args) {

        int[][] graph = new int[][]{
                {0,6,max,max,7},
                {max,0,5,-4,8},
                {max,-2,0,max,max},
                {2,max,7,0,max},
                {max,max,-3,9,0}
        };
        char[] node = {'a','b','c','d','e'};
        AllPairShortestRouter route = new AllPairShortestRouter(graph,node);
        route.floydWarshall();
        route.print(0,3);
    }
}

  • 8
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值