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
}
Related
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 need to pass an object (for example object from Class DATA) which is within another object (for example object from Class NODE) to another object (from class NODE)?
The Node objects are nodes of a tree. The tree implementation is :
public class Tree {
private Node rootElement;
public Tree() {
super();
}
public Node getRootElement() {
return this.rootElement;
}
public void setRootElement(Node rootElement) {
this.rootElement = rootElement;
}
and then for Node I have:
public class Node {
public MyNode data;
public List<Node> children;
public int childNo;
public Node() {
super();
}
public Node(MyNode data) {
this();
setData(data);
}
public Node(MyNode data, int childNo) {
this();
setData(data);
this.childNo=childNo;
}
public void setChildren(List<Node> children) {
this.children = children;
}
public void addChild(Node child) {
if (children == null) {
children = new ArrayList<Node>();
}
children.add(child);
}
public MyNode getData() {
return this.data;
}
public void setData(MyNode data) {
this.data = data;
}
and for Mynode I have :
public class MyNode {
public String ID = new String(); //UUID
protected String parentID;
MyNodesDATA d = new MyNodesDATA();
public MyNode() {
setID(UUID.randomUUID().toString());
}
public MyNodesDATA getMyNodesDATA () {
return this.MyNodesDATA ;
}
public void setData(MyNodesDATA d) {
this.MyNodesDATA = data;
}
and this is MyNodesDATA
public class MyNodesDATA {
int iD;
String name;
}
So each node of the tree has an object of MyNode Type and each MyNode Object has a data as an object from MyNodesDATA class. I have already initialised the tree with a predefined structures of hierarchical nodes using some recursive methods which I didn't put here ...
Now, nodes of the tree in lover levels process their data and need to send them to their parents (USING THEIR PARENT ID). I stuck here... how a node (an object) can send it's data to another node (another object) (let say its parent in this scenario) using only one ID variable of the other object ... in a simpler way I need a method to get (ID and DATA) and send the data to the object which has the ID !! and of course there should be another function or event handler in receiver side to take action once receives a Data ....
In your example, Node does not have an object of DATA within it; you've simply initialised one in the constructor then allowed it to go out of scope. You also need to modify your constructor if you want to pass in a DATA object, so change Node to be:
public class Node {
int iD;
DATA d;
public Node(){
d = new DATA();
}
public Node(DATA d){
this.d = d;
}
}
so that you have the DATA instance stored. Then simply provide a getter, e.g.:
public DATA getData() {
return d;
}
and then you can do:
public class MAIN {
public static void main(String[] args) {
Node node1 = new Node();
Node node2 = new Node(node1.getData());
}
}
First of all, you probably want to make the DATA instance created in the Node constructor an instance member. Otherwise it can be released by the garbage collector once the constructor is done.
Then can either pass the DATA parameter to a constructor of Node, or you can have a setter method that would accept a DATA parameter.
public class Node {
int iD;
private DATA d;
public Node(){
this.d = new DATA(); // or this(new DATA());
}
public Node(DATA d){
this.d = d;
}
public void setData (DATA d) {
this.d = d;
}
public DATA getData() {
return this.d;
}
}
Now you have several options for 2 Node instances to share the DATA member :
public class MAIN {
public static void main(String[] args) {
DATA data = new DATA();
Node node1 = new Node(data);
Node node2 = new Node(data);
}
}
or
public class MAIN {
public static void main(String[] args) {
Node node1 = new Node();
Node node2 = new Node(node1.getData());
}
}
or
public class MAIN {
public static void main(String[] args) {
Node node1 = new Node();
Node node2 = new Node(null);
node2.setData (node1.getData());
}
}
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)
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.
I'm trying to make my own tree class but keep getting horribly confused. Basically I'm trying to make a weighted tree. I've made the following node class:
import java.util.*;
public class subdivNode {
private int nodevalue;
private int nodeID;
private List<subdivNode> childnodes;
public subdivNode(int value, int id){
nodevalue = value;
nodeID = id;
}
public int getValue(){
return nodevalue;
}
public int getId(){
return nodeID;
}
public void addChild(subdivNode child){
childnodes.add(child);
}
public int getNumChildren(){
return childnodes.size();
}
public subdivNode getChild(int pos){ //return's i'th child
return childnodes.get(pos);
}
}
And this is the skeleton for my tree class so far:
public class subdivTree {
private subdivNode rootnode;
public subdivTree(){
rootnode = new subdivNode(0,0);
}
public void addNode(int parent, int value){
}
public int getNodeValue(int node){
return 0;
}
public int getNumChildren(int node){
return 0;
}
}
Beyond that I have no idea
EDIT: Sorry for the ambiguity. My question should have been how would I go about implementing the addnode method in subdivTree. The end goal is to create an alogrithim which searches the tree for the path between any two nodes such that the greatest value(adding the value of all the in between nodes) is obtained.
Before working on addNode, tell us how getNodeValue(int node) is going to work.
You have a rootNode, what method of that are you going call with that "node" value?
I'm not sure, but I think that your interface is broken. I think your concepts of get by position and get by Id are confused.
Draw a picture of the data structure you expect.