I have implemented a simple binary tree program, but there is a problem I encounter while traversing the tree, only root element is accessed. I suspect the nodes aren't linked. I tried my best to figure out the problem but didn't find anything wrong with my code.
I tried printing the data from the insertion function, right before exiting the function, which did print the data correctly.
public class BinaryTree {
Node root;
public void addNode(int data){
Node newNode = new Node(data);
if(root == null){
root = newNode;
}
else{
Node currentNode = root;
while(true){
if(data <= currentNode.data){
currentNode = currentNode.leftChild;
if(currentNode == null){
currentNode = newNode;
return;
}
}
else{
currentNode = currentNode.rightChild;
if(currentNode == null){
currentNode = newNode;
return;
}
}
}
}
}
public void inorderTraversal(Node currentNode){
if(currentNode != null){
inorderTraversal(currentNode.leftChild);
System.out.print(currentNode.data + " ");
inorderTraversal(currentNode.rightChild);
}
}
}
In fact you are not adding the new node correctly to the tree during the recursive step. The logic you should be using is when you a reach a node whose left or right pointer be null, and the new node belongs in that direction, you should add the new node either to the left or right. Otherwise, keep traversing until you reach such node.
while(true) {
if (data <= currentNode.data) {
if (currentNode.leftChild == null) {
currentNode.leftChild = newNode;
return;
}
else {
currentNode = currentNode.leftChild;
}
else {
if (currentNode.rightChild == null) {
currentNode.rightChild = newNode;
return;
}
else {
currentNode = currentNode.rightChild;
}
}
}
Keep in mind that the above simple algorithm for adding new nodes is not guaranteed to necessarily result in a balanced binary tree. To ensure that, you would have to add more logic which handle rebalancing.
You are not assigning the element to the left or right child. You are just assigning it to the local variable currentNode - which is not linked to the tree.
Follow the below code to put inside the while loop & it should work for you.
if(data <= currentNode.data){
if(currentNode.leftChild == null){
currentNode.leftChild = newNode;
return;
}
else {
currentNode = currentNode.leftChild;
}
}
else{
if(currentNode.rightChild == null){
currentNode.rightChild = newNode;
return;
}
else {
currentNode = currentNode.rightChild;
}
}
Related
Hello I need to implement a Hashtable with a separate chaining. For that I am implementing a Node class and LinkedList. Nodes included in the linked list have the attributes data, count, a link to next and a link to previous.Linked list should not have values with duplicate value but given another node with the same value inserted, the count of that node should be increased. Above is my code but I could not figure out on how to implement the insert function so that when a duplicate node is found, the count is increased.
public void insertToHead(Node newNode) {
newNode.setNext(head);
head = newNode;
}
public void drop(Node newNode) {
newNode.getPrev().setNext(newNode.getNext());
}
public void insert(String newData) {
Node newNode = new Node(newData);
Node temp = head;
if (temp == null) {
insertToHead(newNode);
newNode.incrementCount();
nodeCount++;
} else {
for(int i=0;i<nodeCount;i++){
if(temp.getData().equals(newNode.getData())){
if(temp.getPrev()==null){
temp.incrementCount();
head=temp;
}
if(temp.getNext()==null){
temp.getPrev().setNext(null);
temp.incrementCount();
insertToHead(temp);
}
else{
temp.incrementCount();
drop(temp);
insertToHead(temp);
}
}
temp = temp.getNext();
}
insertToHead(newNode);
nodeCount++;
}
}
You need to traverse the linked list until you found an equal node and then increment the count on the same node, not the previous. If you reached the end of the list in that process, you do your normal insertion.
Node newNode = new Node(newData);
Node temp = head;
if (temp == null) {
insertToHead(newNode);
newNode.incrementCount();
nodeCount++;
} else {
while(temp != null){
if(temp.getData().equals(newNode.getData())){
temp.incrementCount();
break;
}
temp = temp.getNext();
}
// didn't find anything, prepend to the list
if(temp == null){
insertToHead(newNode);
nodeCount++;
}
}
I have completed the recursive insert function and it works perfectly, but I can not get the non recursive solution to work.
public void insert(T item){
root= nonRecursive(root,item);
}
public BinaryTreeNode<T> nonRecursive(BinaryTreeNode<T> tree, T item){
if(root==null){
root=new BinaryTreeNode<T>(item);
return root;
}
else{
BinaryTreeNode<T> next = new BinaryTreeNode<T>();
Comparable<T> temp = (Comparable<T>) root.info;
if(temp.compareTo(item)== 0){
return null;
}
else if(temp.compareTo(item) > 0){
next=root.lLink;
}
else{
next=root.rLink;
}
while(next != null){
Comparable<T> temp2 = (Comparable<T>) next.info;
if(temp.compareTo(item) == 0){
return null;
}
else if(temp2.compareTo(item) > 0){
next=next.lLink;
}
else{
next=next.rLink;
}
}
next=new BinaryTreeNode<T>(item);
return root;
}
}
and then the recursive one is:
public void insert(T item) {
root = recInsert(root, item);
}
public BinaryTreeNode<T> recInsert(BinaryTreeNode<T> tree, T item) {
if(tree == null) {
//create new node
tree = new BinaryTreeNode<T>(item);
}
else {
Comparable<T> temp = (Comparable<T>) tree.info;
if (temp.compareTo(item) == 0) {
System.err.print("Already in duplicates are not allowed.");
return null;
}
else if (temp.compareTo(item) > 0)
tree.lLink = recInsert(tree.lLink, item);
else
tree.rLink = recInsert(tree.rLink, item);
}
return tree;
}
does anyone know what I am doing wrong?
I thought I had gotten it but now it only returns the first number I enter in
here you go then
in your code,
if(current == null){
current.lLink=node;
if current is null, then how can it have a iLink ?
maybe you need to do
if(current == null){
current = new Node ();
current.lLink=node;
Your code is not even close to finish.
You haven't even done one comparison. What you did is simply meaningless loops.
If you are looking for a non-recursive logic, here is the pseudo code. Your job is to understand it and write it in Java.
insert(item) {
Node itemNode = new Node(item);
if root is null {
root = itemNode
return
}
currentNode = root;
keep looping until node is inserted {
if currentNode is equals to itemNode {
show error and exit
} else if itemNode is smaller than currentNode {
if (currentNode has no left){
set currentNode's left to itemNode
// Item Inserted!!!!
} else { // there are node at currentNode's left
set currentNode to currentNode's left (and continue lookup)
}
} else { // item node is greater than current node
// do similar thing as the "itemNode < currentNode logic",
// of course on currentNode's right
}
}
}
I am trying to add Point into a linked list, in order to keep track of the frequency of each data entry. Everytime I run this code it gives me a NullPointerException. I don;t understand why, to me it seems as if after it adds the frequency it creates a gap but I cant seem to fix it.
if(firstNode == null)
{
addPair = new Pair(aData, 1);
firstNode = new Node(null, addPair, null);
lastNode = firstNode;
currentNode = firstNode;
numberOfNodes++;
}
else
{
currentNode=firstNode;
for(int count = 0; count<numberOfNodes; count++)
{
if(currentNode.data.fst().equals(aData))
{
addPair = new Pair(aData,currentNode.data.freq()+1);
if(count==0)
firstNode= new Node(currentNode,addPair,null);
currentNode = new Node(currentNode,addPair,null);
break;
}
if(count == (numberOfNodes-1) && currentNode.data.fst() !=(aData))
{
addPair = new Pair(aData,1);
Node newNode = new Node(currentNode, addPair, null);
currentNode.next = newNode;
lastNode = newNode;
numberOfNodes++;
break;
}
currentNode = currentNode.next;
}
}
numberOfEntries++;
private class Node
{
private Node previous;
private Pair data;
private Node next;
private Node(Node previousNode, Pair<T,Integer> addPair, Node nextNode)
{
previous = previousNode;
data = addPair;
next = nextNode;
}
}
If you are receiving a NPE at the line if(currentNode.data.fst().equals(aData)) then either currentNode == null or currentNode.data == null or currectNode.data.fst() == null. The first thing to do in diagnosing the problem is to find out which of these is the case. I suggest you put the following statements before this line and rerun your code:
assert currentNode != null;
assert currentNode.data != null;
assert currentNode.data.fst() != null;
Apart from that diagnosis there are a number of ways you could make your code safer. Firstly you really have no need to use a count to iterate through your linked list. Much safer would be to end when the next pointer is null:
for (Node current = firstNode; current != null; current = current.next) {
if (current.data.equals(aData)) {
// increment counter
return;
}
}
The main problem is in this line
firstNode= new Node(currentNode,addPair,null);
When you increase frequency of first node you are not setting the next Node, so you got list of only one node, but with size of many. Similar problem with line
currentNode = new Node(currentNode,addPair,null);
Also all first if statement is wrong. You are corrupting links in the list, it should be something like this
if (currentNode.data.fst().equals(aData)) {
addPair = new Pair(aData, currentNode.data.freq() + 1);
// create new node
Node c = new Node(currentNode.previous, addPair, currentNode.next);
// set links to new node
if (currentNode.previous != null) {
currentNode.previous.next = c;
}
if (currentNode.next != null) {
currentNode.next.previous = c;
}
if (count == 0) {
firstNode = c;
}
break;
}
To simplify your code and decrease possible errors I could recommend to write some function like incFrequency() in Pair class. Then in the loop do something like this
if (currentNode.data.fst().equals(aData)) {
currentNode.data.incFrequency();
break;
} else if(count == (numberOfNodes-1) && currentNode.data.fst() !=(aData)) {
// add new node to the end
}
Also you could rewrite you for loop
currentNode = firstNode;
// iterate through list
while (currentNode != null) {
// process currentNode
...
// move to the next node
currentNode = currentNode.next;
}
I just learned about binary trees and I tried to create an insert method. My first method did not work and I did a bit of tweaking. It now works but I do not understand why the previous method failed.
The method that does not work is:
if(root == null)
{
root = new Node(data);
}
else if(data < root.getData())
{
insertNode(root.getLeft(), data);
}
else
{
insertNode(root.getRight(), data);
}
The method that does work is:
if(data < root.getData())
{
if(root.getLeft() == null)
{
root.left = new Node(data);
}
else
{
insertNode(root.getLeft(), data);
}
}
else
{
if(root.getRight() == null)
{
root.right = new Node(data);
}
else
{
insertNode(root.getRight(), data);
}
}
Any explanations as to why this is the case? Because the way I see it, root should be equal to root.left, so setting root to a new Node should be the same as setting root.left/right to a new Node.
In your first method, you would give null into your insertNode method, but no reference pointer. Therefore you set root = new Node() in the insertNode method, but the parent node does not know any of this, it still points to null.
Since this is some very basic Java understanding, I recommend reading some articles about "java parameter passing" e.g. http://javadude.com/articles/passbyvalue.htm
Assuming that you call the method recursively, insertNode(root, data), you have to be sure that root is not null, which means executing root = new Node(data); creates an object whose visibility is limited to insertNode method.
If not, you can rewrite insertNode(data) to be non-recursive and create the root inside it if it is null.
public void insert(int data) {
if(root == null){
root = new Node(data);
}
else {
Node current = root;
Node previous;
String from;
while(current != null) {
previous = current;
if(data < current.getData()) {
current = current.left();
from = "left";
}
else {
current = current.right();
from = "right";
}
}
current = new Node(data);
if(from.equals("left")) {
previous.left() = current;
} else {
previous.right() = current;
}
}
}
I am pretty new to trees, and I am trying to create kind of a "leaf iterator". I'm thinking it should put all nodes that does not have a .left and .right value onto a stack, but I'm not sure how or even if it's the right thing to do. I have tried searching for it, but every example I come over starts with going to the leftmost leaf, and going p = node.parent, and I am avoiding linking to the node's parent.
I don't understand how I can repeatedlty start from the root and go through the vines without visiting the same vines over and over.
EDIT
I see people suggests using a recursive method to solve this, and I agree now. But I have been banging my head trying to find the solution for an iterator-class-way to do this for a while, and I still would like to know if that's possible, and how!
Use recursion:
public void visitNode(Node node) {
if(node.left != null) {
visitNode(node.left);
}
if(node.right != null) {
visitNode(node.right);
}
if(node.left == null && node.right == null) {
//OMG! leaf!
}
}
start it by supplying root:
visitNode(root);
In order to translate this into an Iterator<Node> you'll have to translate recursion to loop and then to traversal with state. Non-trivial, but should give you a lot of fun.
class Node {
public Node left = null;
public Node right = null;
// data and other goodies
}
class Tree {
public Node root = null;
// add and remove methods, etc.
public void visitAllLeaves(Node root) {
// visit all leaves starting at the root
java.util.Stack<Node> stack = new java.util.Stack<Node>();
if (root == null) return; // check to make sure we're given a good node
stack.push(root);
while (!stack.empty()) {
root = stack.pop();
if (root.left == null && root.right == null) {
// this is a leaf
// do stuff here
}
if (root.left != null) {
stack.push(root.left);
}
if (root.right != null) {
stack.push(root.right);
}
}
}
}
I'm not sure if the above code works, but that's somewhere along the lines of what needs to be done. Another option is javax.swing.TreeModel (half-joking).
Here is how one could implement an Iterator that would only return the leaf nodes, i.e. nodes without a left or right subtree.
The iterator searches for leaf nodes in the tree by doing a depth-first search, remembering the current state of the search in a stack and "pausing" when it has found a leaf node (see fetchNext() method).
The search is resumed when the client "consumes" the leaf node by calling next().
class Node {
public Node left;
public Node right;
}
class LeaveIterator implements Iterator<Node> {
private final Stack<Node> stack = new Stack<>();
private Node nextNode = null;
public LeaveIterator(Node root) {
if (root != null) {
stack.push(root);
nextNode = fetchNext();
}
}
private void fetchNext() {
Node next = null;
while (!stack.isEmpty() && next == null) {
Node node = stack.pop();
if (node.left == null && node.right == null) {
next = node;
}
if (node.right != null) {
stack.push(node.right);
}
if (node.left != null) {
stack.push(node.left);
}
}
return next;
}
public boolean hasNext() {
return nextNode != null;
}
public Node next() {
if (!hasNext()) {
throw new NoSuchElementException();
}
Node n = nextNode;
nextNode = fetchNext();
return n;
}
public void remove() {
throw new UnsupportedOperationException();
}
}