算法――数据结构图的最短路径实现JAVA代码

2014-11-23 23:31:11 · 作者: · 浏览: 0
图求最短路径的Floyd和Dijkstra算法JAVA代码实现

 
package graph;

/**
 * Created by Thinkpad on 2014/3/31.
 */
public class VertexType
{
    private String name;
    private int id;

    public VertexType(int i, String a)
    {
        id = i;
        name = a;
    }

    public String getName()
    {
        return name;
    }

    public void setName(String name)
    {
        this.name = name;
    }

    public int getId()
    {
        return id;
    }

    public void setId(int id)
    {
        this.id = id;
    }
}
package graph;

/**
 * Created by Thinkpad on 2014/3/31.
 */
public class EdgeType
{
    protected int weight;

    public EdgeType(int weight)
    {
        this.weight = weight;
    }
}

package graph;

import java.util.ArrayList;
import java.util.HashMap;

public class GraphMatrixOperator
{
    private static final int INFINITY = 65535;
    private ArrayList
  
   > arcList = new ArrayList
   
    >(); private ArrayList
    
      vertexes = new ArrayList
     
      (); private HashMap
      
        vertexNodeHashMap = new HashMap
       
        (); // protected int[] p; /* 用于存储最短路径下标的数组 */ // protected int[] d ;/* 用于存储到各点最短路径的权值和 */ private int numVertexes; private int numEdges; public ArrayList
        
         > getArcList() { return arcList; } public ArrayList
         
           getVertexes() { return vertexes; } public HashMap
          
            getVertexNodeHashMap() { return vertexNodeHashMap; } /* 建立无向网图的邻接矩阵表示 */ public static void initMGraph(GraphMatrixOperator g) { } protected static void initVertexes(GraphMatrixOperator g) { for (int i = 0; i < g.numVertexes; i++) /* 读入顶点信息,建立顶点表 */ { g.getVertexes().set(i, new VertexType(i, "")); } } protected static void initArcWithIJ(GraphMatrixOperator g) { for (int i = 0; i < g.getNumVertexes(); i++) { for (int j = i; j < g.getNumVertexes(); j++) { g.getArcList().get(j).get(i).weight = g.getArcList().get(i).get(j).weight; } } } protected static void initNet(GraphMatrixOperator g) { for (int i = 0; i < g.numVertexes; i++)/* 初始化图 */ { for (int j = 0; j < g.numVertexes; j++) { if (i == j) { g.getArcList().get(i).set(j, new EdgeType(0)); } else { g.getArcList().get(i).set(j, new EdgeType(INFINITY)); g.getArcList().get(j).set(i, new EdgeType(INFINITY)); } } } } private static void initArcList(GraphMatrixOperator g, int size) { for (int i = 0; i < size; i++) { ArrayList
           
             al = new ArrayList
            
             (); g.getArcList().add(al); for (int j = 0; j < size; j++) { if (i == j) { al.add(new EdgeType(0)); } else { al.add(new EdgeType(INFINITY)); } } } } public static void addArcFromI2J(GraphMatrixOperator g, String a, String b, int w) { addVex(g, a); addVex(g, b); g.getArcList().get(g.getVertexNodeHashMap().get(a).getId()).get(g.getVertexNodeHashMap().get(b).getId()).weight = w; g.getArcList().get(g.getVertexNodeHashMap().get(b).getId()).get(g.getVertexNodeHashMap().get(a).getId()).weight = w; } private static void addVex(GraphMatrixOperator g, String a) { if (!g.getVertexNodeHashMap().containsKey(a)) { int size = g.getVertexes().size(); VertexType e = new VertexType(size, a); g.getVertexes().add(e); g.getVertexNodeHashMap().put(a, e); } } /* Dijkstra算法,求有向网G的v0顶点到其余顶点v的最短路径p[v]及带权长度d[v] */ /* p[v]的值为前驱顶点下标,d[v]表示v0到v的最短路径长度和 */ public static void shortestPath_Dijkstra(GraphMatrixOperator g, int v0, int[] p, int[] d) { int v, w, k = 0, min; int maxvex = g.getNumVertexes(); int[] finalInt = new int[maxvex];/* finalInt[w]=1表示求得顶点v0至vw的最短路径 */ int n = g.numVertexes; for (v = 0; v < n; v++) /* 初始化数据 */ { finalInt[v] = 0; /* 全部顶点初始化为未知最短路径状态 */ d[v] = g.getArcList().get(v0).get(v).weight;/* 将与v0点有连线的顶点加上权值 */ p[v] = -1; /* 初始化路径数组P为-1 */ } d[v0] = 0; /* v0至v0路径为0 */ finalInt[v0] = 1; /* v0至v0不需要求路径 */ /* 开始主循环,每次求得v0到某个v顶点的最短路径 */ for (v = 1; v < n; v++) { min = INFINITY; /* 当前所知离v0顶点的最近距离 */ for (w = 0; w < n; w++) /* 寻找离v0最近的顶点 */ { if ((finalInt[w] == 0) && (d[w] < min)) { k = w; min = d[w]; /* w顶点离v0顶点更近 */ } } finalInt[k] = 1; /* 将目前找到的最近的顶点置为1 */ for (w = 0; w < n; w++) /* 修正当前最短路径及距离 */ { /* 如果经过v顶点的路径比现在这条路径的长度短的话 */ if ((0 == finalInt[w]) && ((min + g.getArcList().get(k).get(w).weight) < d[w])) { /* 说明找到了更短的路径,修改d[w]和p[w] */ d[w] = min + g.getArcList().get(k).get(w).weight; /* 修改当前路径长度 */ p[w] = k; } } } System.out.println("final[]:"); for (int i : finalInt) { System.out.print(i); } System.out.println(); } public static void main(String[] args) { /* 求某点到其余各点的最短路径 */ String[] src = new String[]{"a,b,1", "b,c,2", "a,c,4", "b,d,7"}; GraphMatrixOperator g = createMGraph(src); logMGraph(g); int v0 = 0; main_Dijkstra(g, v0); main_floyd(g); } private static GraphMatrixOperator createMGraph(String[] src) { GraphMatrixOperator g = new GraphMatrixOperator(); initArcList(g, src.length); for (String s : src) { System.out.println(s); String[] line = s.split(","); addArcFromI2J(g, line[0], line[1], Integer.valueOf(line[2])); } int size = g.getVertexes().size(); g.setNumVertexes(size); g.setNumEdges(src.length); return g; } private static void logMGraph(GraphMatrixOperator g) { for (VertexType vertexType : g.getVertexes()) { System.out.print(vertexType.getName() + " "); } System.out.println(); for (ArrayList
             
               edgeTypes : g.getArcList()) { for (EdgeType edgeType : edgeTypes) { System.out.print(edgeType.weight + " "); } System.out.println(); } } private static void main_Dijkstra(GraphMatrixOperator g, int v0) { int size = g.getVertexes().size(); int[] p = new int[size]; int[] d = new int[size]; shortestPath_Dijkstra(g, v0, p, d); System.out.println("用于存储到各点最短路径的权值和:"); for (int i : d) { System.out.print(i + " "); } System.out.println(); System.out.println("用于存储最短路径下标的数组 :"); for (int i : p) { System.out.print(i + " "); } System.out.println(); System.out.println("最短路径倒序如下:"); int j; for (int i = 1; i < g.numVertexes; ++i) { System.out.print(v0 + "-" + i + ":"); j = i; while (p[j] != -1) { System.out.print(g.getVertexes().get(p[j]).getName()); j = p[j]; } System.out.println(); } System.out.println("\n源点到各顶点的最短路径长度为:"); for (int i = 1; i < g.numVertexes; ++i) { System.out.print(g.getVertexes().get(v0).getName() + "-"); System.out.print(g.getVertexes().get(i).getName() + ":"); System.out.println(d[i]); } } public void setNumVertexes(int numVertexes) { this.numVertexes = numVertexes; } public int getNumVertexes() { return numVertexes; } public void setNumEdges(int numEdges) { this.numEdges = numEdges; } public int getNumEdges() { return numEdges; } /* Floyd算法,求网图G中各顶点v到其余顶点w的最短路径p[v][w]及带权长度d[v][w]。 */ public static void shortestPath_Floyd(GraphMatrixOperator g, int[][] pList, int[][] dList) { int size = g.numVertexes; for (int v = 0; v < size; ++v) /* 初始化D与P */ { for (int w = 0; w < size; ++w) { dList[v][w] = g.arcList.get(v).get(w).weight; /* d[v][w]值即为对应点间的权值 */ pList[v][w] = w; /* 初始化P */ } } for (int k = 0; k < size; ++k) { for (int v = 0; v < size; ++v) { for (int w = 0; w < size; ++w) { if (dList[v][w] > dList[v][k] + dList[k][w]) {/* 如果经过下标为k顶点路径比原两点间路径更短 */ dList[v][w] = dList[v][k] + dList[k][w];/* 将当前两点间权值设为更小的一个 */ pList[v][w] = pList[v][k];/* 路径设置为经过下标为k的顶点 */ } } } } } public static void main_floyd(GraphMatrixOperator g) { int size = g.getVertexes().size(); int[][] pList = new int[size][size]; int[][] dList = new int[size][size]; shortestPath_Floyd(g, pList, dList); printPath(size, pList, dList); printDList(size, dList); printPList(size, pList); } private static void printPList(int size, int[][] pList) { System.out.println("最短路径的下标P:"); for (int v = 0; v < size; ++v) { for (int w = 0; w < size; ++w) { System.out.print(pList[v][w] + "-"); } System.out.println(); } } public static void printDList(int size, int[][] dList) { System.out.println("最短路径的权值和D:"); for (int v = 0; v < size; ++v) { for (int w = 0; w < size; ++w) { System.out.print(dList[v][w] + "-"); } System.out.println(); } } public static void printPath(int size, int[][] pList, int[][] dList) { System.out.println("各顶点间最短路径如下:"); for (int v = 0; v < size; ++v) { for (int w = v + 1; w < size; w++) { System.out.println(v + "-" + w + ":" + dList[v][w]); printPathFromV2W(pList, v, w); } } } public static void printPathFromV2W(int[][] pList, int v, int w) { int k; k = pList[v][w]; /* 获得第一个路径顶点下标 */ System.out.print(v + "-"); /* 打印源点 */ while (k != w) /* 如果路径顶点下标不是终点 */ { System.out.print(k + "-"); /* 打印路径顶点 */ k = pList[k][w]; /* 获得下一个路径顶点下标 */ } System.out.println(w); /* 打印终点 */ } }