【问题标题】:adjacency list creation , out of Memory error邻接表创建,内存不足错误
【发布时间】:2010-04-19 03:49:23
【问题描述】:

我正在尝试创建一个邻接列表来存储图形。该实现在存储 100,000 条记录时运行良好。但是,当我尝试存储大约 100 万条记录时 我遇到了 OutofMemory 错误:

线程“主”java.lang.OutOfMemoryError 中的异常:Java 堆空间 在 java.util.Arrays.copyOfRange(Arrays.java:3209) 在 java.lang.String.(String.java:215) 在 java.io.BufferedReader.readLine(BufferedReader.java:331) 在 java.io.BufferedReader.readLine(BufferedReader.java:362) 在 liarliar.main(liarliar.java:39)

以下是我的实现

HashMap<String,ArrayList<String>> adj = new HashMap<String,ArrayList<String>>(num);


        while ((str = in.readLine()) != null)
        {

            StringTokenizer Tok = new StringTokenizer(str);
            name = (String) Tok.nextElement();
            cnt = Integer.valueOf(Tok.nextToken());
            ArrayList<String> templist = new ArrayList<String>(cnt);

            while(cnt>0)
             {
                    templist.add(in.readLine());
                    cnt--;
             }
            adj.put(name,templist);

        } //done creating a adjacency list

我想知道,是否有更好的方法来实现邻接列表。另外,我一开始就知道节点的数量,并且将来我在访问节点时会展平列表。有什么建议吗?

谢谢

【问题讨论】:

    标签: java data-structures heap-memory adjacency-list


    【解决方案1】:

    我在这里似乎有不公平的优势,因为我知道问题的名称 (liarliar) 和输入的确切性质。

    我可以告诉你,这个OutOfMemoryError 是设计使然。你需要找到一种更好的算法,不会将图的整个邻接信息存储在内存中。

    我不会提供过多的算法洞察力,但我可以告诉你,在这个阶段你需要坐下来思考比你需要编程的更多。也许读一本关于算法和数据结构的好书。


    您现在正在做的是实际上将输入文件中的 字符串 不必要地存储到您的HashMap&lt;String,ArrayList&lt;String&gt;&gt; 中。考虑到问题的性质,这非常节省空间。

    如果您改用java.util.Scanner,它会更容易、更高效。 new Scanner(new File(inputFilename))next()nextInt() 就是你所需要的。

    为每个名称分配一个唯一的int(提示:Map&lt;String, Integer&gt;),并存储更小的int

    【讨论】:

      【解决方案2】:

      感谢您回答我的问题。是的,你猜对了,代码是关于什么的。

      我认为是的,使用字符串到整数的映射可以为邻接列表节省一些空间请求。从这个意义上说,可以消除上述错误。

      但是,我使用了 java -jar -Xmx1024M。这提供了一种使用更多堆内存运行程序的方法,并且由于它允许在给定的问题中使用它,因此这不是我提交失败的原因。

      虽然我不确定,但性能可能是机器人失败的原因之一。

      关于你的解决方案,

      如果我创建一个 Map ,然后将数字存储在邻接列表中,它将为我节省一些空间,但它也会在我每次需要在我的 bfs/dfs 遍历期间访问一个节点时添加一个额外的查找。这让我很困扰。你是说我根本不应该创建邻接列表吗?我是否理解您要正确说的内容。

      谢谢。

      【讨论】:

      • Map&lt;String, Integer&gt; 查找很便宜 (O(1));你不应该被它打扰,除非它被证明是一个问题。过早的优化是万恶之源。在这种情况下更是如此,因为您还没有发现 BIG 优化。你理解我的正确:你根本不需要创建邻接列表。你可以在O(V)空间解决这个问题。您可以在O(V+E) 中处理输入(这是最佳的,因为这是输入的大小),在您完成读取输入后,您可以立即在O(1) 中生成输出。
      • 另一种不使用Map&lt;String,Integer&gt; 来节省空间的方法是.intern() 字符串。很多名字会在输入中重复,并且在内存中多次冗余存储。如果您只存储这些名称中的.intern(),则会对冗余副本进行垃圾收集。作为奖励,如果您始终使用.intern() 名称,则可以使用==!= 而不是equals()。阅读有关字符串实习的工作原理。不过,这是一个小的时间优化。真正重要的是上面评论中的那个。
      • 我知道这与测试二分性/图形着色有关..但我仍然在想在创建 Map(name,int) 之后在 O(1) 中得到答案所有节点!! Map(name,int) 中的 int 可以根据距离变化,所有偶数都在 1 组中,奇数在其他组中。所有这些方法都有问题,它需要一个邻接表 :( 以确保在 BFS 或 DFS 中跟踪图形格式。否则你最终会得到一个新节点,不知道该节点属于哪个组。所以很难知道孩子们会去哪些节点我错过了一些东西,我在正确的轨道上吗?
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-02-20
      • 1970-01-01
      • 1970-01-01
      • 2016-10-23
      • 1970-01-01
      • 2015-09-20
      相关资源
      最近更新 更多