Right Rotation Linked List Recursively - java

I need to create a method to rotate or shift elements in a LinkedList which is called ListItem for my program to the right recursively. For example, I have the List 1->2->3->4 after the method it is 4->1->2->3. The Method should return the rotated List.
So, this is what could be helpful for the method:
public class ListItem<T>
{
public T key;
public ListItem<T> next;
/**
* Constructor of this Class
*
* #param key
* the key of the ListItemAbstract
*/
public ListItem(T key)
{
this.key = key;
}
#SuppressWarnings("unchecked")
#Override
public boolean equals(Object obj)
{
if (obj == null || obj.getClass() != this.getClass())
return false;
if (this.key == null && ((ListItem<T>) obj).key == null)
return true;
if (this.key != null && this.key.equals(((ListItem<T>) obj).key))
{
if (this.next == null)
if (((ListItem<T>) obj).next == null)
return true;
else
return false;
return this.next.equals(((ListItem<T>) obj).next);
}
else
return false;
}
/**
* This methode returns the Element on the given position.
*
* #param pos
* the position to return the key from. Position 1 means the current element
* #return the key of the element at pos
* #throws IllegalArgumentException
* if the position ist not in the list
*/
public T get(int pos) throws IllegalArgumentException
{
// recursion stop
if (pos == 1)
{
return this.key;
}
else if (pos > 1)
{
// recursion start: call this method again for the next element of the list,
// but check for NullpointerException first
if (next != null)
{
return next.get(pos - 1);
}
else
{
//
throw new IllegalArgumentException("the index is greater than the number of elements in this list");
}
}
else
{
throw new IllegalArgumentException("the position is less than 1, but must be equal to or higher than 1");
}
}
/**
* This method returns the size of the List
*
* #return the size of this list
*/
public int getSize()
{
if (this.key == null && this.next == null)
{
// recursion stop: no next element and this key is null -> don't add it to the size
return 0;
}
else if (this.next == null) // deleting this if-case causes a NullpointerException
{
// recursion stop: no next element, but this key is not null -> add it to the size
return 1;
}
else
{
// recursion start: recall this method for the next element and increase the size by one
return this.next.getSize() + 1;
}
}
/**
* Inserts an key into this list.
*
* #param key
* the key to insert.
* #throws IllegalArgumentException
* if key is null
*/
public void insert(T key) throws IllegalArgumentException
{
if (key == null)
{
throw new IllegalArgumentException("Cannot insert null");
}
else if (this.key == null && this.next == null)
{
this.key = key;
}
else
{
ListItem<T> p = this;
while (p.next != null)
{
p = p.next;
}
p.next = new ListItem<T>(key);
}
}
}
This is what I have so far for the method:
/**
* The method shifts the elements of the List to the right.
*
* #param lst
* the list to work on
* #return the new list
*/
public ListItem<T> ringShiftRight(ListItem<T> lst) {
if (lst == null) {
return null;
}
if (lst.next == null) {
return lst;
}
// TODO Here I have no Idea how to create the method any further
}

Traverse ListItem till last item and that will become ListItem to be returned. Add input lstto next of next.
ListItem<T> returnList = this.ringShiftRight(lst.next);
lst.next.next = lst;
lst.next = null;
return returnList;

Related

swap two nodes in singly linked lists using method in java

package linkedlists;
public class SinglyLinkedList<E> implements Cloneable {
//---------------- nested Node class ----------------
/**
* Node of a singly linked list, which stores a reference to its
* element and to the subsequent node in the list (or null if this
* is the last node).
*/
private static class Node<E> {
/** The element stored at this node */
private E element; // reference to the element stored at this node
/** A reference to the subsequent node in the list */
private Node<E> next; // reference to the subsequent node in the list
/**
* Creates a node with the given element and next node.
*
* #param e the element to be stored
* #param n reference to a node that should follow the new node
*/
public Node(E e, Node<E> n) {
element = e;
next = n;
}
// Accessor methods
/**
* Returns the element stored at the node.
* #return the element stored at the node
*/
public E getElement() { return element; }
/**
* Returns the node that follows this one (or null if no such node).
* #return the following node
*/
public Node<E> getNext() { return next; }
// Modifier methods
/**
* Sets the node's next reference to point to Node n.
* #param n the node that should follow this one
*/
public void setNext(Node<E> n) { next = n; }
} //----------- end of nested Node class -----------
// instance variables of the SinglyLinkedList
/** The head node of the list */
private Node<E> head = null; // head node of the list (or null if empty)
/** The last node of the list */
private Node<E> tail = null; // last node of the list (or null if empty)
/** Number of nodes in the list */
private int size = 0; // number of nodes in the list
/** Constructs an initially empty list. */
public SinglyLinkedList() { } // constructs an initially empty list
// access methods
/**
* Returns the number of elements in the linked list.
* #return number of elements in the linked list
*/
public int size() { return size; }
/**
* Tests whether the linked list is empty.
* #return true if the linked list is empty, false otherwise
*/
public boolean isEmpty() { return size == 0; }
/**
* Returns (but does not remove) the first element of the list
* #return element at the front of the list (or null if empty)
*/
public E first() { // returns (but does not remove) the first element
if (isEmpty()) return null;
return head.getElement();
}
/**
* Returns (but does not remove) the last element of the list.
* #return element at the end of the list (or null if empty)
*/
public E last() { // returns (but does not remove) the last element
if (isEmpty()) return null;
return tail.getElement();
}
// update methods
/**
* Adds an element to the front of the list.
* #param e the new element to add
*/
public void addFirst(E e) { // adds element e to the front of the list
head = new Node<>(e, head); // create and link a new node
if (size == 0)
tail = head; // special case: new node becomes tail also
size++;
}
/**
* Adds an element to the end of the list.
* #param e the new element to add
*/
public void addLast(E e) { // adds element e to the end of the list
Node<E> newest = new Node<>(e, null); // node will eventually be the tail
if (isEmpty())
head = newest; // special case: previously empty list
else
tail.setNext(newest); // new node after existing tail
tail = newest; // new node becomes the tail
size++;
}
/**
* Removes and returns the first element of the list.
* #return the removed element (or null if empty)
*/
public E removeFirst() { // removes and returns the first element
if (isEmpty()) return null; // nothing to remove
E answer = head.getElement();
head = head.getNext(); // will become null if list had only one node
size--;
if (size == 0)
tail = null; // special case as list is now empty
return answer;
}
#SuppressWarnings({"unchecked"})
public boolean equals(Object o) {
if (o == null) return false;
if (getClass() != o.getClass()) return false;
SinglyLinkedList other = (SinglyLinkedList) o; // use nonparameterized type
if (size != other.size) return false;
Node walkA = head; // traverse the primary list
Node walkB = other.head; // traverse the secondary list
while (walkA != null) {
if (!walkA.getElement().equals(walkB.getElement())) return false; //mismatch
walkA = walkA.getNext();
walkB = walkB.getNext();
}
return true; // if we reach this, everything matched successfully
}
#SuppressWarnings({"unchecked"})
public SinglyLinkedList<E> clone() throws CloneNotSupportedException {
// always use inherited Object.clone() to create the initial copy
SinglyLinkedList<E> other = (SinglyLinkedList<E>) super.clone(); // safe cast
if (size > 0) { // we need independent chain of nodes
other.head = new Node<>(head.getElement(), null);
Node<E> walk = head.getNext(); // walk through remainder of original list
Node<E> otherTail = other.head; // remember most recently created node
while (walk != null) { // make a new node storing same element
Node<E> newest = new Node<>(walk.getElement(), null);
otherTail.setNext(newest); // link previous node to this one
otherTail = newest;
walk = walk.getNext();
}
}
return other;
}
public int hashCode() {
int h = 0;
for (Node walk=head; walk != null; walk = walk.getNext()) {
h ^= walk.getElement().hashCode(); // bitwise exclusive-or with element's code
h = (h << 5) | (h >>> 27); // 5-bit cyclic shift of composite code
}
return h;
}
/**
* Produces a string representation of the contents of the list.
* This exists for debugging purposes only.
*/
public String toString() {
StringBuilder sb = new StringBuilder("(");
Node<E> walk = head;
while (walk != null) {
sb.append(walk.getElement());
if (walk != tail)
sb.append(", ");
walk = walk.getNext();
}
sb.append(")");
return sb.toString();
}
public void swapNodes(Node<E> num1, Node<E> num2) {
Node<E> num1Prev = this.head;
Node<E> num2Prev = this.head;
if (num1 == num2 )
return ;
while((num1Prev != null)&&(num1Prev.getNext() != num1)){
num1Prev = num1Prev.getNext();
}
while((num2Prev != null)&&(num2Prev.getNext() != num2)){
num2Prev = num2Prev.getNext();
}
if(num2Prev == num1) {
num1.setNext(num2.getNext());
num2.setNext(num1);
num1Prev.setNext(num2);
}
else if(num1Prev == num2) {
num2.setNext(num1.getNext());
num1.setNext(num2);
num2Prev.setNext(num1);
}
else {
Node<E> tmp = num1.getNext();
num1.setNext(num2.getNext());
num2.setNext(tmp);
num1Prev.setNext(num2);
num2Prev.setNext(num1);
}
}
//main method
public static void main(String[] args)
{
SinglyLinkedList<String> list = new SinglyLinkedList<String>();
list.addFirst("MSP");
list.addLast("ATL");
list.addLast("BOS");
//
list.addFirst("LAX");
System.out.println(list);
//
SinglyLinkedList<String> swap = new SinglyLinkedList<String>();
swap.addFirst("1");
swap.addLast("2");
swap.addLast("3");
swap.addLast("4");
swap.addLast("5");
System.out.println("Original list: " + swap);
swap.swapNodes("2","5");
System.out.println("After Swapping list: " + swap);
}
}
Task: In this exercise, you will add a method swapNodes to SinglyLinkedList class from week 2 lecture examples. This method should swap two nodes node1 and node2 (and not just their contents) given references only to node1 and node2. The new method should check if node1 and node2 are the same nodes, etc. Write the main method to test the swapNodes method. Hint: You may need to traverse the list.
I made this method
public void swapNodes(Node<E> num1, Node<E> num2) {
Node<E> num1Prev = this.head;
Node<E> num2Prev = this.head;
if (num1 == num2 )
return ;
while((num1Prev != null)&&(num1Prev.getNext() != num1)){
num1Prev = num1Prev.getNext();
}
while((num2Prev != null)&&(num2Prev.getNext() != num2)){
num2Prev = num2Prev.getNext();
}
if(num2Prev == num1) {
num1.setNext(num2.getNext());
num2.setNext(num1);
num1Prev.setNext(num2);
}
else if(num1Prev == num2) {
num2.setNext(num1.getNext());
num1.setNext(num2);
num2Prev.setNext(num1);
}
else {
Node<E> tmp = num1.getNext();
num1.setNext(num2.getNext());
num2.setNext(tmp);
num1Prev.setNext(num2);
num2Prev.setNext(num1);
}
}
And then, created an instance to check if it's work, but it is showing me an error on here swap.swapNodes("2", "5");
Does anyone know what is the problem? Thank you
It's throwing error, because in your swapNodes function, you expect two parameters of type Node<E> passed, but you are passing E (String). So you have to change signature of the function or pass Node<E> that you added to your List.
Here's how you could do your swapNodes function with parameters of type E:
public void swapNodes(E element1, E element2) {
if (element1 == element2 || element1 == null || element2 == null || isEmpty()) return;
Node<E> num1 = findNode(element1);
Node<E> num2 = findNode(element2);
if (num1 == null || num2 == null) return;
Node<E> num1Prev = this.head;
Node<E> num2Prev = this.head;
while(num1Prev != null && num1Prev.getNext() != num1){
num1Prev = num1Prev.getNext();
}
while(num2Prev != null && num2Prev.getNext() != num2){
num2Prev = num2Prev.getNext();
}
if (num1Prev.getNext() == null || num2Prev.getNext() == null) return;
if (num2Prev.equals(num1)) {
num1.setNext(num2.getNext());
num2.setNext(num1);
num1Prev.setNext(num2;
} else if (num1Prev.equals(num2)) {
num2.setNext(num1.getNext());
num1.setNext(num2);
num2Prev.setNext(num1);
} else {
Node<E> tmp = num1.getNext();
num1.setNext(num2.getNext());
num2.setNext(tmp);
num1Prev.setNext(num2);
num2Prev.setNext(num1);
}
}
The findNode function could look like this:
public Node<E> findNode(E element) {
if (isEmpty()) return null;
Node<E> node = this.head;
while(node != null) {
if (node.getElement() == element) return node;
}
return null;
}

AVL Trees: How to properly rebalance?

I'm writing an AVL Tree class and my professor has included some tests for our code. I have passed all the tests except three, and the three tests I'm failing seem to indicate that when elements are added to or removed from the tree, the tree doesn't balance itself when necessary. I've been trying to debug it, but I just can't seem to find the error. Could someone please point out what I'm missing?
EDIT:
Failed tests:
RemoveRoot - removes the root of the AVL tree and replaces it with its successor. AddManySingle - adds several elements and forces single rotation. AddManyDouble - adds several elements and forces double rotation.
private int count, height;
private AVLNode < E > root;
public AVLTree() {
root = null;
count = 0;
height = 0;
}
//the private inner Node class
private class AVLNode < E > {
private int height, bf;
private E data;
private AVLNode < E > left, right;
public AVLNode() {
data = null;
left = right = null;
bf = 0;
height = 0;
}
public AVLNode(E data) {
this.data = data;
left = right = null;
bf = 0;
height = 0;
}
public E getData() {
return data;
}
public void setData(E data) {
this.data = data;
}
public AVLNode < E > getLeft() {
return left;
}
public void setLeft(AVLNode < E > left) {
this.left = left;
}
public AVLNode < E > getRight() {
return right;
}
public void setRight(AVLNode < E > right) {
this.right = right;
}
public int getBF() {
return bf;
}
public void setBF() {
if (right == null && left == null) {
bf = 0;
} else if (right == null) {
bf = this.getLeft().getHeight();
} else if (left == null) {
bf = 0 - this.getRight().getHeight();
} else {
this.bf = this.getLeft().getHeight() - this.getRight().getHeight();
}
}
public void setBF(int theBalanceFactor) {
bf = theBalanceFactor;
}
/**
* The getHeight method computes the height of an AVL tree.
* #return The height of the AVL tree.
*/
public int getHeight() {
return this == null ? -1 : this.height;
}
public void setHeight() {
int leftHeight = (left == null) ? -1 : left.getHeight();
int rightHeight = (right == null) ? -1 : right.getHeight();
height = 1 + Math.max(leftHeight, rightHeight);
}
public void setHeight(int theHeight) {
height = theHeight;
}
}
//the private inner Iterator class
private class AVLIterator implements Iterator < E > {
private AVLNode < E > nextNode;
private Stack < AVLNode < E >> stack;
public AVLIterator() {
nextNode = root;
stack = new Stack < AVLNode < E >> ();
while (root != null) {
stack.push(root);
root = root.getLeft();
}
}
//Returns true if the iteration has more datas.
#Override
public boolean hasNext() {
return !stack.isEmpty();
}
//Returns the next data in the iteration.
#Override
public E next() {
if (!hasNext()) {
throw new NoSuchElementException("No next element.");
}
AVLNode < E > node = stack.pop();
E result = node.data;
if (node.right != null) {
node = node.right;
while (node != null) {
stack.push(node);
node = node.left;
}
}
return result;
}
//Removes the last data in the iteration.
#Override
public void remove() {
throw new UnsupportedOperationException("Invalid operation for support list.");
}
}
/**
* Rotate binary tree node that has a right child.
* Update heights, then return new root.
* n1 is the imbalanced node
*/
private AVLNode < E > rotateWithRightChild(AVLNode < E > n1) {
AVLNode < E > n2 = n1.right;
n1.right = n2.left;
n2.left = n1;
return n2;
}
/**
* Rotate binary tree node that has a left child.
* Update heights, then return new root.
*/
private AVLNode < E > rotateWithLeftChild(AVLNode < E > n2) {
AVLNode < E > n1 = n2.left;
n2.left = n1.right;
n1.right = n2;
return n1;
}
/**
* Double rotate binary tree node: first left child
* with its right child; then node n3 with new left child.
* Update heights, then return new root.
*/
private AVLNode < E > doubleWithLeftChild(AVLNode < E > n3) {
n3.left = rotateWithRightChild(n3.left);
return rotateWithLeftChild(n3);
}
/**
* Double rotate binary tree node: first right child
* with its left child; then node n1 with new right child.
* Update heights, then return new root.
*/
private AVLNode < E > doubleWithRightChild(AVLNode < E > n1) {
n1.right = rotateWithLeftChild(n1.right);
return rotateWithRightChild(n1);
}
//updates height and balance factor
private void updateHeightAndBF(AVLNode < E > node) {
int leftHeight, rightHeight, bf = 0, height = 0;
if (node != null) {
if (node.getLeft() == null) {
leftHeight = -1;
} else {
leftHeight = node.left.height;
}
if (node.getRight() == null) {
rightHeight = -1;
} else {
rightHeight = node.right.height;
}
/*if (leftHeight >= rightHeight) {
height = leftHeight + 1;
} else if (rightHeight >= leftHeight) {
height = rightHeight + 1;
}*/
height = Math.max(leftHeight, rightHeight) + 1;
bf = leftHeight - rightHeight;
node.setHeight(height);
node.setBF(bf);
} else {
height = -1;
}
}
/**
* private helper method.
* Balances a node by updating balance
* factor when a node is removed from
* or added to the AVL tree.
*
* #param node the node that is being balanced
*/
private AVLNode < E > balance(AVLNode < E > node) {
int hLeft, hRight;
if (node == null) {
return node;
}
if (node.bf == 2) {
if (node.left.bf == 1) {
node.left = rotateWithLeftChild(node);
} else if (node.left.bf == -1) {
node.left = doubleWithLeftChild(node);
}
} else if (node.bf == -2) {
if (node.right.bf < 0) {
node.right = rotateWithRightChild(node);
} else if (node.right.bf == -1) {
node.right = doubleWithRightChild(node);
}
}
return node;
}
/**
* Adds the item to the tree. Duplicate items and null items should not be added. O(log n)
*
* #param item the item to add
* #return true if item added, false if it was not
*/
#Override
public boolean add(E item) { // TODO
int theSize = size();
if (root == null && item != null) { //null check here for item
root = new AVLNode < E > (item);
count++;
return true;
} else if (item == null) {
return false;
} else {
add(root, item);
root = balance(root);
}
return (count != theSize);
}
/**
* private helper method for the add() method.
* Adds the item to the tree. Duplicate items and null items should not be added.
* Runs in O(log n) expected time, may be linear time in worst case
*
* #param value the item to add
* #return true if item added, false if it was not
*/
private boolean add(AVLNode < E > node, E value) { // TODO
if (value.equals(node.getData()) || value == null) {
//if it's a duplicate or null
return false;
}
if (value.compareTo(node.data) < 0) {
AVLNode < E > left = node.left;
if (left == null) {
node.left = new AVLNode < E > (value);
count++;
updateHeightAndBF(node);
balance(node);
return true;
} else updateHeightAndBF(node);
balance(node);
return add(left, value);
} else if (value.compareTo(node.data) > 0) {
AVLNode < E > right = node.right;
if (right == null) {
node.right = new AVLNode < E > (value);
count++;
updateHeightAndBF(node);
balance(node);
return true;
} else {
updateHeightAndBF(node);
balance(node);
return add(right, value);
}
}
return false;
}
/**
* returns the maximum data held in the tree. null if tree is empty.
* runs in O(log n) expected, may be linear in worst case
*
* #return maximum item or null if empty
*/
#Override
public E max() {
if (isEmpty()) {
return null;
}
return max(root).data;
}
/**
* a private helper method for the max() method.
*
* #return maximum Node or null if empty
*/
private AVLNode < E > max(AVLNode < E > x) {
if (x.getRight() == null) { //the rightmost node from the root
//is larger than the root, which is larger than the leftmost
//node from the root. so, if the rightmost node is null,
// that means the root node is the maximum data in the tree
return x;
} else {
return max(x.getRight());
}
}
/**
* returns the number of items in the tree O(1) with variable
*
* #return the number of items in the tree
*/
#Override
public int size() {
return count;
}
/**
* O(1)
* #return true if tree has no datas, false if tree has anything in it.
*/
#Override
public boolean isEmpty() {
return size() == 0;
}
/**
* runs in O(n) worst case, and O(log n) average case.
* #return the minimum data in the tree or null if empty
*/
#Override
public E min() {
if (isEmpty()) {
return null;
}
return min(root).data;
}
/**
* private helper method for the min() method
*
* #return the minimum Node in the tree or null if empty
*/
private AVLNode < E > min(AVLNode < E > y) {
if (y == null) {
return null;
} else if (y.left == null) { //the leftmost node from the root
//is smaller than the root, which is smaller than the rightmost
//node. so, if the leftmost node is null,
// that means the root node is the minimum data in the tree
return y;
} else {
return min(y.left);
}
}
/**
* Checks for the given item in the tree. O(log n)
*
* #param item the item to look for
* #return true if item is in tree, false otherwise
*/
#Override
public boolean contains(E item) {
return contains(root, item);
}
/**
* private helper method for the contains() methods
* Checks for the given item in the tree.
* runs in O(log n) expected, may be linear in worst case
*
* #param root the starting point
* #param item the item to look for
* #return true if item is in tree, false otherwise
*/
private boolean contains(AVLNode < E > root, E item) {
if (root == null || isEmpty()) {
return false;
}
if (item.compareTo(root.getData()) == 0) { //if item is
//equal to the data in the root Node, return true
return true;
} else {
if (item.compareTo(root.getData()) < 0) { //if item is less than data
AVLNode < E > left = root.getLeft(); //go to the left node
return (contains(left, item)); //call contains() method with the left node
} else if (item.compareTo(root.getData()) > 0) { //if item is more than data
AVLNode < E > right = root.getRight(); //go to the right node
return (contains(right, item)); //call contains() method with the right node
} else {
return true;
}
}
}
/**
* removes the given item from the tree O(log n). if the item is found
* and removed, balance the tree
*
* #param item the item to remove
* #return true if item removed, false if item not found
*/
#Override
public boolean remove(E item) {
int theSize = size();
root = remove(root, item);
return (count != theSize);
}
/**
* private helper method for the remove() method
* removes the given item from the tree
* runs in O(log n) expected, may be linear in worst case
* uses in-order successor
*
* #param node the starting point
* #param item the item to remove
* #return the node if the specified is node in the tree, null otherwise
*/
private AVLNode < E > remove(AVLNode < E > node, E item) { //TODO
if (node == null || item == null) {
return null;
}
if (root == null) {
return root;
}
if (item.compareTo(node.data) < 0) {
updateHeightAndBF(node);
balance(node);
node.left = remove(node.left, item);
} else if (item.compareTo(node.data) > 0) {
updateHeightAndBF(node);
balance(node);
node.right = remove(node.right, item);
} else if (node.left != null && node.right != null) { //two child nodes
AVLNode < E > succ = min(node.right);
node.data = succ.data;
updateHeightAndBF(node);
balance(node);
node.right = remove(node.right, node.data);
} else {
node = (node.left != null) ? node.left : node.right;
count--;
updateHeightAndBF(node);
return balance(node);
}
return node;
}
/**
* Runs in linear time, O(n)
* #return a list of the data in post-order traversal order
*/
#Override
public List < E > getPostOrder() {
List < E > postOrderList = new ArrayList < E > (size());
recPostOrder(root, postOrderList);
return postOrderList;
}
/**
* private helper method for the getPostOrder() method
* Runs in linear time, O(n)
*/
private void recPostOrder(AVLNode < E > theRoot, List < E > theList) {
if (theRoot != null) {
recPostOrder(theRoot.left, theList);
recPostOrder(theRoot.right, theList);
theList.add(theRoot.data);
}
}
/**
* Runs in linear time, O(n)
* #return a list of the data in pre-order traversal order
*/
#Override
public List < E > getPreOrder() {
List < E > preOrderList = new ArrayList < E > (size());
recPreOrder(root, preOrderList);
return preOrderList;
}
/**
* private helper method for the getPreOrder() method
* Runs in linear time, O(n)
*
*/
private void recPreOrder(AVLNode < E > theRoot, List < E > theList) {
if (theRoot != null) {
theList.add(theRoot.getData());
recPreOrder(theRoot.getLeft(), theList);
recPreOrder(theRoot.getRight(), theList);
}
}
/**
* Runs in linear time
* #return a list of the data in pre-order traversal order
*/
public List < E > getInOrder() {
List < E > inOrderList = new ArrayList < E > (size());
recInOrder(root, inOrderList);
return inOrderList;
}
/**
*
* private helper method for the getInOrder() method
* Runs in linear time
*
*/
private void recInOrder(AVLNode < E > theRoot, List < E > theList) {
if (theRoot != null) {
recInOrder(theRoot.left, theList);
theList.add(theRoot.data);
recInOrder(theRoot.right, theList);
}
}
/**
* Runs in linear time, O(n)
* #return a list of the data in level-order traversal order
*/
#Override
public List < E > getLevelOrder() {
List < E > data = new ArrayList < E > ();
Queue < AVLNode < E >> queue = new LinkedList < AVLNode < E >> ();
if (this.isEmpty()) {
return data;
} else {
queue.add(root);
}
while (!queue.isEmpty()) {
AVLNode < E > x = queue.remove();
if (x != null) {
data.add(x.getData());
if (x.getLeft() != null) {
queue.add(x.getLeft());
}
if (x.getRight() != null) {
queue.add(x.getRight());
}
}
}
return data;
}
/**
* O(1) [ignore garbage collection costs]
*
* Removes all the datas from this tree
*/
#Override
public void clear() {
root = null;
count = 0;
}
/**
* returns an iterator over this collection
* iterator is based on an in-order traversal
*/
#Override
public Iterator < E > iterator() {
return new AVLIterator();
}
}

How to use Java generics to avoid casting?

For the query, raised in link, Java generics is recommended to avoid difficulty in assessing run time type of an item.
After using Java generics in the below code, I do not see the incompatible type errors unlike before.
But a different compile time error at line 96 , DList1<int> l = new DList1<int>(); does not give any clue of the problem.
Error message is: Syntax error on token 'int'
/* DList1.java */
/**
* A DList1 is a mutable doubly-linked list. (No sentinel, not
* circularly linked.)
*/
public class DList1<T> {
/**
* head references the first node.
* tail references the last node.
*
* DO NOT CHANGE THE FOLLOWING FIELD DECLARATIONS.
*/
protected DListNode1<T> head;
protected DListNode1<T> tail;
protected long size;
/* DList1 invariants:
* 1) head.prev == null.
* 2) tail.next == null.
* 3) For any DListNode1 x in a DList, if x.next == y and x.next != null,
* then y.prev == x.
* 4) For any DListNode1 x in a DList, if x.prev == y and x.prev != null,
* then y.next == x.
* 5) The tail can be accessed from the head by a sequence of "next"
* references.
* 6) size is the number of DListNode1s that can be accessed from the
* head by a sequence of "next" references.
*/
/**
* DList1() constructor for an empty DList1.
*/
public DList1() {
this.head = null;
this.tail = null;
this.size = 0;
}
/**
* insertFront() inserts an item at the front of a DList1.
*/
public void insertFront(T item) {
if(this.head == null){
this.head = new DListNode1<T>(item);
this.tail = this.head;
}else{
DListNode1<T> newNode = new DListNode1<T>(item);
newNode.next = this.head;
this.head.prev = newNode;
this.head = newNode;
}
this.size++;
}
/**
* removeFront() removes the first item (and node) from a DList1. If the
* list is empty, do nothing.
*/
public void removeFront() {
if(this.size == 0){
return;
}else if(size ==1){
this.head = null;
this.tail = null;
}else{
this.head.next.prev = null;
this.head = this.head.next;
}
}
/**
* toString() returns a String representation of this DList.
*
* DO NOT CHANGE THIS METHOD.
*
* #return a String representation of this DList.
*/
public String toString() {
String result = "[ ";
DListNode1<T> current = head;
while (current != null) {
result = result + current.item + " ";
current = current.next;
}
return result + "]";
}
public static void main(String[] args) {
// DO NOT CHANGE THE FOLLOWING CODE.
DList1<int> l = new DList1<int>(); //Line 96
System.out.println("### TESTING insertFront ###\nEmpty list is " + l);
l.insertFront(9);
System.out.println("\nInserting 9 at front.\nList with 9 is " + l);
if (l.head == null) {
System.out.println("head is null.");
} else {
if (l.head.item != 9) { //Line 104
System.out.println("head.item is wrong.");
}
if (l.head.prev != null) {
System.out.println("head.prev is wrong.");
}
}
if (l.tail == null) {
System.out.println("tail is null.");
} else {
if (l.tail.item != 9) {
System.out.println("tail.item is wrong.");
}
if (l.tail.next != null) {
System.out.println("tail.next is wrong.");
}
}
if (l.size != 1) {
System.out.println("size is wrong.");
}
l.insertFront(8);
System.out.println("\nInserting 8 at front.\nList with 8 and 9 is " + l);
if (l.head == null) {
System.out.println("head is null.");
} else {
if (l.head.item != 8) {
System.out.println("head.item is wrong.");
}
if (l.head.prev != null) {
System.out.println("head.prev is wrong.");
}
if (l.head.next != l.tail) {
System.out.println("head.next is wrong.");
}
}
if (l.tail == null) {
System.out.println("tail is null.");
} else {
/*if (l.tail.item != 9) {
System.out.println("tail.item is wrong.");
}*/
if (l.tail.next != null) {
System.out.println("tail.next is wrong.");
}
if (l.tail.prev != l.head) {
System.out.println("tail.prev is wrong.");
}
}
if (l.size != 2) {
System.out.println("size is wrong.");
}
} /* end main() */
}
/* DListNode1.java */
/**
* A DListNode1 is a node in a DList1 (doubly-linked list).
*/
class DListNode1<T> {
/**
* item references the item stored in the current node.
* prev references the previous node in the DList.
* next references the next node in the DList.
*
* DO NOT CHANGE THE FOLLOWING FIELD DECLARATIONS.
*/
T item;
DListNode1<T> prev;
DListNode1<T> next;
/**
* DListNode1() constructor.
*/
DListNode1() {
this.item = null;
this.prev = null;
this.next = null;
}
DListNode1(T item) {
this.item = item;
this.prev = null;
this.next = null;
}
}
My question:
What is the meaning of this error at Line 96? How do i resolve this?
Note: using jre 1.6 update 45
In Java you can't parametrize a type with primitive values like int, so instead of:
DList1<int> l = new DList1<int>();
use wrapper classes:
DList1<Integer> l = new DList1<Integer>();

how to mofify linked list to handle double linked lists?

How do you implement a class SequenceDLList that defines a Sequence ADT as a double linked list?
I've been trying to modify the below code with single linked list....but not getting there.
This is supposed to work..
class SequenceListException extends Exception {
SequenceListException() {
super();
}
SequenceListException(String s) {
super(s);
}
}
*/
public class SequenceList
{
/**
* Member class Node encapsulates the nodes of the linked list in
* which the stack is stored. Each node contains a data item and a
* reference to another node - the next in the linked list.
*/
protected class Node
{
public Node(Object o)
{
this(o, null);
}
public Node(Object o, Node n)
{
datum = o;
next = n;
}
//The Node data structure consists of two object references.
//One for the datum contained in the node and the other for
//the next node in the list.
protected Object datum;
protected Node next;
}
//We use object references to the head and tail of the list (the head
//and tail of the sequence, respectively).
private Node listHead;
private Node listTail;
//Only require a single constructor, which sets both object
//references to null.
/**
* Constructs an empty sequence object.
*/
public SequenceList()
{
listHead = null;
listTail = null;
}
/**
* Adds a new item at the start of the sequence.
*/
public void insertFirst(Object o)
{
//There is a special case when the sequence is empty.
//Then the both the head and tail pointers needs to be
//initialised to reference the new node.
if(listHead == null) {
listHead = new Node(o, listHead);
listTail = listHead;
}
//In the general case, we simply add a new node at the start
//of the list via the head pointer.
else {
listHead = new Node(o, listHead);
}
}
/**
* Adds a new item at the end of the sequence.
*/
public void insertLast(Object o)
{
//There is a special case when the sequence is empty.
//Then the both the head and tail pointers needs to be
//initialised to reference the new node.
if(listHead == null) {
listHead = new Node(o, listHead);
listTail = listHead;
}
//In the general case, we simply add a new node to the end
//of the list via the tail pointer.
else {
listTail.next = new Node(o, listTail.next);
listTail = listTail.next;
}
}
/**
* Adds a new item at a specified position in the sequence.
*/
public void insert(Object o, int index) throws SequenceListException
{
//Check the index is positive.
if(index < 0) {
throw new SequenceListException("Indexed Element out of Range");
}
//There is a special case when the sequence is empty.
//Then the both the head and tail pointers needs to be
//initialised to reference the new node.
if(listHead == null) {
if(index == 0) {
listHead = new Node(o, listHead);
listTail = listHead;
}
else throw new SequenceListException("Indexed element is out of range");
}
//There is another special case for insertion at the head of
//the sequence.
else if(index == 0) {
listHead = new Node(o, listHead);
}
//In the general case, we need to chain down the linked list
//from the head until we find the location for the new
//list node. If we reach the end of the list before finding
//the specified location, we know that the given index was out
//of range and throw an exception.
else {
Node nodePointer = listHead;
int i = 1;
while(i < index) {
nodePointer = nodePointer.next;
i += 1;
if(nodePointer == null) {
throw new SequenceListException("Indexed Element out of Range");
}
}
//Now we've found the node before the position of the
//new one, so we 'hook in' the new Node.
nodePointer.next = new Node(o, nodePointer.next);
//Finally we need to check that the tail pointer is
//correct. Another special case occurs if the new
//node was inserted at the end, in which case, we need
//to update the tail pointer.
if(nodePointer == listTail) {
listTail = listTail.next;
}
}
}
/**
* Removes the item at the start of the sequence.
*/
public void deleteFirst() throws SequenceListException
{
//Check there is something in the sequence to delete.
if(listHead == null) {
throw new SequenceListException("Sequence Underflow");
}
//There is a special case when there is just one item in the
//sequence. Both pointers then need to be reset to null.
if(listHead.next == null) {
listHead = null;
listTail = null;
}
//In the general case, we just unlink the first node of the
//list.
else {
listHead = listHead.next;
}
}
/**
* Removes the item at the end of the sequence.
*/
public void deleteLast() throws SequenceListException
{
//Check there is something in the sequence to delete.
if(listHead == null) {
throw new SequenceListException("Sequence Underflow");
}
//There is a special case when there is just one item in the
//sequence. Both pointers then need to be reset to null.
if(listHead.next == null) {
listHead = null;
listTail = null;
}
//In the general case, we need to chain all the way down the
//list in order to reset the link of the second to last
//element to null.
else {
Node nodePointer = listHead;
while(nodePointer.next != listTail) {
nodePointer = nodePointer.next;
}
//Unlink the last node and reset the tail pointer.
nodePointer.next = null;
listTail = nodePointer;
}
}
/**
* Removes the item at the specified position in the sequence.
*/
public void delete(int index) throws SequenceListException
{
//Check there is something in the sequence to delete.
if(listHead == null) {
throw new SequenceListException("Sequence Underflow");
}
//Check the index is positive.
if(index < 0) {
throw new SequenceListException("Indexed Element out of Range");
}
//There is a special case when there is just one item in the
//sequence. Both pointers then need to be reset to null.
if(listHead.next == null) {
if(index == 0) {
listHead = null;
listTail = null;
} else throw new SequenceListException("Indexed element is out of range.");
}
//There is also a special case when the first element has to
//be removed.
else if(index == 0) {
deleteFirst();
}
//In the general case, we need to chain down the list to find
//the node in the indexed position.
else {
Node nodePointer = listHead;
int i = 1;
while(i < index) {
nodePointer = nodePointer.next;
i += 1;
if (nodePointer.next == null) {
throw new SequenceListException("Indexed Element out of Range");
}
}
//Unlink the node and reset the tail pointer if that
//node was the last one.
if(nodePointer.next == listTail) {
listTail = nodePointer;
}
nodePointer.next = nodePointer.next.next;
}
}
/**
* Returns the item at the start of the sequence.
*/
public Object first() throws SequenceListException
{
if(listHead != null) {
return listHead.datum;
}
else {
throw new SequenceListException("Indexed Element out of Range");
}
}
/**
* Returns the item at the end of the sequence.
*/
public Object last() throws SequenceListException
{
if(listTail != null) {
return listTail.datum;
}
else {
throw new SequenceListException("Indexed Element out of Range");
}
}
/**
* Returns the item at the specified position in the sequence.
*/
public Object element(int index) throws SequenceListException
{
//Check the index is positive.
if(index < 0) {
throw new SequenceListException("Indexed Element out of Range");
}
//We need to chain down the list until we reach the indexed
//position
Node nodePointer = listHead;
int i = 0;
while (i < index) {
if(nodePointer.next == null) {
throw new SequenceListException("Indexed Element out of Range");
}
else {
nodePointer = nodePointer.next;
i += 1;
}
}
return nodePointer.datum;
}
/**
* Tests whether there are any items in the sequence.
*/
public boolean empty()
{
return (listHead == null);
}
/**
* Returns the number of items in the sequence.
*/
public int size()
{
//Chain down the list counting the elements
Node nodePointer = listHead;
int size = 0;
while(nodePointer != null) {
size += 1;
nodePointer = nodePointer.next;
}
return size;
}
/**
* Empties the sequence.
*/
public void clear()
{
listHead = null;
listTail = null;
}
}
As others mentioned already, each node has to have a reference to it's next and previous neighbor in the list.
Basically, the whole solution does not look that different from your example. You have to take care, that wherever you add or remove a node, you need to adjust the adjacent nodes' references accordingly.
The only method which is a lot different is deleteLast. Here you don't need to traverse through the whole list to find the penultimate node. You can just use the 'prev'-reference of the last node instead.
I fear that I just did your homework, but here is the complete example anyway. Please be advised that I didn't really test that code much at all:
class SequenceListException extends Exception {
SequenceListException() {
super();
}
SequenceListException(String s) {
super(s);
}
}
public class SequenceList {
/**
* Member class Node encapsulates the nodes of the linked list in which the
* stack is stored. Each node contains a data item and a reference to
* another node - the next in the linked list.
*/
protected class Node {
public Node(Object o) {
this(o, null, null);
}
public Node(Object o, Node p, Node n) {
datum = o;
prev = p;
next = n;
}
// The Node data structure consists of three object references.
// One for the datum contained in the node and two for
// the next and previous node in the list.
protected Object datum;
protected Node next;
protected Node prev;
}
// We use object references to the head and tail of the list (the head
// and tail of the sequence, respectively).
private Node listHead;
private Node listTail;
// Only require a single constructor, which sets both object
// references to null.
/**
* Constructs an empty sequence object.
*/
public SequenceList() {
listHead = null;
listTail = null;
}
/**
* Adds a new item at the start of the sequence.
*/
public void insertFirst(Object o) {
// There is a special case when the sequence is empty.
// Then the both the head and tail pointers needs to be
// initialised to reference the new node.
if (listHead == null) {
listHead = new Node(o);
listTail = listHead;
}
// In the general case, we simply add a new node at the start
// of the list via the head pointer.
else {
listHead.prev = new Node(o, null, listHead);
listHead = listHead.prev;
}
}
/**
* Adds a new item at the end of the sequence.
*/
public void insertLast(Object o) {
// There is a special case when the sequence is empty.
// Then the both the head and tail pointers needs to be
// initialised to reference the new node.
if (listHead == null) {
listHead = new Node(o);
listTail = listHead;
}
// In the general case, we simply add a new node to the end
// of the list via the tail pointer.
else {
listTail.next = new Node(o, listTail, null);
listTail = listTail.next;
}
}
/**
* Adds a new item at a specified position in the sequence.
*/
public void insert(Object o, int index) throws SequenceListException {
// Check the index is positive.
if (index < 0) {
throw new SequenceListException("Indexed Element out of Range");
}
// There is a special case when the sequence is empty.
// Then the both the head and tail pointers needs to be
// initialised to reference the new node.
if (listHead == null) {
if (index == 0) {
listHead = new Node(o);
listTail = listHead;
} else {
throw new SequenceListException("Indexed element is out of range");
}
return;
}
// There is another special case for insertion at the head of
// the sequence.
if (index == 0) {
insertFirst(o);
return;
}
// In the general case, we need to chain down the linked list
// from the head until we find the location for the new
// list node. If we reach the end of the list before finding
// the specified location, we know that the given index was out
// of range and throw an exception.
Node nodePointer = listHead;
int i = 1;
while (i < index) {
nodePointer = nodePointer.next;
i += 1;
if (nodePointer == null) {
throw new SequenceListException("Indexed Element out of Range");
}
}
// Now we've found the node before the position of the
// new one, so we 'hook in' the new Node.
Node newNode = new Node(o, nodePointer, nodePointer.next);
if (nodePointer.next != null) {
nodePointer.next.prev = newNode;
}
nodePointer.next = newNode;
// Finally we need to check that the tail pointer is
// correct. Another special case occurs if the new
// node was inserted at the end, in which case, we need
// to update the tail pointer.
if (nodePointer == listTail) {
listTail = newNode;
}
}
/**
* Removes the item at the start of the sequence.
*/
public void deleteFirst() throws SequenceListException {
// Check there is something in the sequence to delete.
if (listHead == null) {
throw new SequenceListException("Sequence Underflow");
}
// There is a special case when there is just one item in the
// sequence. Both pointers then need to be reset to null.
if (listHead.next == null) {
listHead = null;
listTail = null;
return;
}
// In the general case, we just unlink the first node of the
// list.
listHead = listHead.next;
listHead.prev = null;
}
/**
* Removes the item at the end of the sequence.
*/
public void deleteLast() throws SequenceListException {
// Check there is something in the sequence to delete.
if (listHead == null) {
throw new SequenceListException("Sequence Underflow");
}
// There is a special case when there is just one item in the
// sequence. Both pointers then need to be reset to null.
if (listHead.next == null) {
listHead = null;
listTail = null;
return;
}
// In the general case, we just unlink the last node of the
// list.
listTail = listTail.prev;
listTail.next = null;
}
/**
* Removes the item at the specified position in the sequence.
*/
public void delete(int index) throws SequenceListException {
// Check there is something in the sequence to delete.
if (listHead == null) {
throw new SequenceListException("Sequence Underflow");
}
// Check the index is positive.
if (index < 0) {
throw new SequenceListException("Indexed Element out of Range");
}
// There is a special case when there is just one item in the
// sequence. Both pointers then need to be reset to null.
if (listHead.next == null) {
if (index == 0) {
listHead = null;
listTail = null;
} else {
throw new SequenceListException("Indexed element is out of range.");
}
return;
}
// There is also a special case when the first element has to
// be removed.
if (index == 0) {
deleteFirst();
return;
}
// In the general case, we need to chain down the list to find
// the node in the indexed position.
Node nodePointer = listHead;
int i = 1;
while (i < index) {
nodePointer = nodePointer.next;
i += 1;
if (nodePointer.next == null) {
throw new SequenceListException("Indexed Element out of Range");
}
}
// Unlink the node and reset the tail pointer if that
// node was the last one.
if (nodePointer.next == listTail) {
listTail = nodePointer;
}
// Change reference of node after the node which is removed.
if (nodePointer.next.next != null) {
nodePointer.next.next.prev = nodePointer;
}
// Change reference of node before the node which is removed.
nodePointer.next = nodePointer.next.next;
}
/**
* Returns the item at the start of the sequence.
*/
public Object first() throws SequenceListException {
if (listHead != null) {
return listHead.datum;
} else {
throw new SequenceListException("Indexed Element out of Range");
}
}
/**
* Returns the item at the end of the sequence.
*/
public Object last() throws SequenceListException {
if (listTail != null) {
return listTail.datum;
} else {
throw new SequenceListException("Indexed Element out of Range");
}
}
/**
* Returns the item at the specified position in the sequence.
*/
public Object element(int index) throws SequenceListException {
// Check the index is positive.
if (index < 0) {
throw new SequenceListException("Indexed Element out of Range");
}
// We need to chain down the list until we reach the indexed
// position
Node nodePointer = listHead;
int i = 0;
while (i < index) {
if (nodePointer.next == null) {
throw new SequenceListException("Indexed Element out of Range");
} else {
nodePointer = nodePointer.next;
i += 1;
}
}
return nodePointer.datum;
}
/**
* Tests whether there are any items in the sequence.
*/
public boolean empty() {
return (listHead == null);
}
/**
* Returns the number of items in the sequence.
*/
public int size() {
//Chain down the list counting the elements
Node nodePointer = listHead;
int size = 0;
while (nodePointer != null) {
size += 1;
nodePointer = nodePointer.next;
}
return size;
}
/**
* Empties the sequence.
*/
public void clear() {
listHead = null;
listTail = null;
}
public Node lastNode() {
return listTail;
}
public Node firstNode() {
return listHead;
}
}
In a doubly linked list each Node points to the next Node and to the previous one.
so it would be something like this. So i will give you a hint. Your node should have a Node next and Node previous
________ _______
| | | |
| |------>| |
| |<------| |
| | | |
|_______| |______|
You construct Nodes with an object and the next Node. To make this a doubly-linked list, you need to store a previous Node too:
private class DLNode<T> {
private final T datum;
private DLNode<T> next;
private DLNode<T> previous;
private DLNode(final T datum) { this.datum = datum; }
// Manipulate next and previous directly instead of setting them in constructors.
}
public DLNode<T> insertAfter(DLNode<T> node, T datum) {
final DLNode<T> inserted = new DLNode<T>(datum);
final DLNode<T> currentNext = node.next;
inserted.next = currentNext;
inserted.previous = node;
currentNext.previous = inserted;
node.next = inserted;
return inserted;

NullPointerException while iterating over Binary Tree

Now I'm not sure anybody can really help me with this, since it's a pretty sizable amount of code to go through, but any help would be greatly appreciated. Here is my relevant code:
public class BTree implements Iterable<String> {
/** Left child */
BTree left;
/** Right Child */
BTree right;
/** Comparator to use for sorting */
Comparator<String> comp;
/** Parent node */
BTree parent;
/** String stored in this leaf */
String s;
/** # of iterators currently working on it */
int active = 0;
/** Size of the BTree */
int size;
public void build(Iterable<String> iter, int numStrings) {
if (this.active > 0) {
throw new ConcurrentModificationException();
}
else {
Iterator<String> itr = iter.iterator();
while (numStrings != 0 && itr.hasNext()) {
String s = itr.next();
if (!this.contains(s)) {
this.insert(s);
this.size++;
numStrings--;
}
}
}
}
/**
* Inserts the string into the given BTree
* #param str - String to insert
*/
private void insert(String str) {
if (this.s.equals("")) {
this.s = str;
}
else if (this.comp.compare(str, this.s) > 0) {
if (this.right == null) {
BTree bt = BTree.binTree(this.comp);
bt.s = str;
this.right = bt;
bt.parent = this;
}
else {
this.right.insert(str);
}
}
else if (this.comp.compare(str, this.s) < 0) {
if (this.left == null) {
BTree bt = BTree.binTree(this.comp);
bt.s = str;
this.left = bt;
bt.parent = this;
}
else {
this.left.insert(str);
}
}
}
private class BTreeIterator implements Iterator<String> {
/** Current BTree being iterated over */
BTree current;
/** How many next() calls have there been */
int count;
/** Size of the BTree */
int max;
/** Constructor for BTreeIterator
* #param current
*/
BTreeIterator(BTree current) {
this.current = current;
this.count = 0;
this.max = current.size;
active++;
}
/** Returns true if there is another string to iterate over
* #return boolean
*/
public boolean hasNext() {
if (this.count != this.max) {
return true;
}
else {
active--;
return false;
}
}
/**
* Returns the next string in the iterator
* #return String
*/
public String next() {
if (this.count == 0) {
this.count++;
current = this.current.getLeftMost();
if (this.current.s.equals("")) {
throw new NoSuchElementException();
}
return this.current.s;
}
else if (this.current.right != null) {
this.current = this.current.right.getLeftMost();
this.count++;
return this.current.s;
}
else {
BTree tree = this.current;
while (tree.parent.right == tree) {
tree = tree.parent;
}
this.current = tree.parent;
this.count++;
return this.current.s;
}
}
/** Throws an exception since we aren't removing anything from the trees
*/
public void remove() {
throw new UnsupportedOperationException();
}
}
}
}
The Exception gets thrown at the while (tree.parent.right == tree) line in the next() method of the iterator. The funny thing is, my code has worked just fine with a comparator comparing lexicographically and reverse lexicographically sorting through a file of 24000 words. It only throws the exception when using the following comparator:
class StringWithOutPrefixByLex implements Comparator<String> {
/**
* compares o1 and o2
* #param o1 first String in comparison
* #param o2 second String in comparison
* #return a negative integer, zero, or a positive integer
* as the first argument is less than, equal to, or
* greater than the second.
*/
public int compare(String o1, String o2) {
String s1, s2;
if(o1.length() > 4){
s1 = o1.substring(3);
}
else {
s1 = o1;
}
if(o2.length() > 4){
s2 = o2.substring(3);
}
else {
s2 = o2;
}
return s1.compareTo(s2);
}
}
Even weirder, it works fine with that comparator for the same file up to 199 words, but as soon as I have it build up to 200 words it breaks.
EDIT: I have determined that the Exception is due to the code trying to reference tree.parent.right while tree.parent is null, but I can't figure out WHY it's trying to do that. As far as I can tell, my code should never try to call a null tree.parent, as explained by my comment below.
Well, you do not actually show enough of your code, but, what about the root node of your BTree? What is the value of BTree.parent in the root node? null?
If the root node has a null parent, then, in this while loop, it is likely that :
while (tree.parent.right == tree) {
tree = tree.parent;
}
... will get to the root node, the tree will be set to tree.parent, which is null, and then the while loop test will fail because tree.parent.right will attempt to dereference a null pointer.

Categories