繁体   English   中英

在 Java 中首选的 Tree 中查找循环

[英]Find loop in Tree preferred in java

我在数据库项目文件夹层次结构中有一组数据(如快照)

我在数据中有一个循环

像 A->B , B->C C->D , C->A

在此处输入图片说明

代码如下:

public class Vertex {

    private String label;
    private boolean beingVisited;
    private boolean visited;
    private List<Vertex> adjacencyList;

    public Vertex(String label) {
        this.label = label;
        this.adjacencyList = new ArrayList<>();
    }

    public void addNeighbor(Vertex adjacent) {
        this.adjacencyList.add(adjacent);
    }
    //getters and setters
}

public class Graph {

    private List<Vertex> vertices;

    public Graph() {
        this.vertices = new ArrayList<>();
    }

    public void addVertex(Vertex vertex) {
       if(!vertices.contains(vertex)){
        this.vertices.add(vertex);
        }
    }

    public void addEdge(Vertex from, Vertex to) {
        from.addNeighbor(to);
    }

   // ...

   public boolean hasCycle(Vertex sourceVertex) {
    sourceVertex.setBeingVisited(true);

    for (Vertex neighbor : sourceVertex.getAdjacencyList()) {
        if (neighbor.isBeingVisited()) {
            // backward edge exists
            return true;
        } else if (!neighbor.isVisited() && hasCycle(neighbor)) {
            return true;
        }
    }

    sourceVertex.setBeingVisited(false);
    sourceVertex.setVisited(true);
    return false;
}

  public boolean hasCycle() {
    for (Vertex vertex : vertices) {
        if (!vertex.isVisited() && hasCycle(vertex)) {
            return true;
        }
    }
    return false;
}

//主要的

 public static void main(String[] args) {

      Graph graph = new Graph();
        ResultSet rs = provider.conn.createStatement().executeQuery("SELECT itemId, folder FROM SnapshotData);

            while (rs.next()) {



          Vertex vertexFrom = new Vertex(rs.getString("itemId"));
           Vertex vertexTo = new Vertex(rs.getString("folder"));

            graph.addVertex(vertexFrom);
            graph.addVertex(vertexTo);
            graph.addEdge(vertexFrom, vertexTo);

         }
        assertTrue(graph.hasCycle());

    }

我被我错过的东西困住了

据我所知,您的问题是创建节点。

while (rs.next()) {
    Vertex vertexFrom = new Vertex(rs.getString("itemId"));
    Vertex vertexTo = new Vertex(rs.getString("folder"));
    graph.addEdge(vertexFrom, vertexTo);
}

如果我们截取您的屏幕截图,您有 5 个元素(A、B、C、D、F),但您正在创建 10 个(2xA、2xB、4xC、1xF。因此没有循环,因为您的图形如下所示:

A---B

B---C

C---D

C---A

C---F

我建议将您创建的节点保存在 set/HashMap 中,如果它们已经存在,则从那里获取它,而不是创建新的节点。 像这样的东西(没有测试):

Map<String,Vertex> verticesList = new HashMap<String,Vertex>();
while (rs.next()) {
    String from = rs.getString("itemId");
    Vertex vertexFrom = null;
    if(verticesList.contains(from)){
        vertexFrom = verticesList.get(from);
    } else {
        vertexFrom = new Vertex(from);
        verticesList.put(from,vertexFrom);
    }
    ... //same for the other vertex
    graph.addEdge(vertexFrom, vertexTo);
}

@Edit:一个可运行的例子:

图形:

public class Graph {

    private List<Vertex> vertices;

    public Graph() {
        this.vertices = new ArrayList<>();
    }

    public void addVertex(Vertex vertex) {
        if (!vertices.contains(vertex)) {
            this.vertices.add(vertex);
        }
    }

    public void addEdge(Vertex from, Vertex to) {
        from.addNeighbor(to);
    }

    public boolean hasCycle(Vertex sourceVertex) {
        sourceVertex.setBeingVisited(true);

        for (Vertex neighbor : sourceVertex.getAdjacencyList()) {
            if (neighbor.isBeingVisited()) {
                // backward edge exists
                return true;
            } else if (!neighbor.isVisited() && hasCycle(neighbor)) {
                return true;
            }
        }

        sourceVertex.setBeingVisited(false);
        sourceVertex.setVisited(true);
        return false;
    }

    public boolean hasCycle() {
        for (Vertex vertex : vertices) {
            if (!vertex.isVisited() && hasCycle(vertex)) {
                return true;
            }
        }
        return false;
    }
}

顶点:

public class Vertex {

    public String getLabel() {
        return label;
    }

    public void setLabel(String label) {
        this.label = label;
    }

    private String label;

    public boolean isBeingVisited() {
        return beingVisited;
    }

    public void setBeingVisited(boolean beingVisited) {
        this.beingVisited = beingVisited;
    }

    public boolean isVisited() {
        return visited;
    }

    public void setVisited(boolean visited) {
        this.visited = visited;
    }

    private boolean beingVisited;

    public List<Vertex> getAdjacencyList() {
        return adjacencyList;
    }

    public void setAdjacencyList(List<Vertex> adjacencyList) {
        this.adjacencyList = adjacencyList;
    }

    private boolean visited;
    private List<Vertex> adjacencyList;

    public Vertex(String label) {
        this.label = label;
        this.adjacencyList = new ArrayList<>();
    }

    public void addNeighbor(Vertex adjacent) {
        this.adjacencyList.add(adjacent);
    }
}

主要的:

public class Main {

    public static void main(String[] args) {

        Graph graph = new Graph();
        String[][] rs = new String[5][2];
        rs[0][0] = "A";
        rs[0][1] = "B";
        rs[1][0] = "B";
        rs[1][1] = "C";
        rs[2][0] = "C";
        rs[2][1] = "D";
        rs[3][0] = "C";
        rs[3][1] = "A";
        rs[4][0] = "C";
        rs[4][1] = "F";

        HashMap<String,Vertex> verticesList = new HashMap<String,Vertex>();


        for(int i = 0; i<rs.length;i++){
            String from = rs[i][0];
            String to = rs[i][1];
            System.out.println("From: " + from + " to: " + to);

            Vertex vertexFrom;
            Vertex vertexTo;
            if (verticesList.containsKey(from)) {
                vertexFrom = verticesList.get(from);
            } else {
                vertexFrom = new Vertex(from);
                verticesList.put(from,vertexFrom);
            }
            if (verticesList.containsKey(to)) {
                vertexTo = verticesList.get(to);
            } else {
                vertexTo = new Vertex(to);
                verticesList.put(to,vertexTo);
            }
            graph.addVertex(vertexTo);
            graph.addVertex(vertexFrom);
            graph.addEdge(vertexFrom, vertexTo);
        }
        System.out.println(graph.hasCycle());
        System.out.println(verticesList.size());
    }
}

输出:

From: A to: B
From: B to: C
From: C to: D
From: C to: A
From: C to: F
true
5
  1. 正如我所看到的,你的程序不会仅仅因为它只计算一个方向上的边而工作,但是如果我们想检查一个图是一棵树,我们不使用边的方向。

这样你就永远找不到循环 ab, bc, ac。

  1. 如果要检查算法,请手动计算其中间结果并检查它们 - 所有这些,而不仅仅是最后一个。 这是你的工作,不是我们的。

  2. 把所有合适的代码放在这里。 如我所见,您的示例问题不在hasCycle方法中。 我会检查吸气剂/二传手。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM