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.
}
}
Related
In order to practice data structures I'm implementing my own library of Trees. I've begun with BST and in following I'm about to implement AVL Tree, Red-Black Tree and maybe more. AVL & RBT are BST trees as well, so some class hierarchy is rather obvious. The problem I came into is that all those trees have other types of Nodes - AvlNode has balance factor flag, RgbNode has color flag, BstNode doesn't need any additional info (despite of references to parent, children and value which all Nodes need). So I've a hierarchy of Nodes and a hierarchy of Trees. I could give some flag attribute to BstNode and use it in extending classes but it is surely not a good way to do it.
The problem is how to deal with the fact that for example Bst.findNode() will return BstNode but in Avl I need AvlNode despite the findNode() methods will be the same in both (apart of return type).
I need help with planning the hierarchies or if those parallel hierarchies (as a code smell) are in general a bad idea, I need a workaround because I have no clue how to do it in proper way.
BstTree Class:
public class BstTree<T extends Comparable> implements Iterable
{
private BstNode<T> root;
public void addValue(T value)
{
BstNode node = new BstNode(value);
addNode(node);
}
public void addNode(BstNode<T> node)
{
...
}
public boolean removeNode(T value)
{
...
}
public BstNode findNode(T value)
{
...
}
//other less significant methods
}
BstNode class:
public class BstNode<T extends Comparable>
{
private static int lastId = 0;
private int id;
private T value;
private BstNode parent = null;
private BstNode leftChild = null;
private BstNode rightChild = null;
public BstNode(T value) {
this.id = ++lastId;
this.value = value;
}
public boolean isGreaterThan(BstNode n)
{
//...
}
public boolean hasLeftChild()
{
//...
}
public boolean hasRightChild()
{
//...
}
public boolean hasParent()
{
//...
}
public boolean isLeaf()
{
//...
}
public boolean hasOnlyOneChild()
{
//...
}
public BstNode getOnlyChild(BstNode node)
{
...
}
public boolean isLeftChildren()
{
...
}
public BstNode getConsequentNode()
{
...
}
}
I can guess that the separation of responsibilities above may not be perfect, if it's wrong then I might get some of the methods from Node to Tree class but this thing is not a big problem.
I would do something like this:
public abstract class BstTree<T extends Comparable,N extends BstNode<T,N>> {
private N root;
...
public void addValue(T value)
{
N node = newNode(value);
addNode(node);
}
public abstract N newNode(T value);
public void addNode(N node)
{
// ...
}
}
public class BstNode<T extends Comparable,N extends BstNode<T,N>>
{
private T value;
private N parent = null;
private N leftChild = null;
private N rightChild = null;
public BstNode(T value) {
this.value = value;
}
public N getOnlyChild(N node)
{
// ...
}
...
}
public class AVLTree<T extends Comparable> extends BstTree<T,AVLNode<T>> {
...
#Override
public AVLNode<T> newNode(T value) {
return new AVLNode<>(value);
}
}
public class AVLNode<T extends Comparable> extends BstNode<T,AVLNode<T>> {
...
public AVLNode(T value) {
super(value);
}
#Override
public AVLNode<T> getOnlyChild(AVLNode<T> node) {
return super.getOnlyChild(node);
}
...
}
I have a database table with parent child relationship and any parent can have any number of children but there will only be 1 parent at the root level. Data looks like below:
TagID ParentTagID TagName
-------------------------------
1 null a
2 1 b
3 1 c
4 1 d
5 2 e
6 4 f
7 2 g
I want to fetch the records in java in a tree format. Although I can achieve this at SQL level itself using the below SQL but I want to extract the data from database as it is and perform the processing at java level so that the connection between java and SQL could be of minimum duration to avoid any latency from database side.
with cte as
(
select * from TagValue
where ParentTagID is null
union all
select s.* from TagValue s
join cte c on s.ParentTagID = c.TagID
)
select * from cte
Using Java with taking help from other useful links, I have created a tree as per below:
public class MyTreeNode<T> {
private T data = null;
private List<MyTreeNode<T>> children = new ArrayList<MyTreeNode<T>>();
private MyTreeNode<T> parent = null;
public MyTreeNode(T data) {
this.data = data;
}
public void addChild(MyTreeNode<T> child) {
child.setParent(this);
this.children.add(child);
}
public void addChild(T data) {
MyTreeNode<T> newChild = new MyTreeNode<T>(data);
newChild.setParent(this);
children.add(newChild);
}
public void addChildren(List<MyTreeNode<T>> children) {
for (MyTreeNode<T> t : children) {
t.setParent(this);
}
this.children.addAll(children);
}
public List<MyTreeNode<T>> getChildren() {
return children;
}
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
private void setParent(MyTreeNode<T> parent) {
this.parent = parent;
}
public MyTreeNode<T> getParent() {
return parent;
}
}
While inserting objects in this tree, I can use the below code:
MyTreeNode<Integer> root = new MyTreeNode<Integer>(1);
MyTreeNode<Integer> child1 = new MyTreeNode<Integer>(2);
child1.addChild(3);
child1.addChild(4);
MyTreeNode<Integer> child2 = new MyTreeNode<Integer>(5);
child2.addChild(6);
root.addChild(child1);
root.addChild(child2);
root.addChild(7);
root.addChildren(Arrays.asList(new MyTreeNode<Integer>(8),
new MyTreeNode<Integer>(9), new MyTreeNode<Integer>(10)));
But this is a static code whereas the number of tags could be dynamic. I need a recursive solution to find a node based on ParentTag value and then insert the new tag as its child. Is there a recursive solution to do this? If there is any other out of the box data structure in Java 1.8 to perform this operation, that would also be useful.
Given a ResultSet, you would like to build your tree structure naturally, as follows:
while (... has more rows ...) {
addNode(rs.ParentTagID, rs.TagID);
You need some type of container to store your tree nodes in. You could use a List however the performance will suffer when building the tree; adding a child requires finding its parent, and a list offers no quick way to do this. A Map
however provides O(1) lookup.
The helper method addNode will keep the tree in tact: Find the parent, and add the child accordingly.
In summary the dynamic approach you are looking for is to iterate the result set, and repeatedly call addNode() passing both the parentId and childId (which is stored in the database). The root node is a special case (where parentId = null or 0) and is handled by addNode().
There was a slight modification to MyTreeNode to return the object (when adding a child); it used to be of type void.
Here is some sample code showing this approach.
public class MutipleTreeNode {
static Map<Integer, MyTreeNode<Integer>> nodeMap = new HashMap<>();
public static void main(String[] args) {
// Here you would process your result set
// Rather than simulate a result set, I just build some nodes manually
addNode(0, 1); // Root
addNode(1, 2);
addNode(1, 3);
addNode(1, 4);
addNode(2, 5);
addNode(2, 7);
addNode(4, 6);
printTree();
}
private static void printTree() {
for (MyTreeNode<Integer> node : nodeMap.values()) {
if (node.getParent() == null)
System.out.print("Root node: ");
System.out.println(node.getData()+"; children="+node.getChildren());
}
}
private static void addNode(int parentId, int childId) {
MyTreeNode<Integer> childNode, parentNode;
if (nodeMap.isEmpty())
childNode = new MyTreeNode<Integer>(childId);
else {
parentNode = nodeMap.get(parentId);
childNode = parentNode.addChild(childId);
}
nodeMap.put(childId, childNode);
}
public static class MyTreeNode<T> {
private T data = null;
private List<MyTreeNode<T>> children = new ArrayList<MyTreeNode<T>>();
private MyTreeNode<T> parent = null;
public MyTreeNode(T data) {
this.data = data;
}
public void addChild(MyTreeNode<T> child) {
child.setParent(this);
this.children.add(child);
}
public MyTreeNode<T> addChild(T data) {
MyTreeNode<T> newChild = new MyTreeNode<T>(data);
newChild.setParent(this);
children.add(newChild);
return newChild;
}
public void addChildren(List<MyTreeNode<T>> children) {
for (MyTreeNode<T> t : children) {
t.setParent(this);
}
this.children.addAll(children);
}
public List<MyTreeNode<T>> getChildren() {
return children;
}
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
private void setParent(MyTreeNode<T> parent) {
this.parent = parent;
}
public MyTreeNode<T> getParent() {
return parent;
}
#Override
public String toString() {
return "[data=" + data + "]";
}
}
}
Creates the output:
Root node: 1; children=[[data=2], [data=3], [data=4]]
2; children=[[data=5], [data=7]]
3; children=[]
4; children=[[data=6]]
5; children=[]
6; children=[]
7; children=[]
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 want to create a tree that detect if the insert is a Object of type Characters it will compare each one and decide where to insert [ right or left ],( i know it can detect by position in ascii table) ,and if the insert is an object of int it will do the same operation.
My Questions:
1. I need to create the tree and on the same time to set a compartor ( for example if its a tree of Chars it will be a Chars_comperator that checks Chars and he implements Comparator ( of java ).?
2. My code now is good for int only. becuase i take the object convert to string and then to int and after all this i compare and decide where to insert, this is how i need to do it? or there is another way to do it that can take care all of kinds of Objects?
Here is my code and how i create the tree,
Tree class
public class tree {
bNode root;
public tree() {
this.root = null;
}
public boolean isEmpty(){
return root==null;
}
public void insert(Object data)
{
if(isEmpty())
this.root = new bNode(data);
else
this.root.insert(data);
}
}
bNode Class
public class bNode {
protected Object data;
protected bNode left;
protected bNode right;
public bNode(Object data) {
this.data = data;
this.left = null;
this.right = null;
}
public void insert(Object data){
if(Integer.parseInt(data.toString())<Integer.parseInt(this.data.toString())){
if(this.left==null)
this.left = new bNode(data);
else
this.left.insert(data);
}
else{
if(this.right==null)
this.right = new bNode(data);
else
this.right.insert(data);
}
}
Main class
public class Main {
/**
* #param args
*/
public static void main(String[] args) {
tree x = new tree();
char a = 'G';
x.insert(a);
x.insert(60);
x.insert(40);
x.insert(30);
x.insert(59);
x.insert(61);
x.root.printTree(x.root);
}
}
Thanks!
instead of passing an Object, you could pass a Comparable in insert().
Standard type like Integer, String, etc. already implement the Conparable interface.
instead of using if (a <b) you call
compareTo(a,b);
See java doc of Comparable.
If, for any reason, you want to stay with Passing an Object to insert(), you also can solve that by not using toString, but by checking the class of object, and then casting:
if (object instanceof Integer) {
int val = ((Integer) object).intValue();
// now compare
} else if (object instance of String) {
String val .....
// use val.compareTo()
}
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.