狄克斯特拉算法(Dijkstra):从一个点到其余各结点的最短路径。

算法说明:

      从一个点到其余各结点的最短路径。

设置两个结点的集合S和T,集合S中存放已找到最短路径的结点,集合T中存放当前还未找到最短路径的结点。初始状态时,集合S中只包含源点,设为v0,然后从集合T中选择到源点v0路径长度最短的结点u加入到集合S中,集合S中每加入一个新的结点u都要修改源点v0到集合T中剩余结点的当前最短路径长度值,集合T中各结点的新的当前最短路径长度值,为原来的当前最短路径长度值与从源点过结点u到达该结点的路径长度中的较小者。此过程不断重复,直到集合T中的结点全部加入到集合S 中为止。 下图为意示例:

所用的邻接矩阵与前一篇的一样,weight类和visit类也一样

public class Dijkstra {    static final int maxWeight = 9999;        //distance保存了从起始节点到每一个节点的最短距离    //path保存了路径    //v0是起始节点    public static void dijkstra(MyAdjGraphic g,int v0,int[] distance,int[] path)    throws Exception    {        int n = g.getNumOfVertice();//结点数量        int[] s = new int[n]; //标示结点是否已被访问的数组        int minDis; //每次找到的最短路径        int u=0; //下一次最短路径对应的结点的下标                //初始化,把初始节点距离所有节点的信息初始化        for(int i=0;i

测试类:

public class Test {    static final int maxVertices = 100;        public static void main(String[] args) {        MyAdjGraphic g = new MyAdjGraphic(maxVertices);                Object[] vertices = {new Character('A'),new Character('B'),new Character('C'),                new Character('D'),new Character('E'),new Character('F')};                Weight[] weight = {new Weight(0,2,5),new Weight(0,3,30),new Weight(1,0,2),                new Weight(1,4,8),new Weight(2,1,15),new Weight(2,5,7),new Weight(4,3,4),                new Weight(5,3,10),new Weight(5,4,18)};            int n = 6;        int e = 9;                try        {            Weight.createAdjGraphic(g, vertices, n, weight, e);            int[] distance = new int[n];            int[] path = new int[n];            Dijkstra.dijkstra(g, 0, distance, path);                        System.out.println("从顶点A到其他各顶点的最短距离为:");            for(int i = 1; i < n; i ++)            {                System.out.println("到顶点" + g.getValueOfVertice(i) + "的最短距离为:" + distance[i]);            }                System.out.println("从顶点A到其他各顶点的前一顶点分别为:");            for(int i = 0; i < n; i ++)            {                if(path[i] != -1)                {                    System.out.println("到顶点" + g.getValueOfVertice(i) + "的前一顶点为:" + g.getValueOfVertice(path[i]));                }            }        }        catch(Exception ex)        {            ex.printStackTrace();        }    }}

弗洛伊德算法(Floyd):每对结点之间的最短路径

算法思想:

    每对结点之间的最短路径。

    设矩阵cost用来存放带权有向图G的权值,即矩阵元素cost[i][j]中存放着下标为i的结点到下标为j的结点之间的权值,可以通过递推构造一个矩阵序列A0,A1,A2,……,AN来求每对结点之间的最短路径。初始时有,A0[i][j]=cost[i][j]。当已经求出Ak,要递推求解Ak+1时,可分两种情况来考虑:一种情况是该路径不经过下标为k+1的结点,此时该路径长度与从结点vi到结点vj的路径上所经过的结点下标不大于k的最短路径长度相同;另一种情况是该路径经过下标为k+1的结点,此时该路径可分为两段,一段是从结点vi到结点vk+1的最短路径,另一段是从结点vk+1到结点vj的最短路径,此时的最短路径长度等于这两段最短路径长度之和。这两种情况中的路径长度较小者,就是要求的从结点vi到结点vj的路径上所经过的结点下标不大于k+1的最短路径长度。
  

//佛洛依德算法类public class Floyd {    int[][] length = null;// 任意两点之间路径长度    int[][][] path = null;// 任意两点之间的路径    public Floyd(int[][] G) {        //不联通的两节点默认为之间的权值很大,设为MAX        int MAX = 100;        int row = G.length;// 图G的行数        int[][] spot = new int[row][row];// 定义任意两点之间经过的点        int[] onePath = new int[row];// 记录一条路径        length = new int[row][row];        path = new int[row][row][];                //处理任意两点之间的权值,不联通的节点设置为很大的值        for (int i = 0; i < row; i++)        {            // 处理图两点之间的路径            for (int j = 0; j < row; j++) {                if (G[i][j] == 0||G[i][j] == -1)                {                    G[i][j] = MAX;// 没有路径的两个点之间的路径为默认最大                }                if (i == j)                {                    G[i][j] = 0;// 本身的路径长度为0                }            }        }                        for (int i = 0; i < row; i++)        {            // 初始化为任意两点之间没有路径            for (int j = 0; j < row; j++)            {                spot[i][j] = -1;            }        }                for (int i = 0; i < row; i++)        {            // 假设任意两点之间的没有路径            onePath[i] = -1;        }                //初始把处理后的矩阵放在length数组中        for (int v = 0; v < row; ++v)        {            for (int w = 0; w < row; ++w)            {                length[v][w] = G[v][w];            }        }                for (int u = 0; u < row; ++u)        {            for (int v = 0; v < row; ++v)            {                for (int w = 0; w < row; ++w)                {                    if (length[v][w] > length[v][u] + length[u][w]) {                        length[v][w] = length[v][u] + length[u][w];// 如果存在更短路径则取更短路径                        spot[v][w] = u;// 把经过的点加入                    }                }            }        }                for (int i = 0; i < row; i++) {            // 求出所有的路径            int[] point = new int[1];            for (int j = 0; j < row; j++) {                point[0] = 0;                onePath[point[0]++] = i;                outputPath(spot, i, j, onePath, point);                path[i][j] = new int[point[0]];                for (int s = 0; s < point[0]; s++)                    path[i][j][s] = onePath[s];            }        }    }     void outputPath(int[][] spot, int i, int j, int[] onePath, int[] point) {        // 输出i        // 到j        // 的路径的实际代码,point[]记录一条路径的长度        if (i == j)        {            return;        }        if (spot[i][j] == -1)        {            onePath[point[0]++] = j;        }        // System.out.print(" "+j+" ");        else {            outputPath(spot, i, spot[i][j], onePath, point);            outputPath(spot, spot[i][j], j, onePath, point);        }    }    public static void main(String[] args) {        int data[][] = {                { 0, 2, 3, 6},                { 2, 0, 7, -1},                { 3, 7, 0, 1},                { 6, -1, 1, 0},        };        for (int i = 0; i < data.length; i++)        {            for (int j = i; j < data.length; j++)            {                if (data[i][j] != data[j][i])                {                    return;                }            }        }        Floyd test = new Floyd(data);        for (int i = 0; i < data.length; i++)        {            for (int j = i; j < data[i].length; j++) {                System.out.println();                System.out.print("From " + (char)(i+65) + " to " + (char)(j+65) + " path is: ");                for (int k = 0; k < test.path[i][j].length; k++)                {                    System.out.print(test.path[i][j][k] + " ");                }                System.out.println();                System.out.println("From " + (char)(i+65) + " to " + (char)(j+65) + " length :"                        + test.length[i][j]);            }        }    }}