Rendering a dynamically created family graph with no overlapping using a depth first search?

前端 未结 5 1820
深忆病人
深忆病人 2021-01-31 07:42

I want to generate this:

With this data structure (ids are random, btw not sequential):

var tree = [
    { \"id\": 1, \"name\": \"Me\", \"dob\":         


        
5条回答
  •  既然无缘
    2021-01-31 08:06

    From what I can see - without looking at the code you have there (for now) - you have a DAG (the visual representation is another matter, now I'm talking only about the data structure). Each node has a maximum of 2 incoming connections and no constraint on connections going to other nodes (one can have an arbitrary number of children but we have info on a maximum of 2 parents for each person/node).

    That being said, there will be nodes that do not have parents (in this case are "john", "raymond", "betty", "mistress 1", "wife 1", and "daughter 1 boyfriend"). If you do a BFS on the graph starting from these nodes - which would compose level 0 - you get the nodes for each level. The correct level has to be updated on the fly though.

    Regarding the visual representation, I'm no expert, but IMO it can be achieved via a grid (as in, a table-like one) view. Each row contains the nodes of a certain level. The elements in a given row are arranged based on the relationship with the other elements in the same row, in row x - 1, and in row x + 1.

    To better explain the idea I guess it's better to put in some pseudo-code (not JS though as it's not my strength):

    getItemsByLevel(Graph graph)
    {
        Node[,] result = new Node[,];
        var orphans = graph.getOrphans();
        var visiting = new HashMap();
        var visited = new HashMap();
        var queue = new Queue();
    
        queue.pushAll(orphans);
    
        while(!queue.isEmpty())
        {
            var currentNode = queue.pop();
    
            if(currentNode.relatedNodes.areNotBeingVisited()) // the nodes that should be on the same level
            {
                // the level of the current node was not right
                currentNode.level++;
                queue.push(currentNode);
            }
            else
            {
                var children = currentNode.children;
    
                foreach(var child in children)
                {
                    child.level = currentNode.level + 1;
                    queue.push(child);
                }
    
                visited.insert(currentNode);
                result[currentNode.level, lastOfRow] = currentNode;
            }
        }
    
        return result;
    }
    

    In the end of the procedure you're going to have a matrix of nodes where row i contains the nodes of level i. You just have to represent them in the gridview (or whatever you choose as layout).

    Let me know if anything's unclear.

提交回复
热议问题