Please find a Tree class definition below.
public class Tree<T>{
private T head;
private List<Tree<T>> leafs = new ArrayList<>();
private Tree<T> parent = null;
private Map<T, Tree<T>> locate = new HashMap<>();
public Tree(T head) {
this.head = head;
locate.put(head, this);
}
public void addLeaf(T root, T leaf) {
if (locate.containsKey(root)) {
locate.get(root).addLeaf(leaf);
} else {
addLeaf(root).addLeaf(leaf);
}
}
public Tree<T> addLeaf(T leaf) {
Tree<T> t = new Tree<>(leaf);
leafs.add(t);
t.parent = this;
t.locate = this.locate;
locate.put(leaf, t);
return t;
}
}
The Tree class object is created in another class and nodes are added in a straightforward way (using the addLeaf(node) function). This process builds the tree alright. Would someone be able to suggest a DFS function implementation on the constructed tree adhering to the above class definition?
Thank you.
This is what I've tried. Yes, it gives me meaningless results.
protected void DFS() {
for(Tree<T> child : leafs) {
DFS();
System.out.println(child);
}
}
The code is from the third comment at link
protected void DFS() {
for(Tree<T> child : leafs) {
child.DFS();
System.out.println(child.head);
}
}
resolved!
You're close. The print should be the value of the node, and the recursion should be on the child.
Related
My goal is to create a tree-like object structure.
For this i created a class named Node (I removed the implementation because the problem still persists without it):
public class Node<S> {
public Node<S> addChild(Node<S> node) {
return this;
}
}
Important to know is that i want to define the generic type S only in the root node, all child nodes should automatically inherit from the root node.
Something like this:
new Node<String>().addChild(
new Node<>().addChild(
new Node<>()
)
)
I restricted the addChild method to only accept Nodes with the same generic type S,
so as far as i know my child node should know that it's generic type S has to be (in this example) String. However it seems like the generic type S gets lost after instantiating a new Node, because it gives me the following Exception:
error: incompatible types: Node<Object> cannot be converted to Node<String>
The use of <> requires type inference, and the argument of the first
addChild must be a Node, and just passing new Node<>() would do - infering from the return type.
But chaining to .addChild(new Node<>()) cannot infer anything, can only provide Node<Object>. So: one cannot use <>.
The problem is (of course) that you want addChild to return the head of the list, and keep adding to the tail of the list.
Normal practice is not to create Node instances, but just use the S values.
public class Node<S> {
private S value;
private Node<S> next;
public Node(S value) {
this.value = value;
}
public static <T> void print(Node<T> root) {
if (root == null) {
System.out.println("empty");
return;
}
System.out.print(root.value);
System.out.print(" --> ");
print(root.next);
}
public static <T> Node<T> addAll(T... values) {
Node<T> root = null;
Node<T> previous = null;
for (T value : values) {
Node<T> current = new Node<>(value);
if (root == null) {
root = current;
} else {
previous.next = current;
}
previous = current;
}
return root;
}
public static void main(String[] args) {
Node<String> root = Node.addAll("a", "b", "c", "d");
print(root);
}
}
Comparable to Collections.addAll or List.of. If you keep a Node<S> last field, you could indeed create something like:
public void addLast(S value) {
last.next = new Node<>(value);
}
This also shows a serious problem of the class: an empty list is not a Node.
One could use Optional<Node<S>> or a special constant for an empty list EMPTY - without value.
The normal solution is to have a container:
public class List<S> {
private class Node {
...
}
private Node<S> root;
private Node<S> last;
private int size;
public List<S> addLast(S value) {
Node<S> current = new Node<>(value);
if (root == null) {
root = current;
last = current;
} else {
last.next = current;
}
last = current;
++size;
return this;
}
private int size() {
return size;
}
...
}
Now everything fits.
List<String> nodes = new List<>()
.addLast("a")
.addLast("b")
.addLast("c")
.addLast("d");
After feedback, when wanting Node references.
Then discard chaining, and make Node public again.
public Node<S> addLast() {
addLast(null);
}
public Node<S> addLast(S value) {
Node<S> current = new Node<>(value);
if (root == null) {
root = current;
last = current;
} else {
last.next = current;
}
last = current;
++size;
return last;
}
List<String> nodes = new List<>()
Node<String> a = nodes.addLast();
Node<String> b = nodes.addLast();
var c = nodes.addLast();
var d = nodes.addLast();
One could use var for shortness.
What you are trying to do is something like this
public class Node<T> {
private Node<T> child;
private T data = null;
public Node (T data) {
this.data = data;
}
public T getData() {
return data;
}
public Node<T> getChild() {
return child;
}
public void addChild(Node<T> child) {
this.child = child;
}
#Override
public String toString() {
return "this node's data: " + data + "; has child? " + (child != null);
}
public static void main(String[] args) {
Node<String> root = new Node<> ("parent");
Node<String> child = new Node<>("child");
root.addChild(child);
System.out.println(root);
System.out.println(child);
}
}
If you were to execute this, it will output
this node's data: parent; has child? true
this node's data: child; has child? false
this node's data: 0; has child? false
this node's data: 1; has child? false
Notice how I can create nodes of type String and Integer. However, this class is incomplete if you want to create a tree structure. The implementation of "tree" will depend on what kind of tree you are talking about. For example, a simple binary tree will have two children at most. Other types of trees could have more children. Also, adding nodes to a tree might require balancing the tree.
Now, to your question, this answer suffices. I was able to demonstrate the use of generics to create Node objects of type T.
I have a class structure something like this:
interface Composite {}
class Leaf implements Composite { public String val; }
class Node implements Composite {
private Node parent;
private Composite left;
private Composite right;
public void attachLeft(Composite c) {
left = c;
}
public void attachRight(Composite c) {
right = c;
}
public void attachLeft(Node n) {
left = n;
n.parent = this;
}
public void attachRight(Node n) {
right = n;
n.parent = this;
}
public void attachRandomly(Composite c) {
if ( ThreadLocalRandom.current().nextBoolean() ) {
attachRight(c);
} else {
attachLeft(c);
}
}
}
I have a method that generates a random tree (pseudocode):
// build tree
for some number of nodes :
make newNode
oldNode = randomly pick an existing node with an empty right/left
oldNode.attachRandomly(newNode)
// fill leaves of tree
for each node with empty right/left :
while node has empty right/left :
node.attachRandomly(new Leaf)
Unfortunately, because of static binding, the attachLeft/Right(Node c) methods never get called by attachRandomly. (attachRandomly is getting a Composite, so the Composite version of attachLeft/Right always gets called.) So my parent attribute is never getting set.
Now, I can think of a couple ways to make this work:
Remove the Node version of attachLeft/Right and just use instanceof and casting inside of the Composite version
Add a Node-specific version of attachRandomly
Option 1 feels yucky (instanceof! casting!) and option 2 just feels awkward because of the amount of extra code. Is there no better way to do this so that polymorphism can kick in and help me out here?
You could write it like this. This basic idea is called double dispatching. It introduces a new level of dispatching to each of your method calls, to allow dynamic binding to be used.
interface Composite {
void attachToLeft(Node newParent);
void attachToRight(Node newParent);
}
class Leaf implements Composite {
public String val;
#Override
public void attachToLeft(Node newParent) {
newParent.left = this;
}
#Override
public void attachToRight(Node newParent) {
newParent.right = this;
}
}
class Node implements Composite {
private Node parent;
private Composite left;
private Composite right;
public void attachLeft(Composite c) {
c.attachToLeft(this);
}
public void attachRight(Composite c) {
c.attachToRight(this);
}
#Override
public void attachToLeft(Node newParent) {
this.parent = newParent;
newParent.left = this;
}
#Override
public void attachToRight(Node newParent) {
this.parent = newParent;
newParent.right = this.
}
}
I've come up with the following as an attempt to create a general tree in java:
import java.util.*;
public class GeneralNode<T>{
private T data = null;
private Vector<GeneralNode<T>> children =
new Vector<GeneralNode<T>>();
public GeneralNode(){
this(null);
}
public GeneralNode(T d){
data = d;
}
public Vector<GeneralNode<T>> getChildren(){
return children;
}
public void addChild(T d){
GeneralNode<T> c = new GeneralNode<T>(d);
this.children.add(c);
}
public void addChild(GeneralNode<T> c){
this.children.add(c);
}
public T getData(){
return data;
}
public void setData(T newData){
data = newData;
}
public boolean isLeaf(){
return(children.isEmpty());
}
public Vector getChildrenData(){
Vector<T> result = new Vector<T>();
for(int i = 0; i < children.size(); i++)
result.add(children.elementAt(i).getData());
return result;
}
}
This works great for storing information. It allows me to create a node and insert more nodes in that node, along with having one type of information in each node. Unfortunately, it seems like I can't reference a "parent" node with this class. Essentially, I'm nesting vectors within vectors, so I can't actually reference the node holding the node.
I'm sure I have to make a separate GeneralTree class in order to get this done, but I'm not sure how I'd go about doing so. I had the idea of assigning the root as a GeneralNode, and having a "previous" and "next" node as being the parent and children respectively. This is what I've come up with so far:
import java.util.*;
public class GeneralTree<T>{
private GeneralNode<T> root;
private GeneralNode<T> parent;
private GeneralNode<T> children;
public GeneralTree(){
this(null);
}
public GeneralTree(T d){
this(d, null);
}
/* I don't know what to do here. I want
* to assign a parent node to every
* tree I make, but if I keep the
* second parameter as GeneralNode<T>, wouldn't
* that mean I could only ever have one GeneralTree?
*/
public GeneralTree(T d, GeneralNode<T> p){
root = new GeneralNode<T>(d);
parent = p;
}
}
I've written comments on the constructor I'm confused on. I hope I've explained my problem well enough. If anyone can help me with this that'd be great.
As #JohnBollinger said, you can keep a reference of parent node inside each nodes. If you do that you must set parent nodes inside addChild methods.
import java.util.Vector;
public class GeneralNode<T>{
private T data = null;
private Vector<GeneralNode<T>> children =
new Vector<GeneralNode<T>>();
private GeneralNode<T> parentNode;
//constructors
private void setParent(GeneralNode<T> parentNode) {
this.parentNode = parentNode;
}
public void addChild(T d){
GeneralNode<T> c = new GeneralNode<T>(d);
c.setParent(this);
this.children.add(c);
}
public void addChild(GeneralNode<T> c){
c.setParent(this);
this.children.add(c);
}
//other methods
}
I wrote a java Node class. It has the basics.
public class Node{
PuzzleState ps;
Node child;
public Node(PuzzleState ps){
this.ps = ps;
}
public PuzzleState getState(){
return this.ps;
}
public void setChild(Node n){
this.child = n;
}
public Node getChild(){
return this.child;
}
}
I created a new Node like this:
Node up = new Node(puzzle);
This will change all my other nodes to have all the characteristics of Node up. Please help me. I think I may be using the modifiers wrong (i.e. private, public, static)
I created a BST that sets each node to a String value, I was wondering if there is a way to search through the tree but just one value at a time. So say the String in a node was "truck" is there a way to search through the tree and return "t"? This is the code I have for building the tree:
public class BinaryTree {
public Node root;
public BinaryTree tree;
public static int pos;
public static Node[] theArray;
private static class Node {
Node left;
Node right;
String data;
Node(String s) {
left = null;
right = null;
data = s;
}
}
public BinaryTree plantTree(ArrayList<String> dict) {
tree = new BinaryTree();
Collections.shuffle(dict);
for (String s : dict) {
s.toUpperCase();
tree.add(s);
}
return tree;
}
/**
* Creates an empty binary tree
*/
public BinaryTree() {
root = null;
}
public void add(String data) {
root = add(root, data);
}
private Node add(Node node, String data) {
if (node == null) {
node = new Node(data);
} else {
if (data.compareTo(node.data) > 0) {
node.left = add(node.left, data);
} else {
node.right = add(node.right, data);
}
}
return (node);
}
}
Maybe I misunderstood your question, but it sounds like you want something to iterate through the tree. I would use the visitor pattern. (This sounds like homework anyways, so why not use standard patterns. :))
public class Node<T>{
...
public void visitDepthFirst(Visitor<T> v){
v.visit(this);
if (left != null){
left.visitDepthFirst(v);
}
if (right != null){
right.visitDepthFirst(v);
}
}
}
interface Visitor<T>{
public void visit(T t);
}
...
Node<String> root = ...;
root.visitDepthFirst(new Visitor<String>(){
public visit(String val){
if ("truck".equals(val)){
// do something
}
}
});
I'll let you figure out breadth search. Also, your node class would be more usable using generics. And your class structure is a bit confusing. Might I suggest you just use node AS the tree itself. After all, every node in a tree, is a tree itself. (read about the composite pattern)
So it appears that your trying to search through your tree by the first letter only. This will take just as long as returning the entire word. So you still have to use a BST traversal or search algorithem.
So say the String in a node was "truck" is there a way to search
through the tree and return "t"?
Really, I have no idea what this question is about.
If you have a BST then you search it using binary search. That's that.
A binary search returns true if the element is found. You can implement your own BST and not return a boolean but a Char as in t in your question and null if the value is not part of the tree.