Add a Custom Tree Class in Java Language Hierarchy - java

I have designed a CustomTree class and programmed its operations.
Nodes are added such that a subtree will become full, before an element can be added to its sibling subtree.
Since Tree is a collection of nodes, I realized that, my CustomTree should implement a Collection Interface.
Is this correct or should my CustomTree extend a more relevant class like TreeSet?
I want to know where my class should go into if it should match Java's language heirarchy.

The question is which properties do you want your class to have? Collection properties (just a general "bag"), Set properties (no two elements are the same) and/or List properties (sequence of elements is relevant)?
Once you have answered these questions for yourself, you can select the proper base class.

Related

Why do I need the Node class in Java for LinkedList?

After going over different tutorials on Linked Lists I am seeing some mentioning the Java Node class for linking to the previous and next nodes and some not using it at all when creating a linkedList.
Is the Node class needed for Linked Lists ?
Why do some tutorials seem to create Linked Lists without it?
Also read that using the Node class is the "formal" way of creating a linkedlist
If you are asking whether (and why) you need to create Node instances to use a java.util.LinkedList, the answer is: No you don't. The list itself takes care of that.
(Note that the Node class that you linked to is not a linked list node. It actually denotes a node in an DOM. The actual Node class used internally by java.util.LinkedList is a private class.)
If you were asking why linked lists in general require a Node type, the answer is that they don't.
The other way of creating a linked list (that doesn't involve a Node type) is to directly chain the elements of a list to each other. This has a couple of consequences:
This requires the element class itself to have a next field (and possibly a prev field) for chaining the elements.
It means that a given element instance can only be a member of one list at a time, and can't be a member of the same list twice.
Together, these mean that the nodeless approach is incompatible with the standard java.util.List API.
The nodeless approach is also bad from the OO design perspective:
By the adding next and prev fields to the element type, you are breaking down abstraction boundaries and the separation of concerns.
The element instance now knows about the list that the element is part of.
The list abstraction only works for certain types of element, and has to take account of which list an element is a member of.
These things are liable to make the nodeless list abstraction harder to use ... and less reusable. (Though in limited circumstances, it may still be a good solution.)
You don’t technically necessarily need a node class, but the design with a node class is the good design. The design without one is the poor design.
This answer is slightly opinionated, but based on what we should all have learned in the first or at least the second year of programming, so consensus-based.
Say that we have a list of students. It’s now the natural responsibility of each Student object to have (“know”) the student’s contact information, courses enrolled in, grades taken, etc. It is not the natural responsibility of a Student object to know that it is part of a linked list, not to mention whether that list is singly or doubly linked. For this responsibility we have the Node class.
The design with the Node class has the further potential advantage that you can design and code a generic linked list and use it to instantiate a list of students, a list of teachers, a list of courses, etc. Stephen C in the other answer mentions further advantages.
Historical background: Where I learned data structures around 1980, we would fit each student record with a next pointer. (We learned singly linked lists. Doubly linked lists were only mentioned in passing.) What is nowadays considered the poor design. I had hoped that it had long gone out of use.
Performance (skip this paragraph until you really need it :-) : The poor design with next and previous references within the business objects like Student will typically perform slightly better. So if you are in a situation where performance is a Very Real Issue, you may consider it. It is no low-hanging fruit since it pollutes your design, so it will probably come near the bottom of your list of measures to take for better performance.

"Preferences" in Java

I don't know exactly how to word this, but I am wondering if it is possible to have "preferences" when choosing from a list.
For example, if I have a list of comparable tree objects with different variables (size, type, height), is it possible to "prefer" say bigger tree/ one type of tree over the other etc. In other words when choosing one object from the list, the tendency is to choose the largest tree or to choose one type of tree over the other, but not always (there is a stochastic element).
The idea you want is a sorted list. Various methods exist for this such as Collections.sort and Arrays.sort, as well as several java.util classes that automatically sort themselves (consider also some structures other than lists, like heaps). You can either make Trees Comparable<Tree> or make a Comparator<Tree> so that you can create lists arranged so that you can easily find the "most preferable" item (which will be moved to the front of the list) or the "least preferable" item (at the end of the list). See the documentation for the various classes I have mentioned for how to accomplish this.

What should a Tree class contain?

My class is currently doing Binary Trees as part of our data structures unit. I understand that the Node class must have 3 parameters (value, left node, right node) in its constructor. As part of a requirement, we must have a Tree class. What is the purpose of a tree class? Is it for managing the entire set of Nodes? Does it simply contain the functions necessary to insert, remove and search for specific Nodes?
Thank you in advance.
My Node class:
class Node {
protected int data;
protected leftNode;
protected rightNode;
Node (int data, Node leftNode, Node rightNode){
this.data = data;
this.leftNode = leftNode;
this.rightNode = rightNode;
}
}
Yes, it is supposed to give the functional interface of a Tree by encapsulating all the behavior and algorithms related to the internal structure.
Why this is good?
Because you will define something that just provide some functionality and that works in a stand-alone way so that everyone should be able to use your tree class without caring about nodes, algorithms and whatever.
Ideally the class should be parametric so that you'll have Tree<T> and you'll be able to have generic methods for example
T getRoot()
Basically you'll have to project it so that it will allow you to
insert values
delete values
search values
visit the whole tree
whatever
As I see it, a Tree class should hold a reference to the root node of the tree, and to methods and attributes that operate on the tree as a whole, as opposed to methods that belong to each node, like getLeft(), getValue().
For example, I'd define a size attribute in the Tree class, and the methods that add or remove nodes to the tree (which also happen to be in this class) would be responsible for keeping the size up to date.
The purpose of any data structure is to give you a way to hold onto collections of related values and manipulate them in meaningful ways.
A tree is a special kind of data structure. It's a good choice for data that is hierarchical: those with natural parent-child relationships. A binary tree has, at most, two children for every parent node.
One other feature of trees that deserves special mention is the fact that it's self-similar: every Node in a tree is itself the root of a sub-tree. Recursion exploits this fact.
Yes, those are good methods to start with. You might want to have a look at the java.util.Map interface for others that might be useful.
The assumption is, as you suspect, a little bit flawed. The Node type that you have defined is a perfectly fine instance of a binary tree.
Jack mentions that you want to have a Tree type around the whole set of nodes in order to provide operations like getRoot, inserts, deletes and so on. This is of course not a bad idea, but it is by no means a requirement. Many of these operations could go on Node itself, and you don't necessarily have to have all of these operations; for example, there are arguments both for and against having a getRoot operation. An argument against it is that if you have an algorithm that at one point only needs a subtree, then the Tree object that holds on to the root Node prevents garbage collection of Nodes that your algorithm no longer needs.
But more generally, the real question that needs to be asked here is this: which of the things you're dealing are interface, and which are implementation? Because it's one thing if you want to expose binary trees as an interface to callers, and another if you want to provide some sort of finite map as the interface, and the binary tree is just an implementation detail. In the former case, the client would "know" that a tree is either null or a Node with a value and branches, and would be allowed to, for example, recurse on the structure of the tree; in the latter case, all that the client would "know" is that your class supports some form of put, get and delete operations, but it's not allowed to rely on the fact that this is stored as a search tree. In many variants of the latter case you indeed would use a Tree type as a front end to hide the nodes from the clients. (For example, Java's built-in java.util.TreeMap class does this.)
So the shortest answer is, really, it depends. The slightly longer answer is it depends on what the contract is between the binary tree implementation and its users; what things are the callers allowed to assume about the trees, what details of the binary tree are things that the author expects to be able to change in the future, etc.
"Is it for managing the entire set of Nodes?"
Yes.
"Does it simply contain the functions necessary to insert, remove and search for specific Nodes?"
Basically, yes. For that reason, it should contain at least a reference to the root node.

Java: implementing MutableTreeNode, remove similar old methods?

I'm getting closer to fully implementing a JTree to represent a collection of Series.
The hierarchy is Show > Season > Episode.
These are all classes and each one of them implements the MutableTreeNode interface.
When starting this project I didn't know that I was going to need this interface, so I defined methods like 'removeFromSeason' in Episode, 'add(Episode ep)' in Season,..
Now that I'm implementing this MutableTreeNode interface I see that many methods overlap.
So I'm wondering how I should handle this. For example: the add(Episode ep) in just takes an Episode as argument, while the 'insert(MutableTreeNode child, int index)' uses 2 arguments, the child and the index. In the add episode I just added the episode to the ArrayList at a random position. Each Episodes has a variable containing the number of the Episode so that wasn't a problem.
If I fully replace the add Method, I should also be giving the index of the Episode, which could complicate the ArrayList. Or I would be doing double work, passing the episode and the episode.getNumber() as arguments, which seems stupid to me.
I could also keep both the original methods and the new ones, and let the one call the other. This would doesn't really seem right to me.
What are your opinions on how to handle this? Any comment is appreciated :)
Harm
When I want to implement a tree, I provide an implementation of TreeModel and I do all the tree handling in it. I never implement TreeNode or MutableTreeNode (A node doesn't need to implement any interface). This frees the business objects from UI concerns. Of course, the TreeModel must be somehow notified when changes happen.

Existing implementations of Trees in Java?

I'm looking for any implementation of a pure Tree data structure for Java (that aren't graphical ones in java.awt), preferably generic.
With a generic tree I'd like to add elements that are not supposed to be sorted and do something like this:
TreeNode anotherNode = new TreeNode();
node.add(anotherNode);
…and then I'd like to traverse the nodes (so that I can save and preserve the structure in a file when I load the tree from the same file again).
Anyone knows what implementations exist or have any other idea to achieve this?
You can use the DefaultMutableTreeNode defined in the javax.swing.tree package. It contains methods getUserObject() and setUserObject(Object) allowing you to attach data to each tree node. It allows an arbitrary number of child nodes for each parent and provides methods for iterating over the tree in a breadth-first or depth-first fashion (breadthFirstEnumeration() / depthFirstEnumeration()).
Also note that despite being resident in the javax.swing.tree package this class does not contain any UI code; It is merely the underlying model of JTree.
Scala has a nice Tree data structure. It's a "General Balanced Tree." It's not exactly Java, but it's close, and can serve as a good model.
It is hard to believe, given how much is in the base Java libraries, but there is no good generic Tree structure.
For a start, the TreeSet and TreeMap in the runtime are red-black-tree implementations.
Assuming you don't want to store arbitrary Java objects on the nodes, you could use the W3C DOM. It even comes with its own serialization format (I forget what it's called :-).

Categories