Java 如何递归地获取图中所有可以包含圈的连通节点?

Java 如何递归地获取图中所有可以包含圈的连通节点?,java,recursion,graph,Java,Recursion,Graph,我尝试实现加权图。差不多完成了,但我面临一个问题,我不能正确地收集图中所有连接的节点。例如,我有以下图表: 1 2 3 4 5 6 1 0 1 1 0 0 0 2 1 0 1 1 0 0 3 1 1 0 1 0 0 4 0 1 1 0 0 0 5 0 0 0 0 0 1 6 0 0 0 0 1 0 我想得到集合[[1,2,3,4],[5,6]]的结果集,如果没有循环,我的代码运行良好,但是有了循环,我的代码进入无限循环

我尝试实现加权图。差不多完成了,但我面临一个问题,我不能正确地收集图中所有连接的节点。例如,我有以下图表:

  1  2  3  4  5  6
1 0  1  1  0  0  0
2 1  0  1  1  0  0
3 1  1  0  1  0  0
4 0  1  1  0  0  0
5 0  0  0  0  0  1
6 0  0  0  0  1  0
我想得到集合[[1,2,3,4],[5,6]]的结果集,如果没有循环,我的代码运行良好,但是有了循环,我的代码进入无限循环

节点类:

    public class Node<T> {

    private T content;

    private Set<Node<T>> neighbors;

    private boolean marked;

    public Node(T content) {
        super();
        Validate.notNull(content, "Value of vertex can't be null!");
        this.content = content;
        this.neighbors = new HashSet<Node<T>>();
    }

    public T getContent() {
        return content;
    }

    public void setContent(T content) {
        this.content = content;
    }

    public boolean hasNeighbors() {
        return !neighbors.isEmpty();
    }

    public void addNeighbor(Node<T> neighbor) {
        this.neighbors.add(neighbor);
    }

    public Set<Node<T>> getNeighbors() {
        return neighbors;
    }

    public void setNeighbors(Set<Node<T>> neighbors) {
        this.neighbors = neighbors;
    }

    public boolean isMarked() {
        return marked;
    }

    public void setMarked(boolean marked) {
        this.marked = marked;
    }

    public Set<Node<T>> getAllRelatedNeighbors() {
        Set<Node<T>> result = new HashSet<Node<T>>();
        result.add(this);

        if (neighbors.isEmpty()) {
            return result;
        }

        for (Node<T> neighbor : neighbors) {
            result.add(neighbor);
            for(Node<T> nestedNeighbor: neighbor.getNeighbors()){
                if(!nestedNeighbor.equals(this) ){
                    result.addAll(neighbor.getAllRelatedNeighbors());
                }
            }
        }
        return result;
    }

    @Override
    public String toString() {
        return "Vertex [content=" + content + ", marked=" + marked + "]";
    }

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + ((content == null) ? 0 : content.hashCode());
        result = prime * result + (marked ? 1231 : 1237);
        return result;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        Node other = (Node) obj;
        if (content == null) {
            if (other.content != null)
                return false;
        } else if (!content.equals(other.content))
            return false;
        if (marked != other.marked)
            return false;
        return true;
    }
}

public class Edge<T> {

    private Node<T> first;

    private Node<T> second;

    private int weight;

    public Edge(Node<T> first, Node<T> second, int weight) {
        this(first, second);
        this.weight = weight;
    }

    public Edge(Node<T> first, Node<T> second) {
        super();
        this.first = first;
        this.second = second;
        this.first.addNeighbor(second);
        this.second.addNeighbor(first);
    }

    public Node<T> getFirst() {
        return first;
    }

    public void setFirst(Node<T> first) {
        this.first = first;
    }

    public Node<T> getSecond() {
        return second;
    }

    public void setSecond(Node<T> second) {
        this.second = second;
    }

    public int getWeight() {
        return weight;
    }

    public void setWeight(int weight) {
        this.weight = weight;
    }

    @Override
    public String toString() {
        return "Edge [first=" + first + ", second=" + second + ", weight="
                + weight + "]";
    }

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + ((first == null) ? 0 : first.hashCode());
        result = prime * result + ((second == null) ? 0 : second.hashCode());
        result = prime * result + weight;
        return result;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        Edge other = (Edge) obj;
        if (first == null) {
            if (other.first != null)
                return false;
        } else if (!first.equals(other.first))
            return false;
        if (second == null) {
            if (other.second != null)
                return false;
        } else if (!second.equals(other.second))
            return false;
        if (weight != other.weight)
            return false;
        return true;
    }               
}

public class WeightedGraph<T> {

    private Set<Node<T>> nodes;

    private Set<Edge<T>> edges;

    public WeightedGraph(Collection<T> elements) {
        this();
        addNodes(convertCollectionOfElementsToNodes(elements));
    }

    public WeightedGraph(Set<Node<T>> nodes, Set<Edge<T>> edges) {
        super();
        validateParameters(nodes, edges);
        this.nodes = nodes;
        this.edges = edges;
    }

    public WeightedGraph() {
        super();
        this.nodes = new HashSet<Node<T>>();
        this.edges = new HashSet<Edge<T>>();
    }

    public void addNode(Node<T> node) {
        this.nodes.add(node);
    }

    public void addNodes(Set<Node<T>> nodes) {
        this.nodes.addAll(nodes);
    }

    public void addEdge(Edge<T> edge) {
        this.edges.add(edge);
    }

    public void addEdges(Set<Edge<T>> edges) {
        this.edges.addAll(edges);
    }

    public Set<Node<T>> getNodes() {
        return nodes;
    }

    public Set<Edge<T>> getEdges() {
        return edges;
    }

    public void connectNodesBidirectional(Node<T> first, Node<T> second) {
        connectNodesBidirectional(first, second, 0);
    }

    public void connectNodesBidirectional(Node<T> first, Node<T> second,
            int weight) {
        validateNode(first);
        validateNode(second);
        edges.add(new Edge<T>(first, second, weight));      
        edges.add(new Edge<T>(second, first, weight));
    }

    public void connectNodes(Node<T> first, Node<T> second) {
        connectNodes(first, second, 0);
    }

    public void connectNodes(Node<T> first, Node<T> second, int weight) {
        validateNode(first);
        validateNode(second);
        edges.add(new Edge<T>(first, second, weight));
    }

    private Set<Node<T>> convertCollectionOfElementsToNodes(Collection<T> elements){
        Set<Node<T>> nodes = new HashSet<Node<T>>();
        for(T element : elements) {
            nodes.add(new Node<T>(element));
        }
        return nodes;
    }

    private void validateParameters(Set<Node<T>> nodes, Set<Edge<T>> edges) {
        Validate.notNull(nodes, "Collection of nodes can't be null.");
        Validate.notNull(edges, "Collection of nodes can't be null.");
        for (Edge<T> edge : edges) {
            Validate.isTrue(
                    nodes.contains(edge.getFirst())
                            && nodes.contains(edge.getSecond()),
                    "Should be passed properly configured collection, each node of each edge should exist in node collection.");
        }
    }

    private void validateNode(Node<T> node) {
        Validate.notNull(node, "Node can't be null.");
        Validate.isTrue(nodes.contains(node),
                "Graph should contains specified node: " + node + ".");
    }
}
公共类节点{
私有内容;
私人设置的邻居;
私有布尔标记;
公共节点(T内容){
超级();
notNull(内容:“顶点的值不能为null!”);
this.content=内容;
this.neights=new HashSet();
}
公共T getContent(){
返回内容;
}
公共内容(T内容){
this.content=内容;
}
公共布尔值(){
返回!邻居。isEmpty();
}
公共无效添加邻居(节点邻居){
this.neighbors.add(neighbor);
}
公共集getNeights(){
回归邻居;
}
公共无效集合邻居(集合邻居){
这个。邻居=邻居;
}
公共布尔值isMarked(){
返回标记;
}
设置标记的公共无效(布尔标记){
这是有标记的;
}
公共集GetAllRelatedNeights(){
Set result=new HashSet();
结果。添加(此);
if(neights.isEmpty()){
返回结果;
}
用于(节点邻居:邻居){
结果。添加(邻居);
对于(节点nestedNeighbor:neighbor.getNeighbors()){
如果(!nestedNeighbor.equals(this)){
result.addAll(neighbor.getAllRelatedNeighbors());
}
}
}
返回结果;
}
@凌驾
公共字符串toString(){
返回“顶点[content=“+content+”,marked=“+marked+”]”;
}
@凌驾
公共int hashCode(){
最终整数素数=31;
int结果=1;
result=prime*result+((content==null)?0:content.hashCode();
结果=素数*结果+(标记为?1231:1237);
返回结果;
}
@凌驾
公共布尔等于(对象obj){
if(this==obj)
返回true;
if(obj==null)
返回false;
如果(getClass()!=obj.getClass())
返回false;
节点其他=(节点)obj;
if(content==null){
if(other.content!=null)
返回false;
}如果(!content.equals(other.content))
返回false;
如果(已标记!=其他已标记)
返回false;
返回true;
}
}
公共阶级边缘{
私有节点优先;
第二私有节点;
私有整数权重;
公共边(节点第一,节点第二,整数权重){
这(第一,第二);
重量=重量;
}
公共边缘(节点第一,节点第二){
超级();
this.first=first;
这个秒=秒;
这个。第一。添加邻居(第二);
this.second.addNeighbor(第一个);
}
公共节点getFirst(){
先返回;
}
公共void setFirst(节点优先){
this.first=first;
}
公共节点getSecond(){
返回第二;
}
公共无效设置秒(节点秒){
这个秒=秒;
}
公共整数getWeight(){
返回重量;
}
公共空隙设定重量(内部重量){
重量=重量;
}
@凌驾
公共字符串toString(){
return“Edge[first=“+first+”,second=“+second+”,weight=”
+重量+“]”;
}
@凌驾
公共int hashCode(){
最终整数素数=31;
int结果=1;
result=prime*result+((first==null)?0:first.hashCode();
result=prime*result+((second==null)?0:second.hashCode();
结果=基本值*结果+权重;
返回结果;
}
@凌驾
公共布尔等于(对象obj){
if(this==obj)
返回true;
if(obj==null)
返回false;
如果(getClass()!=obj.getClass())
返回false;
边缘其他=(边缘)obj;
if(first==null){
if(other.first!=null)
返回false;
}else如果(!first.equals(other.first))
返回false;
if(秒==null){
if(other.second!=null)
返回false;
}else如果(!second.equals(other.second))
返回false;
如果(重量!=其他重量)
返回false;
返回true;
}               
}
公共类加权图{
私有集节点;
私有集边;
公共权重图(集合元素){
这个();
添加节点(ConvertCollectionFelementsToNodes(元素));
}
公共权重图(设置节点、设置边){
超级();
验证参数(节点、边);
this.nodes=节点;
这个。边=边;
}
公共权重图(){
超级();
this.nodes=new HashSet();
this.edges=新的HashSet();
}
公共void addNode(节点){
this.nodes.add(节点);
}
公共void addNodes(设置节点){
this.nodes.addAll(节点);
}
公共无效添加(边缘){
this.edges.add(edge);
}
公共无效添加(设置边){
this.edges.addAll(edges);
}
公共集getNodes(){
返回节点;
}
公共集getEdge(){
返回边;
}
public void connectNodes双向(节点第一,节点第二){
连接节点双向(第一、第二、0);
}
public void connectNodes双向(节点第一,节点第二,
整数(重量){
验证节点(第一);
验证节点(第二);
添加(新边(第一、第二、权重));
预计起飞时间
    WeightedGraph<Integer> graph = new WeightedGraph<Integer>();

    Node<Integer> first = new Node<Integer>(1);
    Node<Integer> second = new Node<Integer>(2);
    Node<Integer> third = new Node<Integer>(3);
    Node<Integer> fourth = new Node<Integer>(4);

    graph.addNode(first);
    graph.addNode(second);
    graph.addNode(third);
    graph.addNode(fourth);

    graph.connectNodesBidirectional(first, second);
    graph.connectNodesBidirectional(second, third);
    graph.connectNodesBidirectional(first, third);
    graph.connectNodesBidirectional(third, fourth);
    graph.connectNodesBidirectional(fourth, second);

    Set<Node<Integer>> nodes = graph.getNodes();
    Set<Set<Node<Integer>>> result = new HashSet<Set<Node<Integer>>>();
    for (Node<Integer> node : nodes) {
        result.add(node.getAllRelatedNeighbors());
    }