[英]How can I recursively get all connected nodes of graph, which can contain cycles?
I try to implement weighted graph. 我尝试实现加权图。 Almost done, but I faced with one problem, I can't properly collect all connected nodes of graph.
差不多完成了,但是我面临一个问题,我无法正确收集图的所有连接节点。 For example I have following 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
I want to get as result set of sets [[1,2,3,4],[5,6]], my code works good if no cycles but with cycles my code goes to infinite loop. 我想获得集合[[1,2,3,4],[5,6]]的结果集,如果没有循环,但是我的代码进入无限循环,则代码运行良好。
Node class: 节点类:
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 + ".");
}
}
Code of test class 测试等级代码
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());
}
I hope you help me with recursive function. 希望您对我的递归功能有所帮助。 Thank you for your time.
感谢您的时间。
[Copied from comment] While following the nodes you need to keep track which nodes you have seen already, eg put all nodes you followed in a set. [从注释中复制]在跟踪节点时,您需要跟踪已经看到的节点,例如,将跟踪的所有节点放在集合中。 Whenever you consider a new node, you check if you have been following this before, and if yes you ignore it.
无论何时考虑新节点,都将检查您之前是否一直在关注此节点,如果是,则忽略它。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.