Tree that sorts classes hierarchicly - java

I need a tree-structure that sorts all added classes hierarchically. I have to get all classes that inherit one certain class. That one particular read access needs to be very fast.
Example:
I add the following classes.
public static class Event
{
}
public static class PlayerEvent extends Event
{
}
public static class PlayerMoveEvent extends PlayerEvent
{
}
public static class WorldEvent extends Event
{
}
It should sort the classes like this:
http://i.imgur.com/J6DyZvL.png

Use a Map <Class, List <Class>>, where the key is the parent class, and the List contains all the children.

Have a Node class that represents a node in your tree.
It stores the class that it represents and its direct children.
class Node {
Set<Node> children;
Class class;
}
Then you can construct the tree, and get your root node.
List<Class> classList = ...l
Map<Class,Node> classMap = ... a map from all your classes to nodes made from them;
Node rootNode = null;
for(Class c : classList){
Node parentNode = classMap.get(c.getSuperclass());
if(parentNode != null)
parentNode.children.add(classMap.get(c));
else
rootNode = classMap.get(c);
}

Andres answer is best for O(1) lookup.
You always have to iterate if you are using a hierarchial data structure . If you want to store the hierarchial data structure so that you can have O(1) retrieval , you need to have memory to snapshot it. Java stores references , so it wont be as much memory as you are thinking of, but it still would not be insignificant. If you want to save on memory you can use disk sapce by writing the values of the child classes to a file . Every time you add a child class, you append a row to the list of child classes.

Related

How to implement Graph search (DFS) with Object Oriented design [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 6 years ago.
Improve this question
I'm not so sure about what's the best approach to model this problem in the object oriented world.
Suppose I have to represent a graph and its nodes in Java and suppose I want to traverse the graph using a depth first search (DFS).
What is the best approach in Software engineering among these two:
Create a class Node, a class Graph and a class GraphsFunctions where the GraphsFunctions class contains the DFS method which takes the Graph and a Node as parameters. Something like this: public void DFS(Graph g, Node n) and the call new GraphsFunctions().DFS(new Graph(), new Node())
Create a class Node and a class Graph where the class Graph contains the method DFS which only takes a Node as a parameter. Something like this: public void DFS(Node n) and the call new Graph().DFS(new Node())
I would rather use the first of the two options but I can't say why it's the best for me. Can you tell me what makes the best choice, actually the best?
This really depends on mostly two things:
How much encapsulation you want in your project. More encapsulation is usually better, but it can come at the price of over engineering the problem, which can cause a lot more work which you want to avoid for small projects which wont grow over time.
Your own personal style. Each developer will develop his or her own style over time which will be clearly distinguishable from other developers. The most important thing is consistency throughout a project
Assuming you want (only) good encapsulation I would personally do it like the following..
Create an interface GraphSearch and define your search(Graph g, Node n) method in there. Now have a class called DFSearch and possibliy BFSearch.
If - at some point - a method wants to perform searches on a Graph you can specify the search algorithm which should be used.
If you want great encapsulation, I would recommend using the iterator pattern as DFS and BFS are basically just iteration orders.
Start by creating an Interface GraphIterator instead. It simply extends Iterator<Node> which means it can iterate over Nodes in some order.
public interface GraphIterator extends Iterator<Node> {
}
Create as many implementations of this algorithm as you like. An empty construct for DFS looks like this:
public class DFSIterator implements GraphIterator {
private Graph g;
public DFSIterator(Graph g) {
this.g = g;
}
#Override
public boolean hasNext() {
// todo: implement
return false;
}
#Override
public Node next() {
// todo: implement
return null;
}
}
Next you can still create your Interface GraphSearch..
public interface GraphSearch {
Node search(Graph g, Node n);
}
And one simple implementation would be IterationSearch which can only perform searches with a given Iterator.
public class IterationSearch {
public Node search(Graph g, Node n, GraphIterator iter){
Node current = null;
while (iter.hasNext()){
current = iter.next();
if (current.equals(n)){
return n;
}
}
return null;
}
}
It just iterates over the Iterator and compares each element to the searched node. Next create your class DFSearch which is the first actual GraphSearch...
public class DFSearch extends IterationSearch implements GraphSearch{
#Override
public Node search(Graph g, Node n) {
return search(g, n, new DFSIterator(g));
}
}
Now your Graph can extend Itarable<Node> and return one of your iterators as the default iterator. This way you could nicely iterate over your Graph.
public class Graph implements Iterable<Node> {
#Override
public Iterator<Node> iterator() {
return new DFSIterator(this);
}
}
and use it like the following:
Graph g = createGraph();
for (Node n : g) {
// do things...
}
The great thing about this solution is that you can make the Iterators inner classes of your Graph, which allows them to access private members. This often improves performance significantly as you don't have to treat the Graph as a black box.
Best in terms of fast-to-code, easy-to-modify, or some other criterion? Unless you come up with a very precise definition of "what is good", do not expect to find "best".
My first answer would be to use a graph library for Java. Most come with DFS already implemented:
Already implemented and debugged.
Good documentation.
No company will generally want me to reinvent the wheel.
However, since your question is probably part of a do-it-yourself course, I would instead recommend:
Node class, which can provide access to neighbors, and has equals and hashcode methods.
Graphs class, which can build graphs and display them. Includes a Dfs(Graph g, Node start, DfsVisitor visitor) method. This would be a utility class with all-static methods, in the same vein as JDK's Collections or Files.
Graph class, with a list of nodes (and possibly other things, such as the possibility of returning an iterator to a list of edges).
DfsVisitor, an interface for visitors:
Main class, which builds a graph and calls your DFS on the graph with the useful payload in the visitor.
Because DFS by itself is useless - it is just a node-visiting strategy. Its value is in what it does before and after it visits a node. Unless you allow this to be customized, placing a DFS algorithm into GraphsFunctions or Graphs makes no big difference: it is not likely to be reused outside of whatever payload you have built into it.
public interface DfsVisitor() {
void started(Graph g, Node node); // when first encountered
void finished(Graph g, Node node); // when all children processed
}

Java member function for BST in order traversal

I recently was in a interview and was asked to code a in order traversal for a BST using the java member function prototype below.
public void inOrderPrint()
I was confused by the fact that it did not take in any parameters. I am used to the node to be passed in. It is very easy to traverse the tree with the node passed in... I am just a little confused how one would go about it without the initial reference?
The given signature makes sense if inOrderPrint() is defined in the Node class of the BST, then it's implied that the tree to traverse is the one rooted in the current node. Alternatively, it could be that the tree is an attribute in the current class. Assuming that the method is in the node class, it'd be something like this - and do notice how the recursion gets called:
public class Node {
private Node left;
private Node right;
private Object value;
public void inOrderPrint() {
if (left != null)
left.inOrderPrint();
System.out.println(value);
if (right != null)
right.inOrderPrint();
}
}
Given that it's a member function,one can assume that you have access to the root (e.g. this.root). You could just overload this method with a method where you pass in a node. You would then call the overloaded method inside the given one with the root.
EDIT:
I thought the method was defined in the tree, not in the Node class. You could do it like this: (make sure to check for null!)
public void inOrderPrint(){
//traverse down the left tree
this.left.inOrderPrint();
System.out.println(this);
//traverse down the right tree
this.right.inOrderPrint();
}

Graph implementing a comparable node java

For one of my projects in my computer science class, I have to implement a directed, weighted graph. Since we are only allowed to use an adjacency list and not an adjacency matrix, I decided to create a Node class that will contain my data, as well as a treeset to hold all of its edges, since the project stipulates that the edges must be sorted using the natural ordering of whatever data my graph is instantiated with. My Node class looks like this:
private class Node<V extends Comparable<V>> {
private V data;
private TreeSet<Edge> edges = new TreeSet<Edge>();
public Node(V data) {
this.data = data;
}
}
My graph itself is also a treeset that contains objects of type Node. I cannot, however, add to the graph using my add method which is as follows:
private boolean addVertex(V vertex) {
Iterator iter = graph.iterator();
Node check;
while (iter.hasNext()) {
check = (Node) iter.next();
if (check.data.compareTo(vertex) == 0)
return false;
}
Node n = new Node(vertex);
graph.add(n);
return true;
}
How can I make it so that my code adds Nodes to my graph class using the natural ordering of the data that the Node class is instantiated with?
**Edit
So based on what Peter said, I was able to come up with a solution (sort of) to my problem. Since my edges, per project stipulation, must be iterated over in the natural order of the data held in the nodes, I created a compareTo method in my edge class that works by using the data's compareTo method. It looks something like this:
private class Edge<V extends Comparable<V>> implements Comparable<V> {
private int weight;
private boolean visited;
//This is the data held in the node the edge ends at
private V endNode;
public Edge(V dest, int weight) {
visited = false;
endNode = dest;
this.weight = weight;
}
public int compareTo(Edge<V> e) {
if (endNode.compareTo((V) e.endNode) < 0)
return -1;
else if (endNode.compareTo((V) e.endNode) == 0)
return 0;
else
return 1;
}
}
Unfortunately, when I try and do this, I get two errors. one of them says "the type parameter V is hiding the type V" and the other says I must implement the Comparable.compareTo(V) method even though I explicitly do it in my code. I was able to find some information on the first error, which said that I could be getting that error because I used V as a concrete type somewhere in my code, however, that does not really help me much since I don't fully understand it. I did that in my Node class and nothing happened, so why am I getting errors in my Edge class? Any help would be greatly appreciated.
Also the class that both Node and Edge are declared in is defined as
public class Graph<V extends Comparable<V>>
if that helps anyone
The wikipedia page http://en.wikipedia.org/wiki/Adjacency_list is a good starting point.
Also, google for this "Goodrich and Tamassia adjacency".
This is a good starting point too.
Because your Graph is weighted and directed, it means you can/should associate with each Vertex the list of its outgoing (or alternatively incoming) Edges. An Edge is then an ordered couple of its two vertices (start vertex and end vertex) and whatever additional information you may want to store in it (e.g. its weight). That's what you need here.
Seems to me the natural ordering you're referring to is about the Edges, not about the Vertices. But you can have some ordering the vertices too.
You can also have a Graph class. The Graph can be just your top-level container class which gives you fast access to e.g.: 1) a Vertex given its id/name (or whatever piece of data you use to identify it), 2) an Edge given e.g. its start and end vertices, other methods, etc.
In general your code so far looks OK btw. I mean you seem to be on the right track.

Using an Interface in Java

Well I have a fairly simple question I just can't seem to find my way around...
For a class, I have to implement an interface for a binary tree that has a method like:
public List<Node<E>> listAll();
we are required to have a class called MyNode.java, which is what I use to make my tree with. So to list all children I thought I would do this:
public List<Node<E>> listAll(){
List<Node<E>> childList = new ArrayList<>();
MyNode<E> thisNode = this.l;
while(thisNode!= null){
childList.add(thisNode);
thisNode = thisNode.l;
}
return childList;
}
and to do something like set a child
public void setChild(Node<E> child){
E elem = child.getElement();
MyNode<E> newNode = new MyNode(elem);
this.l = newNode;
}
So my question is: am I going about this correctly? If I try to create a Node, I can't because my nodes are called MyNodes but when I try to create a list of MyNodes and return them it gives me an error because I am not following the interface.. When I try to make the method accept MyNode instead of Node it says I am not following the interface. A little more clarification below..
I currently am using the implements declaration to implement the Node.java interface.. When I am writing the method that is specified by my interface as:
public void setChild(Node<E> child);
then I am currently fleshing out the method like so:
public void setChild(Node<E> child) {
E elem = child.getElement();
MyNode<E> newNode = new MyNode<E>(elem);
MyNode<E> transNode = this.l;
if(transNode!=null){
while(transNode.r!=null){
transNode = transNode.r;
}
transNode = newNode;
}
else transNode = newNode;
}
you can see how I am getting the element from input child and creating a new MyNode out of it to put as the new child instead of just injecting Node into my tree.. Is this wrong? I can't seem to get another way to work...
Interfaces are good for making code generic. If you wanted to have multiple implementations of a Node class that each would have the same methods then making an interface would be a good idea.
Alternatively, if you want to enforce an API for someone else to use, and interface is the right way to do that. You can make methods that accept any object that implements that interface.
If you're just creating one Node class for a simple binary tree implementation it might not make sense. Your binary tree might want to implement a Collection interface to make it available as a generic structure.
If you want to contractualize yourself to an API before beginning, an interface could further be a good way to do that.
In general you don't want to create an interface unless you want an abstraction where you actually will write different implementations of that abstraction. In your case, class Node<T> will suffice for your needs.
It is generally considered good form to use an interface for the API.
Briefly, doing so:
allowing the caller to provide whatever implementation they like
makes testing easier, especially when using mocks
chisels the least amount of the API in stone
See Liskov substitution principle

class declaration and definition in Java

public class Tree<T>
{
private Node<T> root;
public Tree(T rootData)
{
root = new Node<T>();
root.data = rootData;
root.children = new ArrayList<Node<T>>();
}
}
I found a code in which the class is declared like this? What does mean?
The class is for a Tree, which is a common data structure used to store things in a tree like form (each part of the tree is called a "node", and then each node can have a child node to its left or right like this.
The generic parameter T means we can create a tree of any type, and all the nodes in that tree will need to be of that same type.
The constructor we see allows us to create a new Node (the top of the tree), initialise it with the rootData, and create a list of children which will be all of the nodes below this root node.
This is a generic. When instantiating a Tree you can provide a class such as Tree<String> that will be used for the Node in a similar way, and as the constructor parameter type.

Categories