I'm adding values from an ArrayList of Strings to a BST and I'm coming up with a null pointer error on my line "tree.add(s);" and after tracing my code I can't figure out why this is happening. Can someone please help:
public class BinaryTree {
public Node root;
public BinaryTree tree;
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) {
Collections.shuffle(dict);
for (String s : dict) {
s.toUpperCase();
System.out.print(s);
tree.add(s);
}
System.out.print(tree);
System.out.println();
return tree;
}
/**
* Creates an empty binary tree
*/
public BinaryTree() {
root = null;
}
public boolean search(String data) {
return (search(root, data));
}
private boolean search(Node node, String data) {
if (node == null) {
return (false);
}
if (data == node.data) {
return (true);
} else if (data.compareTo(node.data) > 0) {
return (search(node.left, data));
} else {
return (search(node.right, data));
}
}
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);
}
}
You have to set the tree variable to something before using it. For example:
public BinaryTree plantTree(ArrayList<String> dict) {
tree = new BinaryTree(); // important!
Collections.shuffle(dict);
for (String s : dict) {
s.toUpperCase();
System.out.print(s);
tree.add(s);
}
System.out.print(tree);
System.out.println();
return tree;
}
Maybe tree should be a local variable of the method rather than an instance variable?
Related
I am using custom made data structure and, in this project, I am using a doubly LinkedList to implement a blockchain.
so I have made a Main class and a Block class and of course the LinkedList class, the LinkedList class was made to accept data of the type Block so when I try to add elements to my list i pass on a new block with the information the problem is after the first element I don't know how to call the hash value of the previous block.
basically in every block class there should be a hash and the hash of the previous block in block one there is no prev hash so its 0 but the second block and onwards is where I am lost.
this is my block class
import java.util.Date;
public class Block {
public String hash;
public String previousHash;
private String data;
private long timeStamp;
public Block(String data, String previousHash) {
this.data = data;
this.previousHash = previousHash;
this.timeStamp = new Date().getTime();
this.hash = calculateHash();
}
public String calculateHash() {
String calculatehash = StringUtil.applySha256(
previousHash + Long.toString(timeStamp) + data);
return calculatehash;
}
}
this is my doubly LinkedList file
class Node {
private Block data; // node storing int data
private Node nextNode; // the next pointer node, the arrow in drawing
private Node prevNode;
// don't forget the class constructor
public Node(Block data2) {
this.data = data2;
}
// since we made variable private
// to access them we need setters and getters
public Block getData() {
return this.data;
}
public Node getNextNode() {
return this.nextNode;
}
public Node getPrevNode() {
return this.prevNode;
}
public Block setData(Block data) {
return this.data = data;
}
public Node setNextNode(Node nextNode) {
return this.nextNode = nextNode;
}
public Node setpervNode(Node prevNode) {
return this.prevNode = prevNode;
}
#Override
public String toString() {
return "Data: " + this.data;
}
}
public class DoublyLinkedlist {
private Node head;
private Node tail;
private int size = 0;
public DoublyLinkedlist() {
}
public int getSize() {
return this.size;
}
public void addFirst(Block data) {
Node node = new Node(data);
if (this.tail == null && this.head == null) {
this.tail = node;
this.head = node;
} else if (this.head == null) {
this.head = node;
} else {
Node old = this.head;
node.setNextNode(old);
this.head = node;
old.setpervNode(this.head);
}
this.size++;
}
public void addLast(Block data) {
Node node = new Node(data);
if (this.tail == null && this.head == null) {
this.tail = node;
this.head = node;
} else if (this.tail == null) {
this.tail = node;
} else {
Node old = this.tail;
this.tail.setNextNode(node);
this.tail = node;
this.tail.setpervNode(old);
}
this.size++;
}
public Node removeFirst() {
Node removed = this.head;
this.head = this.head.getNextNode();
this.size--;
return removed;
}
#Override
public String toString() {
String output = "[size=" + this.size + "] >> ";
Node fromHead = this.head;
while (fromHead != null) {
output = output + fromHead.getData();
if (fromHead != this.tail)
output = output + " >> ";
fromHead = fromHead.getNextNode();
}
output += "\n";
Node fromTail = this.tail;
while (fromTail != null) {
output = output + fromTail.getData();
if (fromTail != this.head)
output = output + " << ";
fromTail = fromTail.getPrevNode();
}
return output;
}
public boolean contains(Block data) {
Node current = this.head;
while (current != null) {
if (current.getData() == data) {
return true;
}
current = current.getNextNode();
}
return false;
}
public void clear() {
while (this.head != null) {
this.removeFirst();
}
System.out.println("List Is Cleared!");
}
}
and this is my Main class
public class Main {
public static DoublyLinkedlist blockchain = new DoublyLinkedlist();
public static void main(String[] args) {
blockchain.addFirst(new Block("hi i am the first block", "0"));
blockchain.addLast(new Block("yo i am the second block", blockchain.get(blockchain.getSize()-1.hash)));
}
}
i tried using the get method based on a tutorial that was implementing using an arraylist but obviously it's a wrong syntax.
The main program should not have to deal with retrieving hashes, not even with creating blocks. Instead aim for your main code to look like this:
public class Main {
public static DoublyLinkedlist blockchain = new DoublyLinkedlist();
public static void main(String[] args) {
blockchain.addLast("Hi, I am the first block");
blockchain.addLast("Yo, I am the second block");
}
}
Then your other classes would also need some adaptations. In Node I would add a constructor that can take a second argument, so it can establish the link with a previous node:
public Node(Block data, Node prevNode) { // Additional constructor
this.data = data;
this.prevNode = prevNode;
if (prevNode != null) {
prevNode.setNextNode(this);
}
}
In the DoublyLinkedList class, remove the addFirst method: you don't want to add blocks before any existing blocks, as that would invalidate the hashes of the blocks that are already in the list. Blocks should only be added at the end.
The addLast method should take a string instead of a Block instance, and this method can also be used for adding the very first block.
public void addLast(String data) {
tail = new Node(new Block(data, tail != null ? tail.getData().hash : "0"), tail);
if (head == null) head = tail;
size++;
}
Basically, my problem with my code is that somewhere in its implementation it creates a blank node which is then inserted into my binary tree. This node exists, as my sizeOfTree method counts it as such.
The code works just fine, the only problem is the node.
OK, so here I have defined the TreeNode based on which the Binary Tree is constructed:
package hr.fer.oop.lab1.prob6;
public class TreeNode {
TreeNode left=null;
TreeNode right=null;
String data;
public TreeNode(String data) {
this.data=data;
}
}
And here is the rest of it:
package hr.fer.oop.lab1.prob6;
import hr.fer.oop.lab1.prob6.TreeNode;
public class BinaryTree {
TreeNode root;
public BinaryTree() {
TreeNode node = new TreeNode("");
root=node;
}
public void insert (String data) {
if (this.root==null) {
this.root=new TreeNode(data);
return;
}
else {
TreeNode node = this.root;
TreeNode parent = new TreeNode("");
while(node!=null) {
parent = node;
if (node.data.compareTo(data)<=0) {
node=node.left;
}
else{
node=node.right;
}
}
if (parent.data.compareTo(data)<=0) {
parent.left=new TreeNode(data);
}
else {
parent.right=new TreeNode(data);
}
}
return;
}
private boolean subTreeContainsData(TreeNode node, String data) {
if ((node.data).compareTo(data)<1E-15) return true;
TreeNode temp=new TreeNode("");
temp=node;
if((temp.left.data).equals("")&&(temp.right.data).equals("")) return false;
return (subTreeContainsData(temp.left, data)||subTreeContainsData(temp.right, data));
}
private boolean containsData(String data) {
return subTreeContainsData(root, data);
}
private int sizeOfSubTree(TreeNode node) {
if (node==null) return 0;
return 1 + sizeOfSubTree(node.left) + sizeOfSubTree(node.right);
}
public int sizeOfTree() {
return sizeOfSubTree(root);
}
private void writeSubTree(TreeNode node) {
if (node!=null) {
writeSubTree(node.left);
System.out.println(node.data);
writeSubTree(node.right);
}
return;
}
public void writeTree() {
writeSubTree(root);
}
private void reverseSubTreeOrder(TreeNode node) {
if (node==null) return;
TreeNode helpNode;
helpNode=node.left;
node.left=node.right;
node.right=helpNode;
reverseSubTreeOrder(node.left);
reverseSubTreeOrder(node.right);
}
public void reverseTreeOrder() {
reverseSubTreeOrder(root);
}
public static void main (String[] args) {
BinaryTree tree = new BinaryTree();
tree.insert("Jasna");
tree.insert("Ana");
tree.insert("Ivana");
tree.insert("Anamarija");
tree.insert("Vesna");
tree.insert("Kristina");
System.out.println("Writing tree inorder:");
tree.writeTree();
tree.reverseTreeOrder();
System.out.println("Writing reversed tree inorder:");
tree.writeTree();
int size=tree.sizeOfTree();
System.out.println("Number of nodes in tree is "+size+".");
boolean found = tree.containsData("Ivana");
System.out.println("Searched element is found: "+found);
}
}
Much appreciate any help provided.
You create an empty TreeNode in your constructor and make it the root of the tree:
public BinaryTree() {
TreeNode node = new TreeNode("");
root=node;
}
Later, in your insert method, your if (this.root==null) condition is always false, so you don't assign the first inserted node to the root.
Just remove it:
public BinaryTree() {
}
Can some one show me the way to loop a binary tree in order to traverse all nodes.
I will add students by insert method.
I just want to print all the students objects.
This is my BST :
public class BinarySearchTree<Students extends Comparable<? super Student>> {
public static BinaryNode root;
public BinarySearchTree() {
this.root = null;
}
public void insert(Student student) {
root = insert(student, root);
}
protected BinaryNode<Student> insert(Student student, BinaryNode<Student> t) {
if (t == null) {
t = new BinaryNode<Student>(student);
} else if (student.compareTo(t.element) < 0) {
t.left = insert(student, t.left);
} else if (student.compareTo(t.element) > 0) {
t.right = insert(student, t.right);
} else {
// throw new DuplicateItemException(student.toString());
}
return t;
}
}
Node Class :
class BinaryNode<Student> {
// Constructor
BinaryNode(Student theElement) {
element = theElement;
left = right = null;
}
// Data; accessible by other package routines
Student element; // The data in the node
BinaryNode<Student> left; // Left child
BinaryNode<Student> right; // Right child
}
Add this method to the BinarySearchTree class:
public void inorder(BinaryNode node) {
if (node == null) {
return;
}
inorder(node.left);
System.out.print(...); //whatever you want to do with the node
inorder(node.right);
}
In a similar way you can do preorder and postorder traversals.
There are 3 ways to traverse Binary Search Trees.
Pre-order
public void preOrder(BinaryNode node) {
if (node == null) {
return;
}
doSomethig(node.element); // process node
preOrder(node.left);
preOrder(node.right);
}
In-order in this case nodes are traversed in order
public void inOrder(BinaryNode node) {
if (node == null) {
return;
}
inOrder(node.left);
doSomethig(node.element); // process node
inOrder(node.right);
}
Post-order
public void postOrder(BinaryNode node) {
if (node == null) {
return;
}
postOrder(node.left);
postOrder(node.right);
doSomethig(node.element); // process node
}
You have to choose one of these and run for example:
preOrder(root); // where root is a handle to your BST
public class BinarySearchTree<Students extends Comparable<? super Student>> {
public static BinaryNode root;
public BinarySearchTree() {
this.root = null;
}
...
public void print() {
print(root);
}
public void print(BinaryNode<Student> node) {
if (node == null) {
return;
}
print(node.left);
doSomething(node.getStudent());
print(node.right);
}
}
I've just created a method to test the height of my binary tree implementation as follows:
public int height() {
return height(rootNode);
}
private int height(BinaryTreeNode node) {
if(node == null) return -1;
else return 1 + Math.max(height(node.getLeftChild()), height(node.getRightChild()));
}
But it returns a height of 6, and not 7 when i add the nodes 1-6.
Here is my Binary Tree code:
import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.Queue;
public class BinaryTree<E extends Comparable<E>>
{
private class BinaryTreeNode
{
private E value;
private BinaryTreeNode leftChild, rightChild;
public BinaryTreeNode(E value) {
this(value, null, null);
}
public BinaryTreeNode(E value, BinaryTreeNode leftChild, BinaryTreeNode rightChild) {
this.value = value;
this.leftChild = leftChild;
this.rightChild = rightChild;
}
public E getValue() {
return value;
}
public BinaryTreeNode getLeftChild() {
return leftChild;
}
public BinaryTreeNode getRightChild() {
return rightChild;
}
public void setLeftChild(BinaryTreeNode newLeftChild) {
this.leftChild = newLeftChild;
}
public void setRightChild(BinaryTreeNode newRightChild) {
this.rightChild = newRightChild;
}
}
private BinaryTreeNode rootNode;
public BinaryTree() {
this.rootNode = null;
}
public void addNode(E value) {
if(rootNode == null)
rootNode = new BinaryTreeNode(value);
else
addNode(value, rootNode);
}
//TODO: Implement removeNode()
public void printLevelOrder() {
printLevelOrder(rootNode);
}
public int height() {
return height(rootNode);
}
public void inOrderTraversal() {
if(rootNode != null) inOrderTraversal(rootNode);
else System.out.println("The tree is empty!");
}
private void addNode(E value, BinaryTreeNode node) {
if(node.getValue().compareTo(value) > 0) {
if(node.getLeftChild() != null)
addNode(value, node.getLeftChild());
else
node.setLeftChild(new BinaryTreeNode(value));
} else {
if(node.getRightChild() != null)
addNode(value, node.getRightChild());
else
node.setRightChild(new BinaryTreeNode(value));
}
}
private void printLevelOrder(BinaryTreeNode node) {
Queue<BinaryTreeNode> currentLevel = new LinkedList<BinaryTreeNode>();
Queue<BinaryTreeNode> nextLevel = new LinkedList<BinaryTreeNode>();
currentLevel.add(node);
while (!currentLevel.isEmpty()) {
Iterator<BinaryTreeNode> iter = currentLevel.iterator();
while (iter.hasNext()) {
BinaryTreeNode currentNode = iter.next();
if (currentNode.leftChild != null) {
nextLevel.add(currentNode.leftChild);
}
if (currentNode.rightChild != null) {
nextLevel.add(currentNode.rightChild);
}
System.out.print(currentNode.value + " ");
}
System.out.println();
currentLevel = nextLevel;
nextLevel = new LinkedList<BinaryTreeNode>();
}
}
private int height(BinaryTreeNode node) {
if(node == null) return -1;
else return 1 + Math.max(height(node.getLeftChild()), height(node.getRightChild()));
}
private void inOrderTraversal(BinaryTreeNode node) {
if(node != null) {
inOrderTraversal(node.leftChild);
System.out.println(node.getValue() + " ");
inOrderTraversal(node.getRightChild());
}
}
public BinaryTreeNode getRoot() {
return rootNode;
}
}
I think the problem is adding my node into the tree, but I've taken a look at other examples but they all seem to be doing the same thing I am.. So i can't realise the problem!
Thanks!
private int height(BinaryTreeNode node) {
if(node == null) return 0;
else return 1 + Math.max(height(node.getLeftChild()), height(node.getRightChild()));
}
You were returning -1 on node==null when you should return 0.
The condition is true when we arrive to leaf so for example if we add 1-2 then we have height as 1+Max(leftof(1),rightof(1))=
1+Max(height(null),height(2))=
1+Max(0,1+Max(leftof(2),rightof(2)))=
1+Max(0,1+Max(height(null),height(null)))=
1+Max(0,1+Max(0,0))=
1+Max(0,1+0)=
1+1=2.
Try to replace height(null) with -1 in the previous example to see by yourself.
By the way your BinaryTree implementation is actually a binary search tree since you're putting less elements on the left and bigger elements on the right, If a search tree is your intention then Ok but if you want to implement a general binary tree then you should change the add function.
My problem is in the add method. I think I know what I want it to do but I can't figure out what type of loop I should use to look through the list. As you can see I started to make a if else loop but I couldn't figure out what I should use as the counter. I'm pretty sure I have the right logic in dealing with the add but I feel like I'm not quite there yet. I was thinking of using compareTo in some fashion.
import java.util.*;
public class OrderedLinkedList<E extends Comparable<E>>
{
private Node topNode;
private class Node
{
private E data;
private Node nextNode;
public Node(E data)
{
this.data = data;
nextNode = null;
}
}
public OrderedLinkedList()
{
topNode = null;
}
public boolean empty()
{
if(topNode == null)
return true;
return false;
}
public String toString()
{
String myString = "";
Node nextNode = topNode;
while(nextNode != null)
{
myString = topNode + " -> " + nextNode;
nextNode = topNode.nextNode;
}
return myString;
}
public void add(E data)
{
Node myNode = new Node(data);
Node priorNode = topNode;
Node currentNode = topNode;
if(___)
{
priorNode = currentNode;
currentNode = currentNode.nextNode;
}
else
{
priorNode.nextNode = myNode;
myNode.nextNode = currentNode;
}
}
}
Since you don't typically know the length of a linked list until you've walked down it, the usual thing would be to use a while loop (as you've done in your toString() method)
Perhaps using a doubly linked list would be more beneficial. Consider the following alterations to your class:
import java.util.*;
public class OrderedLinkedList<E extends Comparable<E>>
{
private Node head;
private Node tail;
private class Node
{
private E data;
private Node nextNode;
private Node prevNode;
public Node(E data)
{
this.data = data;
nextNode = null;
prevNode = null;
}
public void setNext(Node node)
{
this.nextNode = node;
}
public Node getNext()
{
return this.nextNode;
}
public void setPrev(Node node)
{
this.prevNode = node;
}
public Node getPrev()
{
return this.prevNode;
}
public E getData()
{
return this.data;
}
public int compareTo(Node that) {
if(this.getData() < that.getData())
{
return -1;
}
else if(this.getData() == that.getData()
{
return 0;
}
else
{
return 1;
}
}
}
public OrderedLinkedList()
{
head = new Node(null);
tail = new Node(null);
head.setNext(tail);
tail.setPrev(head);
}
public boolean empty()
{
if(head.getNext() == tail)
{
return true;
}
return false;
}
public void add(E data) {
Node tmp = new Node(data);
if(this.empty()) {
this.addNodeAfterNode(tmp, head);
} else {
Node that = head.getNext();
// this while loop iterates over the list until finding the correct
// spot to add the new node. The correct spot is considered to be
// when tmp's data is >= that's data, or the next node after 'that'
// is tail. In which case the node is added to the end of the list
while((tmp.compareTo(that) == -1) && (that.getNext() != tail)) {
that = that.getNext();
}
this.addNodeAfterNode(tmp, that);
}
}
private void addNodeAfterNode(Node addNode, Node afterNode)
{
addNode.setNext(afterNode.getNext());
afterNode.getNext().setPrev(addNode);
afterNode.setNext(addNode);
addNode.setPrev(afterNode);
}
}