Generic BST having trouble getting constructor to work - binary-search-tree

I have been given some code from my instructor and i need to implement several functions. I have added the insert method but I can not figure out how or what the constructor is looking for, I don't understand why this call to construct a tree is not working. Not very strong in java but understand the logic of a BST
public class BinaryTreeDriver {
public static void main(String[] args){
BinaryTree<Integer> numbers = new BinaryTree<>();
I am getting compiler error cannot infer type arguments BinaryTree<>
Copying rest of code below
public class BinaryTree<T extends Comparable<T>> {
private BinaryTreeNode<T> root; // the root of the tree
private BinaryTreeNode<T> cursor; // the current node
/**
* Constructor for initializing a tree with node
* being set as the root of the tree.
* #param node
*/
public BinaryTree(BinaryTreeNode<T> node) {
root = node;
}
/**
* Moves the cursor to the root.
*/
public void toRoot() {
cursor = root;
}
/**
* Returns the cursor node.
* #return cursor
*/
public BinaryTreeNode<T> getCursor() {
return cursor;
}
/**
* Sets the root to the provided node.
* ONLY USE IN THE DELETE METHOD
* #param node
*/
public void setRoot(BinaryTreeNode<T> node) {
root = node;
}
/**
* Checks if the tree node has a left child node
* #return true if left child exists else false
*/
public boolean hasLeftChild() {
return cursor.getLeft() != null;
}
/**
* Checks if the tree node has a right child node
* #return true if right child exists else false
*/
public boolean hasRightChild() {
return cursor.getRight() != null;
}
/**
* Move the cursor to the left child
*/
public void toLeftChild() {
cursor = cursor.getLeft();
}
/**
* Move the cursor to the right child
*/
public void toRightChild() {
cursor = cursor.getRight();
}
/**
* #return height of the tree
*/
public int height() {
if (root != null) {
return root.height();
} else {
return 0;
}
}
**/**
* Tree-Insert
*/
public boolean insert(T elem)
{
return insert(root, elem);
}
public boolean insert(BinaryTreeNode start, T elem)
{
if (start == null)
{
root = new BinaryTreeNode<T>(elem, null, null);
return true;
}
int comparison = start.getData().compareTo(elem);
if (comparison > 0)
{
if (start.getLeft() == null)
{
start.setLeft(new BinaryTreeNode(elem, null, null));
return true;
}
return insert(start.getLeft(), elem);
}
else if (comparison < 0)
{
if (start.getRight() == null)
{
start.setRight(new BinaryTreeNode(elem, null, null));
return true;
}
return insert(start.getRight(), elem);
}
else
{
return false;
}**
}
/* (non-Javadoc)
* #see java.lang.Object#toString()
*/
public String toString() {
if (root != null) {
return root.toStringPreOrder(".");
} else {
return "";
}
}
}
public class BinaryTreeNode<T extends Comparable<T>> {
private BinaryTreeNode<T> left; // the left child
private BinaryTreeNode<T> right; // the right child
private T data; // the data in this node
public BinaryTreeNode() {
this(null, null, null);
}
public BinaryTreeNode(T theData) {
this(theData, null, null);
}
public BinaryTreeNode(T theData, BinaryTreeNode<T> leftChild,
BinaryTreeNode<T> rightChild) {
data = theData;
left = leftChild;
right = rightChild;
}
public T getData() {
return data;
}
public BinaryTreeNode<T> getLeft() {
return left;
}
public BinaryTreeNode<T> getRight() {
return right;
}
public void setLeft(BinaryTreeNode<T> newLeft) {
left = newLeft;
}
public void setRight(BinaryTreeNode<T> newRight) {
right = newRight;
}
public void setData(T newData) {
data = newData;
}
public void preOrder() {
System.out.println(data);
if (left != null) {
left.preOrder();
}
if (right != null) {
right.preOrder();
}
}
public int height() {
int leftHeight = 0; // Height of the left subtree
int rightHeight = 0; // Height of the right subtree
int height = 0; // The height of this subtree
// If we have a left subtree, determine its height
if (left != null) {
leftHeight = left.height();
}
// If we have a right subtree, determine its height
if (right != null) {
rightHeight = right.height();
}
// The height of the tree rooted at this node is one more than the
// height of the 'taller' of its children.
if (leftHeight > rightHeight) {
height = 1 + leftHeight;
} else {
height = 1 + rightHeight;
}
// Return the answer
return height;
}
/**
* #param pathString
* #return the tree nodes in pre-order traversal
*/
public String toStringPreOrder(String pathString) {
String treeString = pathString + " : " + data + "\n";
if (left != null) {
treeString += left.toStringPreOrder(pathString + "L");
}
if (right != null) {
treeString += right.toStringPreOrder(pathString + "R");
}
return treeString;
}
}

Related

Can not find symbol - method Size()

I have been getting trouble with my program and can't figure out why I am getting this error which has been bugging me. Any suggestion will be of huge assistance! I don't know if i am missing something or something like that. I have correctly imported the Array Class.
private String title;
private ArrayList<Student> students;
private int courseId;
private static int courseIdList = 0;
/**
*
*/
public Course(String tile)
{
this.title = title;
courseId = courseIdList;
courseIdList++;
students = new ArrayList<Student>();
}
/**
* #param returns the title
*/
public String getTitle(String title)
{
return title;
}
/**
* #return returns the ID
*/
public int getId()
{
return courseId;
}
/**
*
*/
public void addStudent(Student students)
{
for(int i = 0; i < students.size(); i++)
{
if(students.getId() != students.get(i).getId())
{
students.add(i);
return;
}
}
}
/**
*
*/
public void removeStudent(Student students)
{
for(int i = 0; i < students.size(); i++)
{
if(students.getId() == students.get(i).getId())
{
students.remove(i);
return;
}
}
}
/**
* #return if class is above or equal to 10 then return true, else return false;
*/
public boolean isFull(Student students)
{
if(students.size() >= 30)
{
return true;
}
else
{
return false;
}
}
/**
* #returns if the class is below ten then return true, else return false
*/
public boolean cancel(Student students)
{
if( students.size() < 10)
{
return true;
}
else
{
return false;
}
}
/**
*
*/
public ArrayList<Student> getStudents()
{
return students;
}
/**
*
*/
public boolean inClass(Student students)
{
for(int i = 0; i < students.size(); i++)
{
if(student.getId() == students.get(i).getId())
{
return true;
}
}
return false;
}
/**
* boolean returns true if a student's ID mathes and false if their ID does not.
*/
public boolean equals(Student s)
{
if(this.getId() == s.getId())
{
return true;
}
return false;
}
/**
*
*/
public double getAverage()
{
double sum = 0;
for(Student s : students)
{
sum += s.getGrade();
}
double avg = sum / students.size();
return avg;
}
/**
*
*/
public void getHighestGrade()
{
int highestGrade = 0;
for(Student s : students)
{
if(students.getGrade() > s.get(i).getGrade())
{
students.highestGrade(i);
}
}
return new Student(" ", 0,0);
}
/**
*
*/
public ArrayList<Student> getWarnings()
{
for(i = 0; i < students.size; i++)
{
if (students.getGrade() <= 70)
{
return students;
}
}
}
/**
*
*/
public void removeSeniors(Student students)
{
for(i = 0; i < students.size; i++)
{
if(students.getId() == students.get(i).subString(0,2).equalsTo(17))
{
students.remove(i);
}
}
}
/**
*
*/
public void sortByGrade()
{
}
/**
*
*/
public void sortByAlpha()
{
}
/**
*
*/
public String toString()
{
String printOut = "";
printOut += "Course name: " + title + "\nStudent ID: " + courseId;
return printOut;
for(Student students : students)
{
printOut += students.toString() + "\n";
}
}
}
Now its the opposite :) students is a List and not a Student. You need to loop over the list and process each student.
public void doSomething(List<Student> students) {
// does not work because students is a List of students not a student.
students.getId(); // ERROR
// loop over the list and then get the id of a single student
for(Student student : students) {
int id = student.getId();
// do something with the id
}
}
size() is a method of the List interface
getId() is a method of your Student class.

How to deserialize a JSON array to a singly linked list by using Jackson

I want to deserialize a JSON array to a singly linked list in Java.
The definition of singly linked list is as the following:
public class SinglyLinkedListNode<T> {
public T value;
public SinglyLinkedListNode next;
public SinglyLinkedListNode(final T value) {
this.value = value;
}
}
How to deserialize a JSON string such as [1,2,3,4,5] in to a singly linked list?
public void typeReferenceTest() throws IOException {
ObjectMapper objectMapper = new ObjectMapper();
final ArrayList<Integer> intArray = objectMapper.readValue("[1,2,3,4,5]",
new TypeReference<ArrayList<Integer>>() {});
System.out.println(intArray);
// How to achieve this?
final ArrayList<Integer> intList = objectMapper.readValue("[1,2,3,4,5]",
new TypeReference<SinglyLinkedListNode<Integer>>() {});
System.out.println(intList);
}
Moreover, I want the SinglyLinkedListNode to be a first-class citizen the same as ArrayList, which can be used in all kinds of combinations, such as HashSet<SinglyLinkedListNode<Integer>>, SinglyLinkedListNode<HashMap<String, Integer>>.
For example, what happens if I want to deserialize [[1,2,3], [4,5,6]] into a ArrayList<SinglyLinkedListNode<Integer>> ?
As far as I know, a customized deserializer extending JsonDeserializer is not enough to do this.
When you want it to be deserialized to ArrayList<SinglyLinkedListNode<Integer>> for example. Your code specifies that is the type that expected. Therefore it should if a deserializer for SinglyLinkedListNode<Integer> is regeistered it will succeed.
From the jackson-user google group I get the right answer from #Tatu Saloranta.
The answer is simple: just implement the java.util.List interface, and Jackson will automatically serialize/deserialize between JSON array and SinglyLinkedListNode.
So I implement the java.util.List interface for SinglyLinkedListNode, the code is as the following:
import java.util.*;
import java.util.function.Consumer;
/**
* Singly Linked List.
*
* <p>As to singly linked list, a node can be viewed as a single node,
* and it can be viewed as a list too.</p>
*
* #param <E> the type of elements held in this collection
* #see java.util.LinkedList
*/
public class SinglyLinkedListNode<E>
extends AbstractSequentialList<E>
implements Cloneable, java.io.Serializable {
public E value;
public SinglyLinkedListNode<E> next;
/**
* Constructs an empty list.
*/
public SinglyLinkedListNode() {
value = null;
next = null;
}
/**
* Constructs an list with one elment.
*/
public SinglyLinkedListNode(final E value) {
this.value = value;
next = null;
}
/**
* Constructs a list containing the elements of the specified
* collection, in the order they are returned by the collection's
* iterator.
*
* #param c the collection whose elements are to be placed into this list
* #throws NullPointerException if the specified collection is null
*/
public SinglyLinkedListNode(Collection<? extends E> c) {
this();
addAll(c);
}
/**
* Links e as last element.
*/
void linkLast(E e) {
final SinglyLinkedListNode<E> l = last();
final SinglyLinkedListNode<E> newNode = new SinglyLinkedListNode<>(e);
if (l == null)
this.value = e;
else
l.next = newNode;
modCount++;
}
/**
* Inserts element e before non-null Node succ.
*/
void linkBefore(E e, SinglyLinkedListNode<E> succ) {
assert succ != null;
final SinglyLinkedListNode<E> prev = this.previous(succ);
final SinglyLinkedListNode<E> newNode = new SinglyLinkedListNode<>(e);
if (prev == null)
this.value = e;
else
prev.next = newNode;
modCount++;
}
/**
* Return the node before x.
*
* #param x current node
* #return the node before x
*/
private SinglyLinkedListNode<E> previous(final SinglyLinkedListNode<E> x) {
assert (x != null);
if (size() < 2) return null;
if (this == x) return null;
SinglyLinkedListNode<E> prev = new SinglyLinkedListNode<>();
prev.next = this;
SinglyLinkedListNode<E> cur = this;
while (cur != x) {
prev = prev.next;
cur = cur.next;
}
return prev;
}
/**
* Return the last node.
* #return the last node.
*/
private SinglyLinkedListNode<E> last() {
if (size() == 0) return null;
if (size() == 1) return this;
SinglyLinkedListNode<E> prev = new SinglyLinkedListNode<>();
prev.next = this;
SinglyLinkedListNode<E> cur = this;
while (cur != null) {
prev = prev.next;
cur = cur.next;
}
return prev;
}
/**
* Unlinks non-null node x.
*/
E unlink(SinglyLinkedListNode<E> x) {
assert x != null;
final E element = x.value;
final SinglyLinkedListNode<E> next = x.next;
final SinglyLinkedListNode<E> prev = previous(x);
if (prev == null) {
this.value = next.value;
this.next = next.next;
} else {
prev.next = next;
}
x.next = null;
modCount++;
return element;
}
/**
* #inheritDoc
*/
public ListIterator<E> listIterator(int index) {
checkPositionIndex(index);
return new ListItr(index);
}
private class ListItr implements ListIterator<E> {
private SinglyLinkedListNode<E> lastReturned;
private SinglyLinkedListNode<E> next;
private int nextIndex;
private int expectedModCount = modCount;
ListItr(int index) {
assert isPositionIndex(index);
next = (index == size()) ? null : node(index);
nextIndex = index;
}
public boolean hasNext() {
return nextIndex < size();
}
public E next() {
checkForComodification();
if (!hasNext())
throw new NoSuchElementException();
lastReturned = next;
next = next.next;
nextIndex++;
return lastReturned.value;
}
public boolean hasPrevious() {
return nextIndex > 0;
}
public E previous() {
throw new UnsupportedOperationException();
}
public int nextIndex() {
return nextIndex;
}
public int previousIndex() {
return nextIndex - 1;
}
public void remove() {
checkForComodification();
if (lastReturned == null)
throw new IllegalStateException();
unlink(lastReturned);
nextIndex--;
lastReturned = null;
expectedModCount++;
}
public void set(E e) {
if (lastReturned == null)
throw new IllegalStateException();
checkForComodification();
lastReturned.value = e;
}
public void add(E e) {
checkForComodification();
lastReturned = null;
if (next == null)
linkLast(e);
else
linkBefore(e, next);
nextIndex++;
expectedModCount++;
}
public void forEachRemaining(Consumer<? super E> action) {
Objects.requireNonNull(action);
while (modCount == expectedModCount && nextIndex < size()) {
action.accept(next.value);
lastReturned = next;
next = next.next;
nextIndex++;
}
checkForComodification();
}
final void checkForComodification() {
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
}
}
/**
* #inheritDoc
*/
public int size() {
int size = 0;
if (value == null) return size;
SinglyLinkedListNode<E> cur = this;
while (cur != null) {
size++;
cur = cur.next;
}
return size;
}
private void checkPositionIndex(int index) {
if (!isPositionIndex(index))
throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
}
/**
* Returns the (non-null) Node at the specified element index.
*/
SinglyLinkedListNode<E> node(int index) {
assert isElementIndex(index);
SinglyLinkedListNode<E> x = this;
for (int i = 0; i < index; i++)
x = x.next;
return x;
}
/**
* Tells if the argument is the index of an existing element.
*/
private boolean isElementIndex(int index) {
return index >= 0 && index < size();
}
/**
* Tells if the argument is the index of a valid position for an
* iterator or an add operation.
*/
private boolean isPositionIndex(int index) {
return index >= 0 && index <= size();
}
/**
* Constructs an IndexOutOfBoundsException detail message.
* Of the many possible refactorings of the error handling code,
* this "outlining" performs best with both server and client VMs.
*/
private String outOfBoundsMsg(int index) {
return "Index: "+index+", Size: " + size();
}
}
Here is the unit test code:
#Test public void typeReferenceTest() throws IOException {
ObjectMapper objectMapper = new ObjectMapper();
final SinglyLinkedListNode<Integer> intList = objectMapper.readValue("[1,2,3,4,5]",
new TypeReference<SinglyLinkedListNode<Integer>>() {});
System.out.println(intList);
final ArrayList<SinglyLinkedListNode<Integer>> arrayOfList = objectMapper.readValue("[[1,2,3], [4,5,6]]",
new TypeReference<ArrayList<SinglyLinkedListNode<Integer>>>() {});
System.out.println(arrayOfList);
}
#Tatu Saloranta Thank you very much!
Here is my original blog, Deserialize a JSON Array to a Singly Linked List

How to deserialize a JSON object to a binary tree by using Jackson

From the previous question How to deserialize a JSON array to a singly linked list , I learned how to deserialize a JSON array to a singly linked list.
Now I want to deserialize a JSON object to a binary tree in Java.
The definition of the binary tree node is as the following:
public class BinaryTreeNode<E> {
public E value;
public BinaryTreeNode left;
public BinaryTreeNode right;
public BinaryTreeNode(final E value) {
this.value = value;
}
}
How to deserialize a JSON string such as:
{
"value": 2,
"left": {
"value": 1,
"left": null,
"right": null
},
"right": {
"value": 10,
"left": {
"value": 5,
"left": null,
"right": null
},
"right": null
}
}
to a binary tree?
2
/ \
1 10
/
5
Here is the unit test code:
#Test public void binaryTreeNodeTest() throws IOException {
ObjectMapper objectMapper = new ObjectMapper();
final ArrayList<Integer> intArray = objectMapper.readValue("[1,2,3,4,5]",
new TypeReference<ArrayList<Integer>>() {});
System.out.println(intArray);
/* How to achieve this?
2
/ \
1 10
/
5
{
"value": 2,
"left": {
"value": 1,
"left": null,
"right": null
},
"right": {
"value": 10,
"left": {
"value": 5,
"left": null,
"right": null
},
"right": null
}
}
*/
final String jsonStr = "{\n"
+ " \"value\": 2,\n"
+ " \"left\": {\n"
+ " \"value\": 1,\n"
+ " \"left\": null,\n"
+ " \"right\": null\n"
+ " },\n" + " \"right\": {\n"
+ " \"value\": 10,\n"
+ " \"left\": {\n"
+ " \"value\": 5,\n"
+ " \"left\": null,\n"
+ " \"right\": null\n"
+ " },\n"
+ " \"right\": null\n"
+ " }\n"
+ "}";
System.out.println(jsonStr);
final BinaryTreeNode<Integer> intTree = objectMapper.readValue(jsonStr,
new TypeReference<BinaryTreeNode<Integer>>() {});
System.out.println(intTree);
}
In other word, I want the BinaryTreeNode to be a first-class citizen the same as ArrayList, which can be used in all kinds of combinations, such as HashSet<BinaryTreeNode<Integer>>, BinaryTreeNode<HashMap<String, Integer>>, etc.
The solution is quite simple, since JSON can express tree naturally, Jackson can deal with recursive tree directly. Just annotate a constructor with JsonCreator:
public static class BinaryTreeNode<E>
{
public E value;
public BinaryTreeNode left;
public BinaryTreeNode right;
#JsonCreator
public BinaryTreeNode(#JsonProperty("value") final E value) {
this.value = value;
}
}
Let's write a unite test to try it:
package me.soulmachine.customized_collection;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.junit.Test;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import static org.junit.Assert.assertEquals;
public class BinaryTreeNodeTest {
public static class BinaryTreeNode<E> {
public E value;
public BinaryTreeNode left;
public BinaryTreeNode right;
#JsonCreator
public BinaryTreeNode(#JsonProperty("value") final E value) {
this.value = value;
}
ArrayList<E> preOrder() {
final ArrayList<E> result = new ArrayList<>();
if (this.value == null) {
return result;
}
preOrder(this, result);
return result;
}
private static <E> void preOrder(BinaryTreeNode<E> root, ArrayList<E> result) {
if (root == null)
return;
result.add(root.value);
if (root.left != null)
preOrder(root.left, result);
if (root.right != null)
preOrder(root.right, result);
}
}
#Test public void binaryTreeNodeTest() throws IOException {
ObjectMapper objectMapper = new ObjectMapper();
/*
2
/ \
1 10
/
5
*/
final String jsonStr = "{\n"
+ " \"value\": 2,\n"
+ " \"left\": {\n"
+ " \"value\": 1,\n"
+ " \"left\": null,\n"
+ " \"right\": null\n"
+ " },\n" + " \"right\": {\n"
+ " \"value\": 10,\n"
+ " \"left\": {\n"
+ " \"value\": 5,\n"
+ " \"left\": null,\n"
+ " \"right\": null\n"
+ " },\n"
+ " \"right\": null\n"
+ " }\n"
+ "}";
System.out.println(jsonStr);
final BinaryTreeNode<Integer> intTree = objectMapper.readValue(jsonStr,
new TypeReference<BinaryTreeNode<Integer>>() {});
final List<Integer> listExpected = Arrays.asList(2, 1, 10, 5);
assertEquals(listExpected, intTree.preOrder());
}
}
A compact serialization format
Well, there is a little problem here, the JSON string above is very verbose. Let's use another kind of serialization format, i.e., serialize a binary tree in level order traversal. For example, the binary tree above can be serialized as the following JSON string:
[2,1,10,null,null,5]
Now how to deserialize this JSON string to a binary tree?
The idea is very similar to my previous article, Deserialize a JSON Array to a Singly Linked List. Just make the BinaryTreeNode implement java.util.list, pretend that it's a list, write our own deserialization code so that Jackson can treat a binary tree as a list.
The complete code of BinaryTreeNode is as the following:
package me.soulmachine.customized_collection;
import java.util.*;
public class BinaryTreeNode<E> extends AbstractSequentialList<E>
implements Cloneable, java.io.Serializable {
public E value;
public BinaryTreeNode<E> left;
public BinaryTreeNode<E> right;
/** has a left child, but it's a null node. */
private transient boolean leftIsNull;
/** has a right child, but it's a null node. */
private transient boolean rightIsNull;
/**
* Constructs an empty binary tree.
*/
public BinaryTreeNode() {
value = null;
left = null;
right = null;
}
/**
* Constructs an binary tree with one element.
*/
public BinaryTreeNode(final E value) {
if (value == null) throw new IllegalArgumentException("null value");
this.value = value;
left = null;
right = null;
}
/**
* Constructs a binary tree containing the elements of the specified
* collection, in the order they are returned by the collection's
* iterator.
*
* #param c the collection whose elements are to be placed into this binary tree
* #throws NullPointerException if the specified collection is null
*/
public BinaryTreeNode(Collection<? extends E> c) {
this();
addAll(c);
}
/**
* #inheritDoc
*
* <p>Note: null in the middle counts, so that each father in the binary tree has a
* one-to-one mapping with the JSON array.</p>
*/
public int size() {
if (value == null) return 0;
Queue<BinaryTreeNode<E>> queue = new LinkedList<>();
queue.add(this);
int count = 0;
while (!queue.isEmpty()) {
final BinaryTreeNode<E> node = queue.remove();
++count;
if (node.left != null) {
queue.add(node.left);
} else {
if (node.leftIsNull) ++count;
}
if (node.right != null) {
queue.add(node.right);
} else {
if (node.rightIsNull) ++count;
}
}
return count;
}
/**
* Tells if the argument is the index of a valid position for an
* iterator or an add operation.
*/
private boolean isPositionIndex(int index) {
return index >= 0 && index <= size();
}
/**
* Constructs an IndexOutOfBoundsException detail message.
* Of the many possible refactorings of the error handling code,
* this "outlining" performs best with both server and client VMs.
*/
private String outOfBoundsMsg(int index) {
return "Index: "+index+", Size: "+ size();
}
private void checkPositionIndex(int index) {
if (!isPositionIndex(index))
throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
}
private class NodeAndFather {
private BinaryTreeNode<E> node;
private BinaryTreeNode<E> father;
private boolean isRight; // the father is the right child of the father
private NodeAndFather(BinaryTreeNode<E> node, BinaryTreeNode<E> father, boolean isRight) {
this.node = node;
this.father = father;
this.isRight = isRight;
}
}
/**
* Returns the (may be null) Node at the specified element index.
*/
NodeAndFather node(int index) {
checkPositionIndex(index);
if (value == null) return null;
Queue<NodeAndFather> queue = new LinkedList<>();
queue.add(new NodeAndFather(this, null, false));
for (int i = 0; !queue.isEmpty(); ++i) {
final NodeAndFather nodeAndFather = queue.remove();
if ( i == index) {
return nodeAndFather;
}
if (nodeAndFather.node != null) {
queue.add(new NodeAndFather(nodeAndFather.node.left, nodeAndFather.node, false));
queue.add(new NodeAndFather(nodeAndFather.node.right, nodeAndFather.node, true));
}
}
throw new IllegalArgumentException("Illegal index: " + index);
}
/**
* #inheritDoc
*/
public ListIterator<E> listIterator(int index) {
checkPositionIndex(index);
return new ListItr(index);
}
private class ListItr implements ListIterator<E> {
private NodeAndFather next;
private int nextIndex;
private int expectedModCount = modCount;
ListItr(int index) {
assert isPositionIndex(index);
next = node(index);
nextIndex = index;
}
public boolean hasNext() {
final BinaryTreeNode<E> cur = next.node;
return cur != null || (next.father.leftIsNull || next.father.rightIsNull);
}
//O(n)
public E next() {
checkForComodification();
if (!hasNext())
throw new NoSuchElementException();
final E result = next.node != null ? next.node.value : null;
next = node(nextIndex+1);
nextIndex++;
return result;
}
public boolean hasPrevious() {
throw new UnsupportedOperationException();
}
public E previous() {
throw new UnsupportedOperationException();
}
public int nextIndex() {
throw new UnsupportedOperationException();
}
public int previousIndex() {
throw new UnsupportedOperationException();
}
public void remove() {
throw new UnsupportedOperationException();
}
public void set(E e) {
throw new UnsupportedOperationException();
}
public void add(E e) { // always append at the tail
checkForComodification();
if (next == null) { // empty list
BinaryTreeNode.this.value = e;
BinaryTreeNode.this.left = null;
BinaryTreeNode.this.right = null;
} else {
final BinaryTreeNode<E> newNode = e != null ? new BinaryTreeNode<>(e) : null;
if (next.father == null) { // root
BinaryTreeNode<E> cur = next.node;
cur.left = newNode;
assert cur.right == null;
throw new UnsupportedOperationException();
} else {
if (next.isRight) {
if (next.father.right != null) throw new IllegalStateException();
next.father.right = newNode;
if (newNode == null) {
next.father.rightIsNull = true;
}
} else {
if (next.father.left != null) throw new IllegalStateException();
next.father.left = newNode;
if (newNode == null) {
next.father.leftIsNull = true;
}
}
}
}
modCount++;
expectedModCount++;
}
final void checkForComodification() {
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
}
}
// the following functions are just for unit tests.
ArrayList<E> preOrder() {
final ArrayList<E> result = new ArrayList<>();
if (this.value == null) {
return result;
}
preOrder(this, result);
return result;
}
private static <E> void preOrder(BinaryTreeNode<E> root, ArrayList<E> result) {
if (root == null)
return;
result.add(root.value);
if (root.left != null)
preOrder(root.left, result);
if (root.right != null)
preOrder(root.right, result);
}
ArrayList<E> inOrder() {
final ArrayList<E> result = new ArrayList<>();
if (this.value == null) {
return result;
}
inOrder(this, result);
return result;
}
private static <E> void inOrder(BinaryTreeNode<E> root, ArrayList<E> result) {
if (root == null)
return;
if (root.left != null)
inOrder(root.left, result);
result.add(root.value);
if (root.right != null)
inOrder(root.right, result);
}
ArrayList<E> postOrder() {
final ArrayList<E> result = new ArrayList<>();
if (this.value == null) {
return result;
}
postOrder(this, result);
return result;
}
private static <E> void postOrder(BinaryTreeNode<E> root, ArrayList<E> result) {
if (root == null)
return;
if (root.left != null)
postOrder(root.left, result);
if (root.right != null)
postOrder(root.right, result);
result.add(root.value);
}
ArrayList<E> levelOrder() {
final ArrayList<E> result = new ArrayList<>();
if (this.value == null) {
return result;
}
Queue<BinaryTreeNode<E>> queue = new LinkedList<>();
queue.add(this);
while (!queue.isEmpty()) {
final BinaryTreeNode<E> node = queue.remove();
result.add(node.value);
if (node.left != null)
queue.add(node.left);
if (node.right != null)
queue.add(node.right);
}
return result;
}
}
Then comes with the unit tests:
java
package me.soulmachine.customized_collection;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.junit.Test;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import static org.junit.Assert.assertEquals;
public class BinaryTreeNodeTest
{
#Test public void deserializeTest() throws IOException {
ObjectMapper objectMapper = new ObjectMapper();
final List<Integer> intList = Arrays.asList(2,1,10,null,null,5);
/*
2
/ \
1 10
/
5
*/
// TODO: the time complexity is O(n^2)
final BinaryTreeNode<Integer> intTree = objectMapper.readValue("[2,1,10,null,null,5]",
new TypeReference<BinaryTreeNode<Integer>>() {});
assertEquals(intList, intTree);
assertEquals(Arrays.asList(2, 1, 10, 5), intTree.levelOrder());
assertEquals(Arrays.asList(2, 1, 10, 5), intTree.preOrder());
assertEquals(Arrays.asList(1, 2, 5, 10), intTree.inOrder());
assertEquals(Arrays.asList(1, 5, 10, 2), intTree.postOrder());
}
}
This article is inspired by Tatu Saloranta from this post, special thanks to him!
Here is my original blog, Deserialize a JSON String to a Binary Tree

addFirst(E e) Doubly Linked List (Null Pointer Exception)

import java.util.*;
public class MyTwoWayLinkedList<E> extends java.util.AbstractSequentialList<E> {
private Node<E> head, tail;
private int size = 0;
private List<E> list;
/** Create a default list */
public MyTwoWayLinkedList() {
list = new LinkedList<E>();
}
public MyTwoWayLinkedList(E[] objects) {
list = new LinkedList<E>();
for (int i = 0; i < objects.length; i++)
add(objects[i]);
}
/** Return the head element in the list */
public E getFirst() {
if (size == 0) {
return null;
}
else {
return head.element;
}
}
/** Return the last element in the list */
public E getLast() {
if (size == 0) {
return null;
}
else {
return tail.element;
}
}
/** Add an element to the beginning of the list */
public void addFirst(E e) {
Node<E> newNode = new Node<E>(e); // Create a new node
newNode.next = head; // link the new node with the head
head.previous = newNode; //link the old node with new head
head = newNode; // head points to the new node
size++; // Increase list size
if (tail == null) // the new node is the only node in list
tail = head;
}
/** Add an element to the end of the list */
public void addLast(E e) {
Node<E> newNode = new Node<E>(e); // Create a new for element e
if (tail == null) {
head = tail = newNode; // The new node is the only node in list
}
else {
tail.next = newNode;// Link the new with the last node
newNode.previous = tail;
tail = tail.next; // tail now points to the last node
}
size++; // Increase size
}
#Override /** Add a new element at the specified index
* in this list. The index of the head element is 0 */
public void add(int index, E e) {
if (index == 0) {
addFirst(e);
}
else if (index >= size) {
addLast(e);
}
else {
Node<E> current = tail;
for (int i = size - 1; i > index; i--) {
current = current.previous;
}
Node<E> temp = current.next;
current.next = new Node<E>(e);
(current.next).previous = current;
(current.next).next = temp;
size++;
}
}
/** Remove the head node and
* return the object that is contained in the removed node. */
public E removeFirst() {
if (size == 0) {
return null;
}
else {
Node<E> temp = head;
head = head.next;
head.previous = null;
size--;
if (head == null) {
tail = null;
}
return temp.element;
}
}
/** Remove the last node and
* return the object that is contained in the removed node. */
public E removeLast() {
if (size == 0) {
return null;
}
else if (size == 1) {
Node<E> temp = head;
head = tail = null;
size = 0;
return temp.element;
}
else {
Node<E> temp = tail;
tail = tail.previous;
tail.next = null;
size--;
return temp.element;
}
}
#Override /** Remove the element at the specified position in this
* list. Return the element that was removed from the list. */
public E remove(int index) {
if (index < 0 || index >= size) {
return null;
}
else if (index == 0) {
return removeFirst();
}
else if (index == size - 1) {
return removeLast();
}
else {
Node<E> previous = tail;
for (int i = size - 1; i > index; i--) {
previous = previous.previous;
}
Node<E> current = previous.next;
(current.next).previous = previous;
previous.next = current.next;
size--;
return current.element;
}
}
#Override /** Override toString() to return elements in the list */
public String toString() {
StringBuilder result = new StringBuilder("[");
Node<E> current = tail;
for (int i = size - 1; i > 0; i--) {
result.append(current.element);
current = current.previous;
if (current != null) {
result.append(" ,"); // Separate two elements with a comma
}
else {
result.append("["); // Insert the closing ] in the string
}
}
return result.toString();
}
#Override /** Clear the list */
public void clear() {
size = 0;
head = tail = null;
}
#Override /** Override iterator() defined in Iterable */
public ListIterator<E> listIterator() {
Node<E> current = head; // Current index
return list.listIterator();
}
#Override /** Override iterator() defined in Iterable */
public ListIterator<E> listIterator(int index) {
Node<E> current = head; // Current index
for (int i = 0; i < index; i++) { // sets current int to the parameter
current = current.next;
}
return list.listIterator();
}
#Override
public int size()
{
return size;
}
public class Node<E> {
E element;
Node<E> next;
Node<E> previous;
public Node(E element) {
this.element = element;
}
}
}
This is my original class, I will include my test case below but first let me explain my problem. I am trying to create a Doubly linked list and iterate backwards through it. However I am getting a Null Pointer Exception by just adding elements to the list. I have looked over the section of code for my addFirst method for about 2 hours now and don't see any logic errors(doesn't mean there arent any), please help!
Here is my test case as promised.
public class TestMyLinkedList {
/** Main method */
public static void main(String[] args) {
// Create a list for strings
MyTwoWayLinkedList<String> list = new MyTwoWayLinkedList<String>();
// Add elements to the list
list.add("America"); // Add it to the list
System.out.println("(1) " + list);
list.add(0, "Canada"); // Add it to the beginning of the list
System.out.println("(2) " + list);
list.add("Russia"); // Add it to the end of the list
System.out.println("(3) " + list);
list.addLast("France"); // Add it to the end of the list
System.out.println("(4) " + list);
list.add(2, "Germany"); // Add it to the list at index 2
System.out.println("(5) " + list);
list.add(5, "Norway"); // Add it to the list at index 5
System.out.println("(6) " + list);
list.add(0, "Poland"); // Same as list.addFirst("Poland")
System.out.println("(7) " + list);
// Remove elements from the list
list.remove(0); // Same as list.remove("Australia") in this case
System.out.println("(8) " + list);
list.remove(2); // Remove the element at index 2
System.out.println("(9) " + list);
list.remove(list.size() - 1); // Remove the last element
System.out.print("(10) " + list + "\n(11) ");
for (String s: list)
System.out.print(s.toUpperCase() + " ");
list.clear();
System.out.println("\nAfter clearing the list, the list size is "
+ list.size());
}
}
I'm not completely sure why you are using a LinkedList within your own implementation of a Double Linked List. In regards to your question about your addFirst method however, I have the following comments and an example of how I would approach this solution.
Head is null when you call the addFirst method.
Head has not been initialized as a new Node.
Therefore newNode.next = head; is actually newNode.next = null; There is your null pointer exception, I would imagine!
public void addFirst (E e)
{
Node<E> newNode = new Node<E>(e); //create new node
if (head != null){ //if head exists
newNode.next = head; //the new node's next link becomes the old head
}
head = newNode; //the new head is the new node
if (tail == null){ //if the tail is non existent ie head the only object in list
tail = head; //the head and the tail are the same
head.next = tail; //the 'next' value of head will be tail
}
head.prev = tail; //the previous node to head will always be tail
size++;
}
}

Exporting a non public Type through public API

I am trying to follow Trees tutorial at: http://cslibrary.stanford.edu/110/BinaryTrees.html
Here is the code I have written so far:
package trees.bst;
import java.util.ArrayList;
import java.util.List;
import java.util.StringTokenizer;
/**
*
* #author sachin
*/
public class BinarySearchTree {
Node root = null;
class Node {
Node left = null;
Node right = null;
int data = 0;
public Node(int data) {
this.left = null;
this.right = null;
this.data = data;
}
}
public void insert(int data) {
root = insert(data, root);
}
public boolean lookup(int data) {
return lookup(data, root);
}
public void buildTree(int numNodes) {
for (int i = 0; i < numNodes; i++) {
int num = (int) (Math.random() * 10);
System.out.println("Inserting number:" + num);
insert(num);
}
}
public int size() {
return size(root);
}
public int maxDepth() {
return maxDepth(root);
}
public int minValue() {
return minValue(root);
}
public int maxValue() {
return maxValue(root);
}
public void printTree() { //inorder traversal
System.out.println("inorder traversal:");
printTree(root);
System.out.println("\n--------------");
}
public void printPostorder() { //inorder traversal
System.out.println("printPostorder traversal:");
printPostorder(root);
System.out.println("\n--------------");
}
public int buildTreeFromOutputString(String op) {
root = null;
int i = 0;
StringTokenizer st = new StringTokenizer(op);
while (st.hasMoreTokens()) {
String stNum = st.nextToken();
int num = Integer.parseInt(stNum);
System.out.println("buildTreeFromOutputString: Inserting number:" + num);
insert(num);
i++;
}
return i;
}
public boolean hasPathSum(int pathsum) {
return hasPathSum(pathsum, root);
}
public void mirror() {
mirror(root);
}
public void doubleTree() {
doubleTree(root);
}
public boolean sameTree(BinarySearchTree bst) { //is this tree same as another given tree?
return sameTree(this.root, bst.getRoot());
}
public void printPaths() {
if (root == null) {
System.out.println("print path sum: tree is empty");
}
List pathSoFar = new ArrayList();
printPaths(root, pathSoFar);
}
///-------------------------------------------Public helper functions
public Node getRoot() {
return root;
}
//Exporting a non public Type through public API
///-------------------------------------------Helper Functions
private boolean isLeaf(Node node) {
if (node == null) {
return false;
}
if (node.left == null && node.right == null) {
return true;
}
return false;
}
///-----------------------------------------------------------
private boolean sameTree(Node n1, Node n2) {
if ((n1 == null && n2 == null)) {
return true;
} else {
if ((n1 == null || n2 == null)) {
return false;
} else {
if ((n1.data == n2.data)) {
return (sameTree(n1.left, n2.left) && sameTree(n1.right, n2.right));
}
}
}
return false;
}
private void doubleTree(Node node) {
//create a copy
//bypass the copy to continue looping
if (node == null) {
return;
}
Node copyNode = new Node(node.data);
Node temp = node.left;
node.left = copyNode;
copyNode.left = temp;
doubleTree(copyNode.left);
doubleTree(node.right);
}
private void mirror(Node node) {
if (node == null) {
return;
}
Node temp = node.left;
node.left = node.right;
node.right = temp;
mirror(node.left);
mirror(node.right);
}
private void printPaths(Node node, List pathSoFar) {
if (node == null) {
return;
}
pathSoFar.add(node.data);
if (isLeaf(node)) {
System.out.println("path in tree:" + pathSoFar);
pathSoFar.remove(pathSoFar.lastIndexOf(node.data)); //only the current node, a node.data may be duplicated
return;
} else {
printPaths(node.left, pathSoFar);
printPaths(node.right, pathSoFar);
}
}
private boolean hasPathSum(int pathsum, Node node) {
if (node == null) {
return false;
}
int val = pathsum - node.data;
boolean ret = false;
if (val == 0 && isLeaf(node)) {
ret = true;
} else if (val == 0 && !isLeaf(node)) {
ret = false;
} else if (val != 0 && isLeaf(node)) {
ret = false;
} else if (val != 0 && !isLeaf(node)) {
//recurse further
ret = hasPathSum(val, node.left) || hasPathSum(val, node.right);
}
return ret;
}
private void printPostorder(Node node) { //inorder traversal
if (node == null) {
return;
}
printPostorder(node.left);
printPostorder(node.right);
System.out.print(" " + node.data);
}
private void printTree(Node node) { //inorder traversal
if (node == null) {
return;
}
printTree(node.left);
System.out.print(" " + node.data);
printTree(node.right);
}
private int minValue(Node node) {
if (node == null) {
//error case: this is not supported
return -1;
}
if (node.left == null) {
return node.data;
} else {
return minValue(node.left);
}
}
private int maxValue(Node node) {
if (node == null) {
//error case: this is not supported
return -1;
}
if (node.right == null) {
return node.data;
} else {
return maxValue(node.right);
}
}
private int maxDepth(Node node) {
if (node == null || (node.left == null && node.right == null)) {
return 0;
}
int ldepth = 1 + maxDepth(node.left);
int rdepth = 1 + maxDepth(node.right);
if (ldepth > rdepth) {
return ldepth;
} else {
return rdepth;
}
}
private int size(Node node) {
if (node == null) {
return 0;
}
return 1 + size(node.left) + size(node.right);
}
private Node insert(int data, Node node) {
if (node == null) {
node = new Node(data);
} else if (data <= node.data) {
node.left = insert(data, node.left);
} else {
node.right = insert(data, node.right);
}
//control should never reach here;
return node;
}
private boolean lookup(int data, Node node) {
if (node == null) {
return false;
}
if (node.data == data) {
return true;
}
if (data < node.data) {
return lookup(data, node.left);
} else {
return lookup(data, node.right);
}
}
public static void main(String[] args) {
BinarySearchTree bst = new BinarySearchTree();
int treesize = 5;
bst.buildTree(treesize);
//treesize = bst.buildTreeFromOutputString("4 4 4 6 7");
treesize = bst.buildTreeFromOutputString("3 4 6 3 6");
//treesize = bst.buildTreeFromOutputString("10");
for (int i = 0; i < treesize; i++) {
System.out.println("Searching:" + i + " found:" + bst.lookup(i));
}
System.out.println("tree size:" + bst.size());
System.out.println("maxDepth :" + bst.maxDepth());
System.out.println("minvalue :" + bst.minValue());
System.out.println("maxvalue :" + bst.maxValue());
bst.printTree();
bst.printPostorder();
int pathSum = 10;
System.out.println("hasPathSum " + pathSum + ":" + bst.hasPathSum(pathSum));
pathSum = 6;
System.out.println("hasPathSum " + pathSum + ":" + bst.hasPathSum(pathSum));
pathSum = 19;
System.out.println("hasPathSum " + pathSum + ":" + bst.hasPathSum(pathSum));
bst.printPaths();
bst.printTree();
//bst.mirror();
System.out.println("Tree after mirror function:");
bst.printTree();
//bst.doubleTree();
System.out.println("Tree after double function:");
bst.printTree();
System.out.println("tree size:" + bst.size());
System.out.println("Same tree:" + bst.sameTree(bst));
BinarySearchTree bst2 = new BinarySearchTree();
bst2.buildTree(treesize);
treesize = bst2.buildTreeFromOutputString("3 4 6 3 6");
bst2.printTree();
System.out.println("Same tree:" + bst.sameTree(bst2));
System.out.println("---");
}
}
Now the problem is that netbeans shows Warning: Exporting a non public Type through public API for function getRoot().
I write this function to get root of tree to be used in sameTree() function, to help comparison of "this" with given tree.
Perhaps this is a OOP design issue... How should I restructure the above code that I do not get this warning and what is the concept I am missing here?
The issue here is that some code might call getRoot() but won't be able to use it's return value since you only gave package access to the Node class.
Make Node a top level class with its own file, or at least make it public
I don't really understand why you even created the getRoot() method. As long as you are inside your class you can even access private fields from any other object of the same class.
So you can change
public boolean sameTree(BinarySearchTree bst) { //is this tree same as another given tree?
return sameTree(this.root, bst.getRoot());
}
to
public boolean sameTree(BinarySearchTree bst) { //is this tree same as another given tree?
return sameTree(this.root, bst.root);
}
I would also add a "short path" for the case you pass the same instance to this method:
public boolean sameTree(BinarySearchTree bst) { //is this tree same as another given tree?
if (this == bst) {
return true;
}
return sameTree(this.root, bst.root);
}