Java中的Dijkstra算法用完堆空间?

时间:2015-07-17 21:03:24

标签: java graph-algorithm

我正在尝试使用25,000个顶点在Java中进行Dijkstra算法。当我做了1000个顶点时程序工作但是我再次尝试它并且它失败了。

我首先制作了一个二维数组来表示从每个节点到每个节点的路径,这个双数组中存储的是权重。

但内存不足则表示java堆空间内存已在第39行耗尽。

输入就像http://pastebin.com/vwR6Wmrh一样,除了现在有25,000个顶点和57604个边。

具有单个数字的行是顶点

带有两个数字的行是边缘所在的顶点和重量。

因此从节点0到节点25的权重是244。

这是我的代码

import java.io.*; //needed for the file class

import java.util.StringTokenizer;
import java.util.Scanner;

public class ShortestPath {

    public static void main(String[] args)
        throws IOException {
        String filename;
        Scanner keyboard = new Scanner(System.in);
        System.out.println("HELLO USER, ENTER THE NAME OF THE FILE YOU WANT TO INPUT");
        filename = keyboard.nextLine();
        FileReader freader = new FileReader(filename);
        BufferedReader inputFile = new BufferedReader(freader);
        String loco = inputFile.readLine();
        System.out.println(loco);
        StringTokenizer pedro = new StringTokenizer(loco, "= m n");
        int N = Integer.parseInt(pedro.nextToken()); //the number of nodes you have in the array
        int inf = 2100000;
        int[][] a = new int[N][N]; //this will hold all vertices going to all edges
        //int[] d = new int[N]; //distance
        //boolean[] kaki = new boolean[N];
        //int[] p = new int[N]; 
        //the sum of all the shortest paths
        int v = 0; //is for vertices
        int x = 0; //is for the edges
        int y = 0;
        //now we initialize the graph the source node is zero the rest of the paths are inf
        for (int i = 0; i < N; i++) {
            for (int j = 0; j < N; j++) {
                if (i != j) {
                    a[i][j] = inf;
                } else {
                    a[i][j] = 0;
                }
            }
        }
        //read the first line
        //ok now we are reading the file
        //in the file the first line is the vertex
        //the second is where it is going and the weight of this edge
        //a is the array vertices and edges are stored
        while (loco != null) {
            loco = inputFile.readLine();
            if (loco == null) {
                break;
            }
            StringTokenizer str = new StringTokenizer(loco);
            if (str.countTokens() == 1) {
                x = Integer.parseInt(str.nextToken());
                v = x;
                //System.out.println(v);
            }
            if (str.countTokens() == 2) {
                x = Integer.parseInt(str.nextToken());
                y = Integer.parseInt(str.nextToken());
                //System.out.println( x + " " + y);
                a[v][x] = y;
                a[x][v] = y; //since the graph goes in multiple directions
            }
        }
        inputFile.close();
        System.out.println("-------------");
        //here I have constructed the graph yes
        //these be examples to make sure its working 
        //System.out.println(a[0][25]);
        //System.out.println(a[0][613]);
        //System.out.println(a[613][0]);
        //System.out.println(a[899][903]);
        //System.out.println(a[991][997]);
        inputFile.close();
        Dijaskra(0, a, N);
        //vertex zero is the shortest path
    }
}

2 个答案:

答案 0 :(得分:0)

基于邻接矩阵的图表表示需要大量内存(如此处wiki所述)。你能尝试图表的邻接列表表示吗?如果你有很好的RAM容量,矩阵表示也应该有效。您可以尝试增加启动VM参数。

答案 1 :(得分:0)

您正在使用邻接矩阵来存储边缘。即使对于不存在的边,该矩阵也包含一个条目。

如果您有25.000个顶点,则邻接矩阵有25.000^2 = 625.000.000个条目。假设Java非常有效地存储这些,这至少需要2.500.000.000,即Java堆空间的~ 2.32 GibiBytes

您可以尝试使用java -Xmx3g运行JVM以使其具有更大的堆大小。当然,这仅适用于64位Java。

然而,真正的解决方案是使用more space efficient implementation进行边缘表示,因为您的图形显然是稀疏(即density只有0.00018)