In the first three parts of this lab, we will be creating our own implementation of the general tree data structure to better understand its implementation and behavior.
Unlike for Labs 3 and 4 that implemented different versions of the List ADT, Java does not provide an interface or abstract class that represents a tree. Thus, we will build the general tree data structure entirely from scratch following the descriptions we used in lecture. We’ll again be using generics for the implementation so that the tree can store any type of data as elements.
ReadMe
In Visual Studio Code, create a new file in your GitHub repository called MyTreeNode.java
. Within this file, you should create a new class called MyTreeNode<T>
that does not have any inheritance. Recall that throughout the semester, we are including the prefix My
in your class name to reference our own implementations of the data structures.
ReadMe
As you are implementing your solutions, do not forget to include documentation using Javadocs! This is important practice to get into the habit of, and it will be a small portion of your solution grade for the remainder of the semester.
Your MyTreeNode<T>
inner class should have three private instance variables:
item
: the item of type T
that is stored by the tree nodeparent
: the parent MyTreeNode<T>
of this tree node (which will be null
for the root node)children
: a List
of children MyTreeNode<T>
All of the instance variables should be private so that their access (especially assigning values) can be controlled through the MyTreeNode
class.
The MyTreeNode
class should have two constructors:
item
to store in the node and a parent MyTreeNode
to save as the parent
of the new node. The children
should be a new empty ArrayList
.item
to store in the node. This constructor should call the other constructor, instead of duplicating its work.Hint
Recall that we had one constructor call another in Lab 3, if you need a refresher of how that process works.
ReadMe
Only the second constructor is public because outside of this class, a developer can only make new root nodes for trees. Non-root children should only be created through the addChild
method that we will develop below, which will call the first private constructor.
Since we made our instance variables private, we can add “getter” methods in order to still be able to retrieve values from outside of the class. You should add three such methods:
public T getItem()
, which returns the value of the item
instance variablepublic MyTreeNode<T> getParent()
, which returns the value of the parent
instance variablepublic List<MyTreeNode<T>> getChildren()
, which returns a deep copy of the children
instance variableReadMe
If we were to simply return the List
stored as the children
instance variable, it could be modified outside of the class (by adding or removing child MyTreeNode<T>
objects), which would defeat the purpose of making the instance variable private in the first place. We can make a deep copy by using the code:
List<MyTreeNode<T>> childrenCopy = new ArrayList<MyTreeNode<T>>(this.children);
which will contain all the same children nodes, but if someone were to try to add or remove nodes from the returned list, it would be different from and therefore not affect the list stored in this.children
.
The last method we will implement in this part of the lab allows us to add children to a given MyTreeNode<T>
so that we can start to build up the structure. You should implement a public method called addChild
that:
item
of type T
to add to the treeMyTreeNode<T>
storing the given item and the current node (i.e., this
) as its parent by using the first (private) constructorchildren
Before moving on to the next part of the lab, we should create unit tests to verify our implementation so far and help us find and remove any bugs. As in previous labs, we can create a Java file that will contain our unit tests by right clicking anywhere in the MyTreeNode.java
file and selecting “Source Action” from the right click menu. Then, select “Generate Tests”. Use the default name proposed by the IDE of MyTreeNodeTest
. Next, it will prompt you with what methods you want to create tests for. Select the getItem
method for now.
Inside the newly created MyTreeNodeTest.java
file, create unit tests verifying:
getItem
method works properlyaddChild
method works properlygetParent
method works properly (e.g., after calling addChild
, the returned node has the correct parent)getChildren
method works properly (e.g., after calling addChild
, the list returned by getChildren
contains the correct number of children)Don’t forget to frequently save your progress periodically to GitHub using the add
, commit
, and push
commands with git.