im coming from c++ to java and i am confused on binary trees with java. is the only way to have a Node class is to make it an inner static class? all the examples i see do this. However, the way im doing it is i have a node class and a binarytree class uses this node class. but i keep getting an error when i try inserting into the tree after the second insert. i get an exception at this line if(dataIn <= nodeIn.getLeft().getData()){
I am confused as to what i did wrong.... here is my code for insert that i have. thanks in advance..
public void insert(int dataIn){
root = insert(root, dataIn);
}
private Node insert(Node nodeIn, int dataIn){
if(nodeIn==null){
nodeIn = new Node(null, null, dataIn);
}else{
if(dataIn <= nodeIn.getLeft().getData()){
nodeIn.setLeft(insert(nodeIn.getLeft(), dataIn));
}else{
nodeIn.setRight(insert(nodeIn.getRight(), dataIn));
}
}
return nodeIn;
}
Part of the reason it's confusing is that "Node" should not be a parameter to the insert method, you should be calling an insert method defined in node.
So let's say you hold the "Root" node in your "normal code"--let's call it "rootNode" just to be obscure.
Okay, so your code to insert into the tree would be:
rootNode.insert(newValue);
Easy enough.
Now to define that method.
public class Node {
private int value;
private Node lower;
private Node higher;
public void insert(int newValue) {
if (newValue < value)
if(lower == null)
lower=new Node(value);
else
lower.insert(newValue);
else
if(higher == null)
higher=new Node(value);
else
higher.insert(newValue);
}
// and you'll need a constructor
public Node(int value) {
this.value=value;
}
}
This should read much more clearly. I'm going to hit "Post" then I'm going to edit it and figure out how to easily refractor that evil evil copy & paste code.
On second thought, I'll leave it there because it's more readable. The best fix I can see is to make the nodes an array, then you get:
public class Node {
private int value;
private Node[] nodes=new Node[2];
private final int LOWER=0;
private final int HIGHER=1;
public void insert(int newValue) {
int index=LOWER;
if (newValue > value)
index=HIGHER;
if(nodes[index] == null)
nodes[index]=new Node(value);
else
nodes[index].insert(newValue);
}
}
But I won't replace the original because, as I said, it's clearer.
I recommend the refactoring book for more of this. It really does help simplify your code once you really get OO. Passing an object to an otherwise static method (one that doesn't use member variables) is a dead give-away.
With more considerations about #ted's comment and OO--getLeft and getRight shouldn't even be an issue. Neither is necessary outside the abstraction.
In general what you probably need is these methods in Node:
public boolean doesContain(int value) {
if(value == this.value)
return true
else
return nodes[ this.value < value ? LOWER : HIGHER].doesContain(value);
}
and maybe
public void getValuesSorted(LinkedList l) {
nodes[LOWER].getValuesSorted(l);
l.put(value);
nodes[HIGHER].getValuesSorted(l);
}
Then you don't even need to expose that it's a tree you are dealing with--beter OO abstraction.
You need to test whether nodeIn.getLeft() == null.
is the only way to have a Node class is to make it an inner static class? all the examples i see do this.
No.
The Node class doesn't need to be an inner or nested class. (Strictly speaking a "static inner" class is a nested class.)
However, only an inner or nested class can be private. If your Node class is a regular class you are exposing implementation details to (at least) other classes in the same package. This is a bad idea ... and that explains why you see the Node class declared the way it is.
you can use the below code to clear your understanding. Mostly we do not use any other class everything can be done inside a single Node class itself. here is a very basic example which i believe might be helpful... Also when i see you have two methods in which you have only provided data rather than root. Trust me it is better to have root in your main class. reasoning we have it handy where ever we need to cache.
public Node insert(Node root, Node newNode) {
if (root == null) {
root = newNode;
} else {
if(root.data > newNode.data) {
root.left = insert(root.left, newNode);
} else {
root.right = insert(root.right, newNode);
}
}
return root;
}
directly call this method from any class where you have initialized. here is a sample plz check..
Node root = new Node(10);
root.insert(root, new Node(5));
root.insert(root, new Node(3));
root.insert(root, new Node(6));
root.insert(root, new Node(1));
Instead of:
if (dataIn <= nodeIn.getLeft().getData()) {
... you want:
if (dataIn < nodeIn.getData()) {
You need to compare the value that is to be inserted with the value at the current node.
I changed the <= sign to a < sign so that duplicates are avoided.
So your code refactored is:
public void insert(int dataIn) {
root = insert(root, dataIn);
}
private Node insert(Node nodeIn, int dataIn){
if (nodeIn == null) {
nodeIn = new Node(null, null, dataIn);
} else {
if (dataIn < nodeIn.getData()) {
nodeIn.setLeft(insert(nodeIn.getLeft(), dataIn));
} else {
nodeIn.setRight(insert(nodeIn.getRight(), dataIn));
}
}
return nodeIn;
}
Actually, for a binary tree there is no need to check whether the inserting element is either greater than or left than the parent node. I think there is no need of checking those conditions. We have to take the input from user whether to insert right or left.
public class TreeNode
{
private int data;
private TreeNode left;
private TreeNode right;
public Tree( )
{
data = 0;
left = null;
right = null;
}
public Tree( int initialInfo, TreeNode initialLeft, TreeNode initialRight )
{
data = initialInfo;
left = initialLeft;
right = initialRight;
}
public void setLeft( TreeNode newLeft )
{
left = newLeft;
}
public void setRight( TreeNode newRight )
{
right = newRight;
}
public void insert( int element )
{
if( element <= data )
{
if( left == null )
setLeft( new TreeNode( element, null, null ) );
else
left.insert( element );
}
else
{
if( right == null )
setRight( new TreeNode( element, null, null ) );
else
right.insert( element );
}
}
}
All your solutions do not take into accoount what would happen if the node was to be inserted in the middle of the tree. You are assuming that it will also be smallest or greatest. When you insert something in the middle of the tree, then you will realize that the operation becomes more complex.
Related
class LinkedList {
static Node head;
static class Node {
int data;
Node next;
Node(int d) {
data = d;
next = null;
}
}
public Node middleNode(Node head) {
Node s = head;
Node f = head;
while(f != null && f.next != null) {
s = s.next;
f = f.next.next;
}
return s;
}
public static void main(String[] args) {
LinkedList list = new LinkedList();
head = new Node(50);
head.next = new Node(20);
head.next.next = new Node(15);
head.next.next.next = new Node(4);
head.next.next.next.next = new Node(10);
I think I am here mistaking but I am not guessing what mistake it is
System.out.println("Middle Node: " +list.middleNode(head));
}
}
The output is coming like this, i dont know why. It should come 15 I think.
Middle Node: com.Sachin.LinkedList.IQ$Node#7b23ec81
To have the println() return a meaningful value you need to override Node::toString().
In example
class node {
...
#Override
public String toString() {
return data;
}
}
Unless you override toString, the function will return the standard String, meaning the result you've posted.
If you don't want to ovrride toString(), you can also specify that you want to print data:
System.out.println("Middle Node: " +list.middleNode(head).data);
Well, that is not really a good idea. Fileds usually are not accessible from outside the class. You should implement a function to read data instead, like
class Node{
...
public int getData() {
return data;
}
}
Then the output line would become:
System.out.println("Middle Node: " +list.middleNode(head).getData());
Overriding toString is usually a good idea when you want to print informations, because Java uses it a lot. Thus you want it to behave like you want.
Having the method getData() is also a good idea, reguardless the fact you override toString or not, because you can need it to access the data in functions.
i've to do write a code to solve this problem:
-Do the subtraction between two nodes p and q, where the substraction p - q is the list that contains all the elements that appear in p and not in q, knowing that p and q are ordered lists.
I tried to write a code and i know that it can't work...can you help me please to solve this problem? thank you very much!
class Node{
public int elem;
public Node next;
public Node(int elem, Node next){
this.elem = elem;
this.next = next;
}
}
public class Main{
public static Node diff(Node p, Node q){
if( p.elem == q.elem )
return diff(p.next, q.next);
else if(p.elem < q.elem){
return new Node (p.elem, diff(p.next, q.next));
else
return new Node(p.elem, diff(p.next, q.next));
}
public static void main(String[] args){
//.......
}
}
Your recursion never ends, since each return statement in your recursion method calls itself, which will lead your code to a Stack Overflow.
To solve this, you should decompose the problem.
First of all, let's find the base cases.
These are the cases where the recursion ends, and there's two for your problem:
If p == null, i.e. if the linked list contains no more items, then the work is done, there is nothing more to add to your result linked list.
if(p == null)
{
return null;
}
If q == null, then you should add all the remaining item in your linked list, i.e. the p node itself.
if(q == null)
{
return p;
}
There is 3 more possible cases, where recursion occurs:
If p.elem == q.elem then the node should not be added, and we should go to the next node for each linked list. Since the list are ordered, there is no way this node could be useful later.
if(p.elem == q.elem)
{
return diff(p.next, q.next);
}
If p.elem > q.elem the node might be useful, but we do not know yet. The next nodes of the second linked list might be equals, so we just skip to the next node for the second linked list.
if (p.elem > q.elem)
{
return diff(p, q.next);
}
There is only one case left, if p.elem < q.elem. This is it, we are sure that this node is absent from the second linked list, so we add a new node to our result.
return new Node(p.elem, diff(p.next, q);
Note that you do not need else statement in each case since there is a return in each of your cases.
Hope it helps!
When i add a node for example, named "Bob" in the insert method:
public void insert(String aLabel){
//left recursion:
if(this.getLabel().compareTo(aLabel) <= 0) {
if (childrenLeft == null) {
BSTreeNode aNode = new BSTreeNode(aLabel,this);
return;
}
else {
childrenLeft.insert(aLabel);
}
}
//right recursion
else {
if (childrenRight==null) {
BSTreeNode aNode = new BSTreeNode(aLabel,this);
return;
}
else{
childrenRight.insert(aLabel);
}
}
}
my tree only adds a blank node with no label on the left side of the treee only. is there something wrong with the (BSTreeNode aNode = new BSTreeNode;)? because when i hard code the nodes like:
BSTreeNode Louis = new BSTreeNode("Louis", treeRoot);
BSTreeNode bonny = new BSTreeNode( "bonny", treeRoot);
BSTreeNode Sue = new BSTreeNode("Anne", bonny);
BSTreeNode Sam = new BSTreeNode("Sam",Louis);
BSTreeNode Anne2 = new BSTreeNode( "delta", bonny);
BSTreeNode Frank = new BSTreeNode("Kalle", Louis);
the tree shows both a label and is inserted at the desired location.
other code-
the constructor:
public BSTreeNode( String aLabel,BSTreeNode aParent){
label = aLabel;
parent = aParent;
//add this node as a child of this node's parent either left or right
if(parent != null){
if(parent.getLabel().compareTo(label)<= 0) {
parent.addLeftChild(this);
}
if(parent.getLabel().compareTo(label)> 0) {
parent.addRightChild(this);
}
}
}
this is the constructor that adds the node to the parent when a node is created.
add childleft and right methods:
private void addLeftChild(BSTreeNode aNode){
if(childrenLeft == null) this.childrenLeft = aNode;
}
private void addRightChild(BSTreeNode aNode) {
if(childrenRight == null) this.childrenRight = aNode;
}
Most binary trees follow a different style, and set the parent's left/right child inside the recursive method, instead of the child going up and telling somebody it's their new parent
This code is a bit more standard for how most binary trees function:
public void insert(String aLabel)
{
if(getLabel().compareTo(aLabel) <= 0)
if(childrenLeft == null)
childrenLeft = new BSTreeNode(aLabel, this);
else
childrenLeft.insert(aLabel);
else
if(childrenRight == null)
childrenRight = new BSTreeNode(aLabel, this);
else
childrenRight.insert(aLabel);
}
That code should correctly save the values of the BSTreeNodes being created, and has the added effect of being less confusing as to how a parent is getting it's child
It makes a whole lot more sense to most people for a parent to be getting a child, instead of a child reaching up to a node and telling it that it's the new child on the block
You logic might be a little flawed.
When adding from your constructor, you're calling addLeftChild or addRightChild directly. These function check if the node on the right/left is null or not and adds the value if its null. But what if it's not null. It should then compare to the left/right child and continue because otherwise the nodes do not get added (i.e. the function falls through & doesn't return anything as its void).
I need to write a function to find previous/next leaf node that meet special condition from any node in a singly rooted tree. (in the parent first order)
The API would be something like this:
Node findNextLeafNode(Node currentNode, Condition condition);
Node findPretLeafNode(Node currentNode, Condition condition);
where currentNode is any node in a tree, and Node is defined as:
interface Node{
/** #return the Node's parent or null if Node is root */
Node getParent();
/** #return true if node is root */
boolean isRoot();
/** #return non-null array of child nodes (zero length for leaf nodes) */
Node[] getChildren();
/** #return the number of child nodes. If node is leaf, value is 0 */
int getChildCount();
}
And the Condition interface defines the semantics of checking a constraint against a given Node.
interface Condition{
/** #return true if provided node meets the condition */
boolean check(Node node);
}
My question:
Is there an existing library or algorithm for such a common scenario? I am open to either stack based or recursive algorithms. Pseudocode, links to open source libraries, or if you care to share you own code, would be appreciated.
(If not, I need to spend time to invent the same wheel again and paste it here later for sharing.)
Thanks.
-----------------------------write a method to getNext()........
// currentNode must be descendant of root
public static Node getNextNode(Node currentNode, Node root)
{
// 1. if is has child, next is its first child
if (currentNode.getChildSize() > 0) {
return currentNode.getChildren()[0];
}
// 2. if it has no child, check if its is the last child of his parent
else {
// if it is root and has no children, return null
if (currentNode == root) {
return null;
}
// else should have parent which is or under root;
Node parent = currentNode.getParent();
int index = getIndex(currentNode);
if (!isLastofParent(currentNode)) {
// ----a. if not last, next is his parent's next
return currentNode.getParent().getChildren()[index + 1];
}
else {
// ----b. if it is the last one, return its parent's next right if there is. while until root
Node tmp = parent;
while (tmp != root) {
int parentIndex = getIndex(tmp);
if (!isLastofParent(tmp)) {
return tmp.getParent().getChildren()[parentIndex + 1];
}
tmp = tmp.getParent();
}
}
}
return null;
}
private static boolean isLastofParent(Node node)
{
if (getIndex(node) == node.getParent().getChildSize() - 1) {
return true;
}
return false;
}
private static int getIndex(Node currentNode)
{
Node parent = currentNode.getParent();
for (int i = 0; i < parent.getChildSize(); i++) {
if (parent.getChildren()[i] == currentNode) {
return i;
}
}
//TODO: error condition handling, will not happen if tree not change
return -1;
}
------------------------a full search is much easier............
public static Node getNextFailNode(Node currentNode, Node root, Condition condition)
{
boolean foundCurrentNode = false;
Stack<Node> stack = new Stack<Node>();
stack.push(root);
while (!stack.isEmpty()) {
Node tmp = stack.pop();
System.out.println("-popup---------" +tmp+ " ");
if (foundCurrentNode && checkCondition(tmp, condition)) {
return tmp;
}
if (tmp == currentNode) {
foundCurrentNode = true;
}
if (tmp.getChildSize() > 0) {
for (int i = tmp.getChildSize() - 1; i >= 0; i--) {
stack.push(tmp.getChildren()[i]);
}
}
}
return null;
}
This maybe way overblown for what you need, but it can support what you want:
There is a graph traversal language: Gremlin. Typically bolted on top of something like Neo4j, but any graph data structure (e.g. a singly rooted directed tree) can be wrapped to support the API. Take a look at Blueprints projects to find out how it is done.
[edit: for something less heavy]
Perhaps JGraphT is what you want. Also take a look at this question on SO. It is not an exact duplicate, but you should find it helpful.
Write an iterator for your tree that can be initialized from any node and uses pre/in/post-order traversal (Of course it should be bi-directional).
This is basically writing one simple algorithm that at least to me seem basic.
Once you have an iterator all you need is to iterate your way to the next node which is a leaf and the condition holds for it.
If you have trouble with any specific part just ask and I'll improve my answer.
Based on the fact that you already have defined your interfaces, and you say the graph-traversal libraries are too heavyweight, you probably should just write it yourself. It would be an absolutely trivial amount of code. (This page contains some code if you need help.)
(One suggestion for your API: don't put a boolean isRoot(); method on Node, that's a waste of bits unless you have a very good reason to do so. The code that builds the tree should just refer to the root node.)
This is for homework but please know that I have looked online for help (such as http://www.sethi.org/classes/class_stuff/cis435/others/notes-java/data/collections/lists/simple-linked-list.html) and my textbook but I am still having some issues.
Any help would be appreciated...
Right now I'm trying to just insert values in but nothing is working. Whether it's the first item, whether it's being added as the last one, or somewhere in between.
Node header = null; // First element of list.
Node back = null; // Last element of list.
public void insert(int i, double value){ //insert value before i-th element
Node e = new Node();
e.num = value;
Node curr = header;
for(int x=0;x<i;x++) {
if (i == 1) { //we want to insert as first thing
if (size == 0) { //its the FIRST time we add something
header.next = e;
e.next = back;
break;
} else if (size == 1){
e.next = header.next; //i.e. the second thing in the list
header.next = e;
break;
} else {
e.next = header.next.next; //i.e. the second thing in the list
header.next = e;
break;
}
}
else if (x == (i-1)) {
e.next = curr.next;
curr.next = e;
break;
}
curr = curr.next;
}
size = size+1;
}
Not really sure why it isn't working.
Thanks!
For some reason, people who are still learning to program make things far more complicated then they need to be. I did it when I was learning java, I still do it when I am just getting into a new language, and students that I have marked find new and amazing ways to do it. You have more going on in your insert then there needs to be, for example, a method that inserts a value at a specific index should not check if it's the first item to be inserted (not saying it shouldn't check bounds). Here is the pseudo code of what I would do.
insert(index, value)
if index>size
throw null pointer
traverse to index -1 //lets call this nodeI
create newnode and set value
set newnode.next to nodeI.next
set nodeI.next to newnode
increase size.
Couple of handy hints for you, you should have a function to get an element from the link list, something that returns a node? public node elementAt(int index) for example? use that to traverse the linked list. If you want to append to the Linked list, try this
append(value)
insert(size-1,value)
and if you want to insert at the beginning? same idea
insert(value)
insert(0,value)
In the line e.next = header.next.next what would happen if header.next points to a 'null'? Is it possible to get there?
What are the corner cases you have to deal with and have you taken them all into account?
Can you start with the simplest case first, adding either an element to the front or an element to the back? Then use those functions to implement the insert?
A few suggestions:
implement java.util.List
Think about generics
Read this.
Start with "insert at the end" before you think about "insert at i".
I have tried a simple program, which will be useful for you guys, I am also learning Java, please bear with me for any mistakes, but this program works fine.
I am posting a very simple singly linked list program in Java, which I tried out today.
I hope it will help all.
LinkList.java
class LinkList
{
public static void main(String args[])
{
Node node = new Node(1);
node.addAtLast(2);
node.addAtLast(3);
node.addAtLast(4);
node.addAtLast(5);
node.printList();
}
}
Node.java
class Node
{
private int data;
private Node link;
public Node(int mydata)
{
data = mydata;
link = null;
}
public void printList()
{
System.out.print("|"+data+"|"+"->");
if(link != null)
{
//recursive call
link.printList();
}
else
{
//marking end of list as NULL
System.out.print("|NULL|");
}
}
public void addAtLast(int mydata)
{
if(link == null)
{
link = new Node(mydata);
}
else
{
link.addAtLast(mydata);
}
}
}
OUTPUT :
The below is our output
|1|->|2|->|3|->|4|->|5|->|NULL|