在Java中实现图形时出错



我试图使用LinkedList的ArrayList在java中创建一个图形。我已经实现了我自己的清单。然而,当我试图在图的顶点之间添加连接时,我陷入了一个无尽的循环。我正在调试,我意识到这发生在我试图在LinkedList的末尾添加元素的时候。我是一个初学者,我不知道我的列表实现有什么问题。有人能帮忙吗?

import java.util.Stack;
// traverse the graph
public class GraphTraversal {

    public static void main(String[] args)
    {
        Graph graph=new Graph();
        initializeGraph(graph);
        graph.breadthFirstSearch();
    }
    public static void initializeGraph(Graph graph)
    {
        Node_Graph node1=new Node_Graph(1, false);
        Node_Graph node2=new Node_Graph(2, false);
        Node_Graph node3=new Node_Graph(3, false);
        Node_Graph node4=new Node_Graph(4, false);
        Node_Graph node5=new Node_Graph(5, false);
        Node_Graph node6=new Node_Graph(6, false);
        Node_Graph node7=new Node_Graph(7, false);
        Node_Graph node8=new Node_Graph(8, false);
        graph.addNode(node1);
        graph.addNode(node2);
        graph.addNode(node3);
        graph.addNode(node4);
        graph.addNode(node5);
        graph.addNode(node6);
        graph.addNode(node7);
        graph.addNode(node8);
        graph.makeConnection(node1, node2);
        graph.makeConnection(node1, node3);
        graph.makeConnection(node3, node4);
        graph.makeConnection(node3, node5);
        graph.makeConnection(node4, node5);
        graph.makeConnection(node4, node6);
        graph.makeConnection(node4, node8);
        graph.makeConnection(node4, node2);
        graph.makeConnection(node6, node5);
        graph.makeConnection(node8, node7);
        graph.makeConnection(node7, node2);
    }
}
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.Stack;
//Class for graph data structure
public class Graph {
    public ArrayList<List> nodes=new ArrayList<List>();

    public void addNode(Node_Graph n)
    {
        List new_node=new List();
        new_node.add(n);
        nodes.add(new_node);
    }
    public void makeConnection(Node_Graph node1, Node_Graph node2)
    {
        for(List list:nodes)
        {
            if(list.head.getId()==node1.getId())
            {
                list.add(node2);
                break;
            }
        }
    }
    public void breadthFirstSearch()
    {
        Stack<Node_Graph> traverse=new Stack<Node_Graph>();
        Node_Graph start=(nodes.get(0)).head;
        start.setVisited(true);
        traverse.push(start);
        while(traverse.empty())
        {
            Node_Graph popped=traverse.pop();
            System.out.println(popped.getId());
            List nextList= nodes.get(popped.getId());
            Node_Graph newElement=nextList.head;
            while(newElement.getNext()!=null)
            {
                newElement=newElement.getNext();
                if(!newElement.getVisited())
                {
                    newElement.setVisited(true);
                    traverse.push(newElement);
                }
            }
            if(!newElement.getVisited())
                traverse.push(newElement);
        }
    }
}
//linked list implementation
public class List{
    public Node_Graph head;
    public int size; 
    public List()
    {
        head=null;
        size=0;
    }
    public void add(Node_Graph element)
    {
        if(head==null)
        {
            head=element;
        }
        else
        {
            Node_Graph last=head;
            while(last.getNext()!=null)
            {
                last=last.getNext();
            }
            last.setNext(element);
        }
    }
}
//node of a graph
public class Node_Graph {
    private int id;
    private boolean visited;
    private Node_Graph next;
    public Node_Graph(int id,boolean visited)
    {
        this.id=id;
        this.visited=visited;
    }
    public void setId(int id)
    {
        this.id=id;
    }
    public int getId()
    {
        return id;
    }
    public void setVisited(boolean visited)
    {
        this.visited=visited;
    }
    public boolean getVisited()
    {
        return visited; 
    }
    public void setNext(Node_Graph next)
    {
        this.next=next;
    }
    public Node_Graph getNext()
    {
        return next; 
    }
}

graph.makeConnection(node4, node6);行导致无限循环,因为节点4的下一个变量与节点5无限连接

我注意到的第一件事是graph.makeConnection(node3, node5);行导致4连接到5,这是不应该的。

我添加了toString方法到你的列表和node_graph类,试图使它更容易理解发生了什么;这就是它们,你可以试试:

列表:

public String toString(){
  Node_Graph h = head;
  String s = "";
  while(h != null){
    s += "[" + h.toString() + "] ";
    h = h.next;
  }
  return s;
}

Node_Graph:

public String toString(){
  String s = id + "";
  if(next != null)
    s += ", " + next.toString();
  return s;
}

查找错误。让我们从这行开始:

graph.makeConnection(node1, node3);

导致调用:{1 -> 2,2 -> null}.add(3)到目前为止一切顺利。

在add中,您找到列表的最后一个元素:{2},并将其设置在{3}旁边。因此,列表现在看起来像{1 -> 2 -> 3,2 -> 3,3},而它应该是{1 -> 2 -> 3,2,3}。第一个列表(错误地)暗示1连接到2和3,2连接到3,而2不应该连接到3,如第二个列表所示。在您当前的方案中,这是不可能的,因为'2'实际上是具有相同的单一next字段的相同对象。它不能在1元素中为{3},而自己为{null}。

总的来说,你需要区分两个"next"。我相信您的目标是node_graph中的下一个字段表示该节点连接到的节点,而列表中的下一个字段表示列表中的下一个节点,无论是否有连接。你试图用一个单一的下一个字段获得一石二鸟,它会用无限递归来咬你。

有更简洁的方法来实现一个图——hashmap(节点->邻居节点的列表)更简洁,并且节省了你处理所有这些后续业务的时间。如果你的主要目标是优化你的图形算法,比如bfs/dfs- ding,你可能就想这么做。

如果你真的想用列表实现一个图,你需要做一些解开。我建议完全从Node_Graph类中删除next字段;Node_Graph类应该只关心它自己的数据,而不是维护列表不变量。然后使列表类有一个内部包装器类,该包装器类包含一个"this"(Node_Graph实例)和一个"next"(Node_Wrapper)实例。在完成所有这些之后,您可以为Node_Graph提供一个类型为List的neighbors字段,该字段将保存其所有可访问的邻居。

下面是遵循您的模式的基本HashMap图实现。您也不需要列表实现。不需要包装器/next:

public class Node{
    public final Graph graph; //The graph this Node belongs to 
    private int id;
    private boolean visited;
    /** Constructs a Node with the given inputs. 
      * Also adds itself to g as part of construction */
    public Node(Graph g, int i, boolean v){
        graph = g;
        id = i;
        visited = v;
        graph.addNode(this);
    }
    public int getId(){
        return id;
    }
    public void setVisited(boolean v){
        visited = v;
    }
    //Getters for boolean fields usually follow the is<Field> pattern
    public boolean isVisited(){
        return visited;
    }
    /** Looks up the neighbors of this in the graph */
    public Set<Node> getNeighbors(){
        return graph.neighborsOf(this);
    }
}
public class Graph{
    private HashMap<Node, HashSet<Node>> graph;  //The actual graph. Maps a node -> its neighbors
    public Graph(){
        graph = new HashMap<Node, HashSet<Node>>();
    }
    /** Adds the node to this graph.
        If n is already in this graph, doesn't overwrite */
    public void addNode(Node n) throws IllegalArgumentException{
        if(n.graph != this) 
            throw new IllegalArgumentException(n + " belongs to " + n.graph ", not " + this);
        if(! graph.contains(n))
            graph.put(n, new HashSet<Node>());
    }
    /** Returns the neighbors of the given node. 
      * Returns null if the node isn't in this graph */
    public Set<Node> neighborsOf(Node n){
        if(! graph.contains(n))
            return null;
        return graph.get(n);
    }
    /** Connects source to sink. Also adds both to graph if they aren't there yet */
    public void makeConnection(Node source, Node sink){
        //Make sure source and sink belong to this graph first
        addNode(source);
        addNode(sink);
        //Make the connection by adding sink to source's associated hashset
        graph.get(source).add(sink);
    }
}

相关内容

  • 没有找到相关文章

最新更新