How to detect circular reference in a Tree?

人走茶凉 提交于 2020-03-23 08:18:02

问题


I have a Node class as follows:

public class Node{
    Object data;
    List<Node> children;
}

I need to traverse this tree in post order and I am using Guava TreeTraverser for for the same.

    TreeTraverser<Node> treeTraverser = new TreeTraverser<Node>() {
                @Override
                public Iterable<Node> children(Node node) {
                    return node.children;
                }
            };

treeTraverser.postOrderTraversal(node);

The catch is that there chances that the given tree could have circular dependencies(means it could be a cyclic graph). What would be an efficient way to detect circular dependencies?


回答1:


By definition, a tree is an acyclic connected graph. Therefore, there is no such thing as a tree with circular dependencies.

You can find cycles in a graph by applying depth-first traversal, and looking for nodes that have been visited the way down. If you visit a node that you have seen during prior steps of DFS, the graph is not a tree.

See this Q&A for advanced cycle detection algorithms.




回答2:


In simple words Tree is a non cyclic data structure and when there are cycles then it becomes a Graph.

Above is an example of a graph. You can represent it using Adjacency list or adjacency matrix. You can refer to http://krishnalearnings.blogspot.in/2015/11/basics-of-graph-in-computer-science.html for basics of Graphs.

In the picture above we can represent it as below (In your question, you have used an adjacency list kind of representation).

int[][] graph = {   {0,1,0,0,0,0},
                    {0,0,1,0,0,0},
                    {0,0,0,1,1,0},
                    {0,0,0,0,0,0},
                    {0,0,0,0,0,1},
                    {0,1,0,0,0,0},
                };

1 represents an edge from corresponding row numbered vertex to column numbered vertex.

We can write a simple method to detect the presence of cycle and also print any one cycle in the graph.

static int[] cycleElements;
static int cycleElementIndex = 0;
static boolean cycleFound = false;
static final int NEW = 0;
static final int PUSHED = 1;
static final int POPPED = 2;
public static int findCycle(int[][] graph,int N, int u, int[] states){
    for(int v = 0; v < N; v++){
        if(graph[u][v] == 1){
            if(states[v] == PUSHED){
                // cycle found
                cycleFound = true;
                return v;
            }else if(states[v] == NEW){
                states[v] = PUSHED;
                int poppedVertex = findCycle(graph, N, v, states);
                states[v] = POPPED;
                if(cycleFound){
                    if(poppedVertex == u){
                        cycleElements[cycleElementIndex++] = v;
                        cycleElements[cycleElementIndex++] = u;
                        cycleFound = false;
                    }else{
                        cycleElements[cycleElementIndex++] = v;
                        return poppedVertex;
                    }
                }
            }
        }
    }
    return -1;
}
public static void main(String[] args) {
    int N = 6;
    int[][] graph = {   {0,1,0,0,0,0},
                        {0,0,1,0,0,0},
                        {0,0,0,1,1,0},
                        {0,0,0,0,0,0},
                        {0,0,0,0,0,1},
                        {0,1,0,0,0,0},
                    };
    cycleElements = new int[N];
    int[] states = new int[N];
    states[0] = PUSHED;
    findCycle(graph,N,0,states);
    for(int i = 0; i < cycleElementIndex; i++){
        System.out.println(cycleElements[i]);
    }
}

You can easily transform above approach to adjacency list if you wish, though representation does not matter much ( only adjacency list may save your space as compared to adjacency matrix)



来源:https://stackoverflow.com/questions/37907339/how-to-detect-circular-reference-in-a-tree

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!