邻接矩阵图实现

Adjacency Matrix Graph Implementation

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

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

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,其中仅包含图中突出显示节点的所有对最短路径?

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

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

我还更改了矩阵的维度以反映有 100 个节点而不是 99 个的事实。

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

initializetestInit 都是从 main 调用的。

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

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;
        }

我已经修改了您的 Floyd-Warshall 实现以正确初始化邻接矩阵的对角线元素 adjMat,其值应为 0。我还将 floydWarshall 方法更改为不重新分配 adjMat,它已经在 main 方法中分配了。我还在您的 arrayCondenser 方法中删除了对 floydWarshall 的重复调用。我还修改了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();
    }
}