邻接矩阵图实现

时间:2017-03-03 22:39:28

标签: java algorithm matrix graph adjacency-matrix

我正在尝试使用邻接矩阵实现以下图表: graph

正在编写的程序将找到从每个商店到每个其他商店的最短距离。这是使用的代码:

public class AdjacencyMatrix
{       
    public static final int NUM_NODES = 100;
    public static final int INF = 99999;
    public static final int A = 20;
    public static final int B = 18;
    public static final int C = 47;
    public static final int D = 44;
    public static final int E = 53;
    public static final int F = 67;
    public static final int G = 95;
    public static final int H = 93;
    public static final int I = 88;
    public static final int W = 66;
    
    public static boolean even(int num) 
    {
        return num%2==0;
    }

    public static boolean odd(int num) 
    {
        return num%2==1;
    }

    public static void initialize(int [][] adjMat, int N) 
    {
        for(int i = 0; i < N; i++)
            for(int j = 0; j <N; j++)
                adjMat[i][j]=INF;

        for(int x = 0; x<N; x++)
        {
            int row = x/10;
            int column = x%10;

            if (even(row)) {
                if (column!=9)
                    adjMat[x][x+1]=1;
            }
            if (odd(row)) {
                if (column!=0)
                    adjMat[x][x-1]=1;
            }
            if (even(column)){
                if (row!=9)
                    adjMat[x][x+10]=1;
            }
            if (odd(column)) {
                if (row!=0)
                    adjMat[x][x-10]=1;
            }
        }
    }
    
    public static int[][] floydWarshall(int[][] adjMat, int N)
    {
    	adjMat = new int[N][N];
	    initialize(adjMat, N);

        for(int k = 0; k < N; ++k) 
        {
           for(int i = 0; i < N; ++i) 
           {
              for(int j = 0; j < N; ++j) 
              {
                 adjMat[i][j] = Math.min(adjMat[i][j], adjMat[i][k] +   adjMat[k][j]);
              }
           }
        }
        
        return adjMat;
    }
    
    public static int[][] arrayCondenser(int[][] adjMat, int N)
    {
    	int[] array = {A,B,C,D,E,F,G,H,I,W};
    	adjMat = floydWarshall(adjMat, N);
    	
    	
    	
    	
    	return adjMat;
    }

    public static void printGrid(int[][] adjMat)
    {
		for (int i=0; i<NUM_NODES; ++i)
		{
		   for (int j=0; j<NUM_NODES; ++j)
		   {
		       if (adjMat[i][j]==INF)
		           System.out.printf("%5s", "INF");
		       else
		           System.out.printf("%5d",adjMat[i][j]);
		   }
		   System.out.println();
		}
    }
    
    public static void main(String[] args)
    {

        int adjMat[][] = new int[NUM_NODES][NUM_NODES];
        adjMat = floydWarshall(adjMat, NUM_NODES);
 
        printGrid(adjMat);
        
        int A,B,C,D,E,F,G,H,I,W;
        
        

        System.out.println();
    }
}

如何将100 x 100阵列缩小为10 x 10,其中仅包含图表中突出显示的节点的所有对最短路径?

2 个答案:

答案 0 :(得分:1)

我修改了你的Floyd-Warshall实现,为邻接矩阵的对角线元素正确初始化adjMat,它应该有一个值0.我还将floydWarshall方法更改为not重新分配已在adjMat方法中分配的main。我还在您的floydWarshall方法中删除了对arrayCondenser的重复调用。我还修改了arrayCondenser方法来计算压缩数组,并添加了printCondensedGrid方法来显示压缩数组:

public class AdjacencyMatrix {
    public static final int NUM_NODES = 100;
    public static final int INF = 99999;
    public static final int A = 20;
    public static final int B = 18;
    public static final int C = 47;
    public static final int D = 44;
    public static final int E = 53;
    public static final int F = 67;
    public static final int G = 95;
    public static final int H = 93;
    public static final int I = 88;
    public static final int W = 66;

    public static boolean even(int num) {
        return num % 2 == 0;
    }

    public static boolean odd(int num) {
        return num % 2 == 1;
    }

    public static void initialize(int[][] adjMat) {
        for (int i = 0; i < adjMat.length; i++)
            for (int j = 0; j < adjMat.length; j++) {
                if (i == j) {
                    adjMat[i][j] = 0;
                } else {
                    adjMat[i][j] = INF;
                }
            }

        for (int x = 0; x < adjMat.length; x++) {
            int row = x / 10;
            int column = x % 10;

            if (even(row)) {
                if (column != 9)
                    adjMat[x][x + 1] = 1;
            }
            if (odd(row)) {
                if (column != 0)
                    adjMat[x][x - 1] = 1;
            }
            if (even(column)) {
                if (row != 9)
                    adjMat[x][x + 10] = 1;
            }
            if (odd(column)) {
                if (row != 0)
                    adjMat[x][x - 10] = 1;
            }
        }
    }

    public static void floydWarshall(int[][] adjMat) {
        // commented this out because you are also allocating
        // adjMat in the main method. 
        //adjMat = new int[adjMat.length][adjMat.length];
        initialize(adjMat);

        for (int k = 0; k < adjMat.length; ++k) {
            for (int i = 0; i < adjMat.length; ++i) {
                for (int j = 0; j < adjMat.length; ++j) {
                    adjMat[i][j] = Math.min(adjMat[i][j], adjMat[i][k] + adjMat[k][j]);
                }
            }
        }

        //return adjMat;
    }

    public static int[][] arrayCondenser(int[][] adjMat, int [] array) {
        int[][] condensedArray = new int[array.length][array.length];
        //adjMat = floydWarshall(adjMat, N);

        for (int storeFrom = 0; storeFrom < array.length; storeFrom++) {
            for (int storeTo = 0; storeTo < array.length; storeTo++) {
                condensedArray[storeFrom][storeTo] = adjMat[array[storeFrom]][array[storeTo]];
            }
        }

        return condensedArray;
    }

    public static void printGrid(int[][] adjMat) {
        System.out.println("Adjacency Matrix: ");
        System.out.printf("%5s", " ");
        for (int i = 0; i < adjMat.length; i++) {
            System.out.printf("%5d", i);
        }
        System.out.println();
        System.out.printf("%4s+", " ");
        for (int i = 0; i < adjMat.length; i++) {
            System.out.printf("%5s", "===");
        }
        System.out.println();
        for (int i = 0; i < adjMat.length; ++i) {
            System.out.printf("%4d|", i);

            for (int j = 0; j < adjMat[i].length; ++j) {
                if (adjMat[i][j] == INF)
                    System.out.printf("%5s", "INF");
                else
                    System.out.printf("%5d", adjMat[i][j]);
            }
            System.out.println();
        }
    }
    public static void printCondensedGrid(int[][] adjMat, int stores[]) {
        System.out.println("Condensed grid: ");
        System.out.printf("%5s", " ");
        for (int i = 0; i < stores.length; i++) {
            System.out.printf("%5d", stores[i]);
        }
        System.out.println();
        System.out.printf("%4s+", " ");
        for (int i = 0; i < adjMat.length; i++) {
            System.out.printf("%5s", "===");
        }
        System.out.println();
        for (int i = 0; i < adjMat.length; ++i) {
            System.out.printf("%4d|", stores[i]);

            for (int j = 0; j < adjMat[i].length; ++j) {
                if (adjMat[i][j] == INF)
                    System.out.printf("%5s", "INF");
                else
                    System.out.printf("%5d", adjMat[i][j]);
            }
            System.out.println();
        }
    }

    public static void main(String[] args) {

        int adjMat[][] = new int[NUM_NODES][NUM_NODES];
        int[] stores = { A, B, C, D, E, F, G, H, I, W };

        floydWarshall(adjMat);

        printGrid(adjMat);
        int condensedArray[][] = arrayCondenser(adjMat, stores);
        printCondensedGrid(condensedArray, stores);

        System.out.println();
    }
}

答案 1 :(得分:0)

我相信下面的初始化(转移到initialize方法)会更准确地反映您的图片。

在偶数行中,每个节点到其右侧的节点都有边。在奇数行中,从每个节点到其左侧的节点都有边缘。在每个偶数列中,从每个节点到下面的节点都有边。在每个奇数列中,从每个节点到上面的节点都有边。

我还改变了矩阵的尺寸,以反映出有100个节点,而不是99个节点。

为了测试初始化​​,我添加了一个测试方法testInit。此方法遍历图中的每个节点,并检查左侧,右侧,上方和下方的节点,以查看这些节点是否存在边缘。您可以检查测试方法的输出并与上图进行比较。

initialize调用testInitmain

编辑:我已经实施Gene建议使用100 X 4矩阵,其中4个数字代表N,S,E,W方向,因为那些是链接可以存在的唯一方向。 Gene建议使用4位,但是我使用了4个阵列位置,这些位置使用了更多的空间,但我已将实际的相邻节点放在这些位置(如果非零)。

public class AdjacencyMatrix
{       
    public static final int NUM_NODES = 100;
    public static final int NUM_DIRECTIONS = 4;
    public static final int NORTH = 0;
    public static final int EAST = 1;
    public static final int SOUTH = 2;
    public static final int WEST = 3;
    public static boolean even(int num) {
        return num%2==0;
    }

    public static boolean odd(int num) {
        return num%2==1;
    }

    public static void initialize(int [][] adjMat, int N, int DIR) {
        for(int i = 0; i < N; i++)
            for(int dir = 0; dir <DIR; dir++)
                adjMat[i][dir]=0;

        for(int x = 0; x<N; x++)
        {
            int row = x/10;
            int column = x%10;

            if (even(row)) {
                if (column!=9)
                    adjMat[x][EAST]=x+1;
            }
            if (odd(row)) {
                if (column!=0)
                    adjMat[x][WEST]=x-1;
            }
            if (even(column)){
                if (row!=9)
                    adjMat[x][SOUTH]=x+10;
            }
            if (odd(column)) {
                if (row!=0)
                    adjMat[x][NORTH]=x-10;
            }
        }
    }



    public static void main(String[] args)
    {

        int adjMat[][] = new int[NUM_NODES][NUM_DIRECTIONS];
        initialize(adjMat, NUM_NODES, NUM_DIRECTIONS);
        testInit(adjMat, NUM_NODES, NUM_DIRECTIONS);            

    }

    private static void testInit(int[][] adjMat, int N, int DIR) {
        for(int fromNode=0; fromNode < N; fromNode++) {
            System.out.print(fromNode + "-->");
            for (int num=0; num<DIR; num++) {
                if (adjMat[fromNode][num]>0) {
                    System.out.print( adjMat[fromNode][num] + ", ");
                }
            }
            System.out.println();
        }
    }
}

示例输出:

0-->1, 10, 
1-->2, 
2-->3, 12, 
3-->4, 
4-->5, 14, 
5-->6, 
6-->7, 16, 
7-->8, 
8-->9, 18, 
9-->
10-->20, 
11-->1, 10, 
12-->22, 11, 
13-->3, 12, 
14-->24, 13, 
15-->5, 14, 
16-->26, 15, 
17-->7, 16, 
18-->28, 17, 
19-->9, 18, 
20-->21, 30, 
21-->11, 22, 
22-->23, 32, 
23-->13, 24, 
24-->25, 34, 
25-->15, 26, 
26-->27, 36, 
27-->17, 28, 
28-->29, 38, 
29-->19, 
30-->40, 
31-->21, 30, 
32-->42, 31, 
33-->23, 32, 
34-->44, 33, 
35-->25, 34, 
36-->46, 35, 
37-->27, 36, 
38-->48, 37, 
39-->29, 38, 
40-->41, 50, 
41-->31, 42, 
42-->43, 52, 
43-->33, 44, 
44-->45, 54, 
45-->35, 46, 
46-->47, 56, 
47-->37, 48, 
48-->49, 58, 
49-->39, 
50-->60, 
51-->41, 50, 
52-->62, 51, 
53-->43, 52, 
54-->64, 53, 
55-->45, 54, 
56-->66, 55, 
57-->47, 56, 
58-->68, 57, 
59-->49, 58, 
60-->61, 70, 
61-->51, 62, 
62-->63, 72, 
63-->53, 64, 
64-->65, 74, 
65-->55, 66, 
66-->67, 76, 
67-->57, 68, 
68-->69, 78, 
69-->59, 
70-->80, 
71-->61, 70, 
72-->82, 71, 
73-->63, 72, 
74-->84, 73, 
75-->65, 74, 
76-->86, 75, 
77-->67, 76, 
78-->88, 77, 
79-->69, 78, 
80-->81, 90, 
81-->71, 82, 
82-->83, 92, 
83-->73, 84, 
84-->85, 94, 
85-->75, 86, 
86-->87, 96, 
87-->77, 88, 
88-->89, 98, 
89-->79, 
90-->
91-->81, 90, 
92-->91, 
93-->83, 92, 
94-->93, 
95-->85, 94, 
96-->95, 
97-->87, 96, 
98-->97, 
99-->89, 98, 

如果要保留原始索引,可以像initialize方法那样修改if语句:

        if (even(row)) {
            if (column!=9)
                adjMat[x][x+1]=1;
        }
        if (odd(row)) {
            if (column!=0)
                adjMat[x][x-1]=1;
        }
        if (even(column)){
            if (row!=9)
                adjMat[x][x+10]=1;
        }
        if (odd(column)) {
            if (row!=0)
                adjMat[x][x-10]=1;
        }