How to iterate through a list of objects and assign children?

冷暖自知 提交于 2019-12-06 15:58:42

If you want to build a graph of any kind, then recognize That a graph is composed of on 2 basic elements:

  1. E -> edge
  2. V -> Vertex (A.K.A node)

Key properties:

  • Vertices can have any number of edges.
  • Edges only go between single nodes (in my implementation I modified this for book keeping sake).

Practically speaking, how you access these will depend on a trade off between functionality and performance. In addition, graph nodes are worthless if they don't contain some of your information. So, we add

Map<String,Object> properties

So we can store some data like:

new Vertext().set("age",10);

We also use named edges so you can do things like:

Graph g = new Graph();
g.addVertex("Doctor",new DrVertex("Dr. Smith"));
g.addVertex("Doctor",new DrVertex("Dr. Cooper"));
List<Vertex> doctors = g.get("Doctor");
assertTrue("Dr. Smith",doctors.get(0));
assertTrue("Dr. Cooper",doctors.get(1));

I have put together the basic structure for how I would implement a generic graph. But some have pointed out that there are graph DB's out there like Neo which are very sophisticated.

Below is the code. Use it if you'd like to model your locations.

/**
 * @author Christian Bongiorno
 */
public class Graph {

    private class Vertex {
        Map<String,Object> properties;
        private Map<String,Edge> edges;

        public Graph addVertex(String edgeName, Vertex v) {
            Edge e = edges.get(edgeName);
            if(e == null) {
                e = new Edge(this);
                edges.put(edgeName,e);
            }

            e.addVertex(v);
            return Graph.this;
        }

        public Graph addVertex(Vertex v) {
            return addVertex("anonymous",v);
        }

    }

    private static class Edge {
        Map<String,Object> properties;
        Vertex in;
        Collection<Vertex> out;

        private Edge(Vertex in) {
            this.in = in;
        }


        private void addVertex(Vertex v) {
            out.add(v);
        }
    }

}

You might consider moving this question to codereview.stackexchange.com

Edited

Imagine you code like this:

  • Location -> Vertex
  • Location[] -> All connected Locations (Vertices) where i in location[i] is the Edge

Your code will be difficult to work with because you don't have declared edges. One of the properties of an edge is "weight" but here you have it as location's property.

As for implementing "visited" -- this is a call-state not a graph wide state. But, by making it part of the Location you now have a state management problem; Imagine trying to "find" something again? You would have to reset the 'visited' property on every node or throw away and create the whole graph again. Very inefficient and error prone.

if you implement DFS, which is really easy recursively or even with a tail loop, you pass the "visited" state along with the dfs method call. Example:

public Location find(Integer locationId) {
   Location result = null;
   for(Location l : locations) {
      // this hashset represents the visited state which only matters for this method call
      result = dfs(new HashSet(),l,locationId); 
      if(result != null)
          break;
   }
   return result;
}

Note that this next method is private.

private Location dfs(Set<Location> visitedAlready,Location current, Integer id){
   if(current.id == id)
      return current;
   visitedAlready.add(current); // instead of your boolean
   Location result = null;
   for(Location l : current.locations) {
      result = dfs(visitedAlready,l,id);
      if(result != null)
        break;
   }
   return result;
}

This is a rough outline. If you reach out to me in Java chat I will give more input and eventually something more slick and reusable. I make no claim the above DFS works. But it's close

I am not sure that I completely understand but do the names in the 'Exits' array become children nodes? Not sure what methods are on the Exit object or if this is even remotely the most efficient solution plus I can't check the syntax at the moment unfortunately.

The idea is that the method takes a node, finds the child node and then invokes the method on that node effectively recursively 'walking' down the hierarchy.

ArrarList<Location> allNodes

// Create children for the specified node
public void createChildNodes(node n){
    // Fetch all available exits
    for(Exit e : n.getExit()){
        // Iterate through all possible nodes
        for(tempNode : allNodes) {
            // Check if the 'exit' node matches one of the available nodes
            if(tempNode.getName().equals(e.getName()){
                // Match found, add it
                n.addChildNode(tempNode, tempNode.getDistance));

                // Check for children nodes of the temp node
                createChildNodes(tempNode);
            }
        }
    }
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!