java—如何递归地获取图中所有可包含循环的连接节点?

e5njpo68  于 2021-07-09  发布在  Java
关注(0)|答案(1)|浏览(308)

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

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 + ".");
    }
}

测试类代码

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());
    }

我希望你能帮助我学习递归函数。谢谢你抽出时间。

cl25kdpy

cl25kdpy1#

[从注解复制]在跟踪节点时,您需要跟踪已看到的节点,例如,将跟踪的所有节点放在一个集合中。每当您考虑一个新节点时,您都会检查您以前是否关注过它,如果是,则忽略它。

相关问题