java - 最小生成树抛出 NullPointerException

标签 java iterator nullpointerexception priority-queue minimum-spanning-tree

我一直盯着这个,它让我发疯。

不知何故,e = pq.poll( ); 使 e 在大型最小生成树的测试用例期间具有 null 值。一个微小的最小生成树就可以工作。

我非常感谢关于这个问题的所有提示,以及如何解决这些问题,因为我觉得我在这里远远超出了我的能力。

感谢您的帮助!

编辑:我的优先级队列似乎是空的。不明白为什么会这样 :/

edit2:我在此处添加了 DisjSet 类以获得额外的见解

public MyMiniGraph<T> generateMinimumSpanningTree()
{
    int edgesAccepted = 0;
      //give all nodes to a class representing disjoint sets
    DisjSet<T> ds = new DisjSet<T>( theGraph.keySet() );

      //set up a new graph to represent the minimum spanning tree
    MyMiniGraph<T> minSpanTree = new MyMiniGraph<T>();
      //initialize minSpanTree with all theGraphs nodes
    Iterator<T> nodeIter = theGraph.keySet().iterator();
    while(nodeIter.hasNext())
        minSpanTree.addNode( nodeIter.next() );

      //order all edges in theGraph in a priority queue
    PriorityQueue<Edge> pq = new PriorityQueue<Edge>(allEdges);
    Edge e;

      // Kruskals algorithm. Accepts the smallest edges in order
      // if they are not part of the same set which would cause a cycle. 
    while(edgesAccepted < currentSize-1)
    {
        e = pq.poll( );

        T uset = ds.find( e.n1 );
        T vset = ds.find( e.n2 );

        if(uset != vset)
        {
            // Accept the edge
            edgesAccepted++;
            ds.union(uset, vset);

             //if the edge is accepted, add it to minSpanTree
            minSpanTree.connectNodes(e.n1, e.n2, e.cost);
        }

    }
    return minSpanTree;
}

类声明和一些成员:

public class MyMiniGraph<T extends Comparable<? super T>> implements MiniGraph<T>
{
      // The Graph containing all the nodes and their edges
    private Map< T, HashSet<Edge> > theGraph = new HashMap< T, HashSet<Edge> >( );
      // Keeps track of theGraphs current size
    private int currentSize = 0;
      // Keeps track of the current Edge quantity
    private int numEdges = 0;
      // TreeSet containing all edges
    private TreeSet<Edge> allEdges = new TreeSet<Edge>();
      // edge representing class with its associated nodes and weight

DisjSet 类:

import java.util.*;

public class DisjSet<K extends Comparable<? super K>>
{
  //HashMap containing 1. K itself, 2. Ks parent. K no.2 is null if K has no parent 
private HashMap<K,K> sets = new HashMap<K,K>();

public DisjSet(Set<K> s)
{
    if(s.isEmpty())
        throw new IllegalStateException("Empty DisjSet argument");

    Iterator<K> nodes_iter = s.iterator();

    while(nodes_iter.hasNext())
        sets.put( nodes_iter.next(), null );
}
  // recursive method to find o_nodes sets root node
public K find(K o_node)
{
    if(sets.get(o_node) == null)
        return o_node;
    else
        return find( sets.get(o_node) );
}
/**
 * connects set 2 to set 1
 * @param root1     root of set 1 
 * @param root2     root of set 2
 */
public void union( K root1, K root2)
{
    sets.put(root2, root1);
}
}

失败跟踪是否有帮助?:

java.lang.NullPointerException
at MyMiniGraph.generateMinimumSpanningTree(MyMiniGraph.java:274)
at MyMiniGraphTest.testGenerateMinimumSpanningTreeLarge(MyMiniGraphTest.java:401)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:44)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:41)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:28)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:76)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:193)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:52)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:191)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:42)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:184)
at org.junit.runners.ParentRunner.run(ParentRunner.java:236)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:49)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)

最佳答案

尝试调用 pq.take() 而不是 pq.poll()。 poll 将在空队列上返回 null,take 将阻塞,直到有可用元素。

关于java - 最小生成树抛出 NullPointerException,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5135987/

相关文章:

java - 使用一个不完全是 JSON 的主体

java - 将 xpath 从 String 转换为 WebElement

Java 泛型不兼容类型(不存在类型变量的实例)

c++ - 存储和重用 vector 迭代器值是否安全?

c++ - 如何从 std::string_view 正确创建 std::string?

java - REST api和json解析

java - 什么是NullPointerException,我该如何解决?

java - 找不到spring-boot-2.3.0.BUILD-SNAPSHOT.jar错误

java - 迭代 map 时为struts迭代器指定范围

Android:加载ListView时出错