I've been trying to write a recursive string method for a binary search tree that returns a multiple line representation of a tree with preorder path info.
Each node should be prefaced by a series of < and > characters showing the path that leads from the root to that node. I'm not sure how to use a string prefix parameter that is extended by one character with each successive call.
The method should be able reproduce this example:
Tree:
15
/ \
12 18
/ / \
10 16 20
\ \
11 17
Expected Print Output:
15
<12
<<10
<<>11
>18
><16
><>17
>>20
I'm new to recursion and so far my actual print output isn't close enough after hours of messing with the code:
18
<17
<10
>15
<11
>12
16
20
Here's my tree node class that works properly:
/**
* A single binary tree node.
* <p>
* Each node has both a left or right child, which can be null.
*/
public class TreeNode<E> {
private E data;
private TreeNode<E> left;
private TreeNode<E> right;
/**
* Constructs a new node with the given data and references to the
* given left and right nodes.
*/
public TreeNode(E data, TreeNode<E> left, TreeNode<E> right) {
this.data = data;
this.left = left;
this.right = right;
}
/**
* Constructs a new node containing the given data.
* Its left and right references will be set to null.
*/
public TreeNode(E data) {
this(data, null, null);
}
/** Returns the item currently stored in this node. */
public E getData() {
return data;
}
/** Overwrites the item stored in this Node with the given data item. */
public void setData(E data) {
this.data = data;
}
/**
* Returns this Node's left child.
* If there is no left left, returns null.
*/
public TreeNode<E> getLeft() {
return left;
}
/** Causes this Node to point to the given left child Node. */
public void setLeft(TreeNode<E> left) {
this.left = left;
}
/**
* Returns this nodes right child.
* If there is no right child, returns null.
*/
public TreeNode<E> getRight() {
return right;
}
/** Causes this Node to point to the given right child Node. */
public void setRight(TreeNode<E> right) {
this.right = right;
}
}
Here's my binary search tree class with the toFullString() method near the bottom:
import java.util.*;
/**
* A binary search tree (BST) is a sorted ADT that uses a binary
* tree to keep all elements in sorted order. If the tree is
* balanced, performance is very good: O(n lg n) for most operations.
* If unbalanced, it performs more like a linked list: O(n).
*/
public class BinarySearchTree<E extends Comparable<E>> {
private TreeNode<E> root = null;
private int size = 0;
/** Creates an empty tree. */
public BinarySearchTree() {
}
public BinarySearchTree(Collection<E> col) {
List<E> list = new ArrayList<E>(col);
Collections.shuffle(list);
for (int i = 0; i < list.size() ; i++) {
add(list.get(i));
}
}
/** Adds the given item to this BST. */
public void add(E item) {
this.size++;
if (this.root == null) {
//tree is empty, so just add item
this.root = new TreeNode<E>(item);
}else {
//find where to insert, with pointer to parent node
TreeNode<E> parent = null;
TreeNode<E> curr = this.root;
boolean wentLeft = true;
while (curr != null) { //will execute at least once
parent = curr;
if (item.compareTo(curr.getData()) <= 0) {
curr = curr.getLeft();
wentLeft = true;
}else {
curr = curr.getRight();
wentLeft = false;
}
}
//now add new node on appropriate side of parent
curr = new TreeNode<E>(item);
if (wentLeft) {
parent.setLeft(curr);
}else {
parent.setRight(curr);
}
}
}
/** Returns the greatest (earliest right-most node) of the given tree. */
private E findMax(TreeNode<E> n) {
if (n == null) {
return null;
}else if (n.getRight() == null) {
//can't go right any more, so this is max value
return n.getData();
}else {
return findMax(n.getRight());
}
}
/**
* Returns item from tree that is equivalent (according to compareTo)
* to the given item. If item is not in tree, returns null.
*/
public E get(E item) {
return get(item, this.root);
}
/** Finds it in the subtree rooted at the given node. */
private E get(E item, TreeNode<E> node) {
if (node == null) {
return null;
}else if (item.compareTo(node.getData()) < 0) {
return get(item, node.getLeft());
}else if (item.compareTo(node.getData()) > 0) {
return get(item, node.getRight());
}else {
//found it!
return node.getData();
}
}
/**
* Removes the first equivalent item found in the tree.
* If item does not exist to be removed, throws IllegalArgumentException().
*/
public void remove(E item) {
this.root = remove(item, this.root);
}
private TreeNode<E> remove(E item, TreeNode<E> node) {
if (node == null) {
//didn't find item
throw new IllegalArgumentException(item + " not found in tree.");
}else if (item.compareTo(node.getData()) < 0) {
//go to left, saving resulting changes made to left tree
node.setLeft(remove(item, node.getLeft()));
return node;
}else if (item.compareTo(node.getData()) > 0) {
//go to right, saving any resulting changes
node.setRight(remove(item, node.getRight()));
return node;
}else {
//found node to be removed!
if (node.getLeft() == null && node.getRight() == null) {
//leaf node
return null;
}else if (node.getRight() == null) {
//has only a left child
return node.getLeft();
}else if (node.getLeft() == null) {
//has only a right child
return node.getRight();
}else {
//two children, so replace the contents of this node with max of left tree
E max = findMax(node.getLeft()); //get max value
node.setLeft(remove(max, node.getLeft())); //and remove its node from tree
node.setData(max);
return node;
}
}
}
/** Returns the number of elements currently in this BST. */
public int size() {
return this.size;
}
/**
* Returns a single-line representation of this BST's contents.
* Specifically, this is a comma-separated list of all elements in their
* natural Comparable ordering. The list is surrounded by [] characters.
*/
#Override
public String toString() {
return "[" + toString(this.root) + "]";
}
private String toString(TreeNode<E> n) {
//would have been simpler to use Iterator... but not implemented yet.
if (n == null) {
return "";
}else {
String str = "";
str += toString(n.getLeft());
if (!str.isEmpty()) {
str += ", ";
}
str += n.getData();
if (n.getRight() != null) {
str += ", ";
str += toString(n.getRight());
}
return str;
}
}
public String toFullString() {
StringBuilder sb = new StringBuilder();
toFullString(root, sb);
return sb.toString();
}
/**
* Preorder traversal of the tree that builds a string representation
* in the given StringBuilder.
* #param n root of subtree to be traversed
* #param sb StringBuilder in which to create a string representation
*/
private void toFullString(TreeNode<E> n, StringBuilder sb)
{
if (n == null)
{
return;
}
sb.append(n.getData().toString());
sb.append("\n");
if (n.getLeft() != null) {
sb.append("<");
} else if (n.getRight() != null) {
sb.append(">");
}
if (n.getLeft() != null || n.getRight() != null)
{
toFullString(n.getLeft(), sb);
toFullString(n.getRight(), sb);
}
}
/**
* Tests the BST.
*/
public static void main(String[] args) {
Collection collection = new ArrayList();
collection.add(15);
collection.add(12);
collection.add(18);
collection.add(10);
collection.add(16);
collection.add(20);
collection.add(11);
collection.add(17);
BinarySearchTree bst = new BinarySearchTree(collection);
//System.out.println(bst);
String temp = bst.toFullString();
System.out.println(temp);
}
}
Any help with the recursive toFullString method will be greatly appreciated.
There are two levels you need to think about when designing a recursive solution.
How do I deal with the current item in the recursion?
How do I go from this item to the next one, and what information gets passed on?
Since we are printing out each item in the tree, there is going to be a single print statement inside of each recursive call. However, the string printed in each row includes information about previous steps that were traversed to reach the current node. How do we deal with this information? It needs to be passed down from previous recursive calls to the next one.
Here is a set of possible rules:
If the current item is a leaf, print out the current result.
If the current item has a left node, add <, and recursively act on the left node.
If the current item has a right node, add >, and recursively act on the right node.
What do we add < and > to? We need a parameter to carry along the current previous steps that have occurred in the recursion from recursive call to call. You don't want to simply print out < and > as you traverse the tree, because you need to remember the current set of steps to print out the prefix to every single node. There could be a second helper method that takes the same parameters as the original toFullString(), but a custom third parameter to carry the current set of previous steps.
So the logic might look something like this:
If there is no current prefix, initialize prefix to "", since the root initially has no steps to reach it.
If the current node is a leaf, add a line of output with the current prefix + leaf value.
If the current node has a left node, recursively call toFullString() on the left node, and add < to the current prefix string, which is handed down.
If the current node has a right node, recursively call toFullString() on the right node, and add > to the current prefix string, which is handed down.
Related
I want to write a java program to arrange the given employee ID in a Binary Search Tree format and then find the immediate manager of any given employee in the organization.
Employee Binary Tree:
Input Format
The first line should contain the number of employees "n" to be inserted in the Tree
The second line should contain the employee ID for which we need to find the immediate manager.
The next "n" lines should contain the employee IDs to form the binary search Tree.
Sample:
Below is the code with which I have intialized the tree successfully. I need help on how to search the parent node for a given child node.
import java.util.Scanner;
class BinarySearchTree {
/* Class containing left and right child of current node and key value*/
class Node {
int data;
int key;
Node left, right;
public Node(int item) {
key = item;
left = right = null;
}
}
// Root of BST
Node root;
// Constructor
BinarySearchTree() {
root = null;
}
// This method mainly calls insertRec()
void insert(int key) {
root = insertRec(root, key);
}
/* A recursive function to insert a new key in BST */
Node insertRec(Node root, int key) {
/* If the tree is empty, return a new node */
if (root == null) {
root = new Node(key);
return root;
}
/* Otherwise, recur down the tree */
if (key < root.key)
root.left = insertRec(root.left, key);
else if (key > root.key)
root.right = insertRec(root.right, key);
/* return the (unchanged) node pointer */
return root;
}
// This method mainly calls InorderRec()
void inorder() {
inorderRec(root);
}
// A utility function to do inorder traversal of BST
void inorderRec(Node root) {
if (root != null) {
inorderRec(root.left);
System.out.println(root.key);
inorderRec(root.right);
}
}
public static void main(String[] args) {
BinarySearchTree tree = new BinarySearchTree();
Scanner sc = new Scanner(System.in);
int num = sc.nextInt();
//int sch = sc.nextInt();
for (int i=0;i<num;i++) {
tree.insert(sc.nextInt());
}
tree.inorder();
}
}
When you write a recursive method, the first thing you need is a condition that terminates the recursion. In your case there are two conditions, as follows.
You find the employee that you are searching for.
You reach the end of the tree.
The recursion needs to terminate if either of the above conditions is true. In your case, terminating the recursion means the method must return a value.
If the terminating condition is not true, the method needs to call itself but with different values for the method parameters.
Here is my recursive search method. More explanation appears after the code.
int search(int employee, int manager, Node node) {
if (node != null) {
if (employee == node.key) {
return manager;
}
manager = node.key;
if (employee < node.key) {
return search(employee, manager, node.left);
}
else {
return search(employee, manager, node.right);
}
}
else {
return -1;
}
}
The method parameters are as follows:
employee - the employee to search for
manager - the manager of the next parameter
node - a node in the tree that will be checked to see if its key is the employee we are searching for
We start searching at the root of the tree and traverse down through the tree nodes. Hence the initial call to the method, which would probably be in method main() would be:
tree.search(sch, -1, tree.root)
According to your sample data, sch is 55. Note that in the initial call, the manager is -1 since the root of the tree does not have a manager. So if sch equals the root key, the method will return -1.
Since we know that the key in the left child of a node is lower and the right child's key is higher, we don't have to search every node. So the method calls itself with the relevant child node. Also we save the current key because if the child node's key is the one we are searching for, then this node's key is the manager.
If the node parameter in method search() is null, that means we have reached the end of the tree which means we have not found the value we are searching for. The value -1 (minus one) is a convention for a value that indicates that the search failed. Method indexOf() in class String is an example of a method also using that convention.
Finally, I used the code you posted in your question. I only added the above method as well as a call to that method from method main(). I added the initial call to method search() as the last line in method main().
For completeness, here is the entire code:
import java.util.Scanner;
public class BinarySearchTree {
class Node {
int key;
Node left, right;
public Node(int item) {
key = item;
left = right = null;
}
}
// Root of BST
Node root;
// Constructor
BinarySearchTree() {
root = null;
}
// This method mainly calls insertRec()
void insert(int key) {
root = insertRec(root, key);
}
/* A recursive function to insert a new key in BST */
Node insertRec(Node root, int key) {
/* If the tree is empty, return a new node */
if (root == null) {
root = new Node(key);
return root;
}
/* Otherwise, recur down the tree */
if (key < root.key)
root.left = insertRec(root.left, key);
else if (key > root.key)
root.right = insertRec(root.right, key);
/* return the (unchanged) node pointer */
return root;
}
// This method mainly calls InorderRec()
void inorder() {
inorderRec(root);
}
// A utility function to do inorder traversal of BST
void inorderRec(Node root) {
if (root != null) {
inorderRec(root.left);
System.out.println(root.key);
inorderRec(root.right);
}
}
// The method I added.
int search(int employee, int manager, Node node) {
if (node != null) {
if (employee == node.key) {
return manager;
}
manager = node.key;
if (employee < node.key) {
return search(employee, manager, node.left);
}
else {
return search(employee, manager, node.right);
}
}
else {
return -1;
}
}
public static void main(String[] args) {
BinarySearchTree tree = new BinarySearchTree();
Scanner sc = new Scanner(System.in);
int num = sc.nextInt();
int sch = sc.nextInt();
for (int i = 0; i < num; i++) {
tree.insert(sc.nextInt());
}
tree.inorder();
System.out.printf("Manager is %d%n", tree.search(sch, -1, tree.root)); // changed this line to print only manager.
}
}
I am trying to write a non-recursive method that removes a node within a binary search tree if it contains the given input value int x in Java. I figured I need to use a stack but can't seem to figure out how to remove the node without calling the function on itself.
This is my TreeNode class as of now.
class TreeNode {
private int data; // data item (key)
private TreeNode left; // this node's left child
private TreeNode right; // this node's right child
// The "external node" is a special node that acts as a sentinel.
private final static TreeNode externalnode = TreeNode.createExternalNode();
/* Return a TreeNode that represents an "external node"*/
public static TreeNode getExternalNode() {
return externalnode;
}
/* Creates a new TreeNode with no children.
*/
public TreeNode(int id) { // constructor
data = id;
left = externalnode;
right = externalnode;
}
I have tried this but cant get it to work.
public TreeNode removeB(int x){
if (this == externalnode) return externalnode;
TreeNode one = new TreeNode(this.data);
System.out.println(this);
Stack<TreeNode> s = new Stack();
s.push(one);
//System.out.println(s);
boolean check;
boolean check1;
while(check = true){
if(x == one.left.data){
System.out.println(one.left.data);
check = false;
return one.left;
}
if(x == one.right.data){
System.out.println(one.right.data);
check1 = false;
return one.right;
}
}
Your code needs to first perform a binary search to find the node to remove. In pseudo-code, it looks something like:
while (currentNode != null && currentNode.value != target) {
if (currentNode.value > target) {
currentNode = currentNode.left;
} else if (currentNode.value < target) {
currentNode = currentNode.right;
}
}
Once you've targeted that node, you replace it with one of its children, and then graft in the other orphaned child under it, just as you would add any node.
I've read all the posts related to this question, yet I am still having a very hard time understanding how to implement the algorithm.
I have a fully written BST with methods that recursively add, delete etc Student objects(the BST class is written for generics, though). I need to write a method that returns the rank of a student in the binary search tree based off their GPA, yet I do not understand how I should implement this. The Student class has a getGPA() method, so I know ill need to use that somehow.
Should I store the elements into an array then search for the index? If so, what's the best algorithm to accomplish this? Is there a better way to do this?
Here is the important parts of my BST class:
public int size()
// Returns the number of elements in this BST.
{
return recSize(root);
}
private int recSize(BSTNode<T> tree)
// Returns the number of elements in tree.
{
if (tree == null)
return 0;
else
return recSize(tree.getLeft()) + recSize(tree.getRight()) + 1;
}
private boolean recContains(T element, BSTNode<T> tree)
// Returns true if tree contains an element e such that
// e.compareTo(element) == 0; otherwise, returns false.
{
if (tree == null)
return false; // element is not found
else if (element.compareTo(tree.getInfo()) < 0)
return recContains(element, tree.getLeft()); // Search left subtree
else if (element.compareTo(tree.getInfo()) > 0)
return recContains(element, tree.getRight()); // Search right subtree
else
return true; // element is found
}
public boolean contains (T element)
// Returns true if this BST contains an element e such that
// e.compareTo(element) == 0; otherwise, returns false.
{
return recContains(element, root);
}
private T recGet(T element, BSTNode<T> tree)
// Returns an element e from tree such that e.compareTo(element) == 0;
// if no such element exists, returns null.
{
if (tree == null)
return null; // element is not found
else if (element.compareTo(tree.getInfo()) < 0)
return recGet(element, tree.getLeft()); // get from left subtree
else
if (element.compareTo(tree.getInfo()) > 0)
return recGet(element, tree.getRight()); // get from right subtree
else
return tree.getInfo(); // element is found
}
public T get(T element)
// Returns an element e from this BST such that e.compareTo(element) == 0;
// if no such element exists, returns null.
{
return recGet(element, root);
}
private BSTNode<T> recAdd(T element, BSTNode<T> tree)
// Adds element to tree; tree retains its BST property.
{
if (tree == null)
// Addition place found
tree = new BSTNode<T>(element);
else if (element.compareTo(tree.getInfo()) <= 0)
tree.setLeft(recAdd(element, tree.getLeft())); // Add in left subtree
else
tree.setRight(recAdd(element, tree.getRight())); // Add in right subtree
return tree;
}
public void add (T element)
// Adds element to this BST. The tree retains its BST property.
{
root = recAdd(element, root);
}
private void inOrder(BSTNode<T> tree)
// Initializes inOrderQueue with tree elements in inOrder order.
{
if (tree != null)
{
inOrder(tree.getLeft());
inOrderQueue.enqueue(tree.getInfo());
inOrder(tree.getRight());
}
}
private void preOrder(BSTNode<T> tree)
// Initializes preOrderQueue with tree elements in preOrder order.
{
if (tree != null)
{
preOrderQueue.enqueue(tree.getInfo());
preOrder(tree.getLeft());
preOrder(tree.getRight());
}
}
private void postOrder(BSTNode<T> tree)
// Initializes postOrderQueue with tree elements in postOrder order.
{
if (tree != null)
{
postOrder(tree.getLeft());
postOrder(tree.getRight());
postOrderQueue.enqueue(tree.getInfo());
}
}
public int reset(int orderType)
// Initializes current position for an iteration through this BST
// in orderType order. Returns current number of nodes in the BST.
{
int numNodes = size();
if (orderType == INORDER)
{
inOrderQueue = new LinkedUnbndQueue<T>();
inOrder(root);
}
else
if (orderType == PREORDER)
{
preOrderQueue = new LinkedUnbndQueue<T>();
preOrder(root);
}
if (orderType == POSTORDER)
{
postOrderQueue = new LinkedUnbndQueue<T>();
postOrder(root);
}
return numNodes;
}
After several failures, it seems I have found a workable solution. Instead of storing in a generic array with a fixed size, I decided to try an ArrayList instead. I use a recursive method to add each node inorder to the array list:
//recursive method used to copy BST to array list
public void recArrayList(BSTNode<T> tree, ArrayList<T> list)
{
if (tree == null)
{
return;
}
recArrayList(tree.getLeft(), list);
list.add(tree.getInfo());
recArrayList(tree.getRight(), list);
}
//converts BST to arraylist used for finding GPA rank
public ArrayList<T> toArrayList()
{
stuList = new ArrayList<T>();
recArrayList(root, stuList);
return stuList;
}
And finally in the class using the BST:
//returns the rank of student in BST based off GPA
public int rank(Student stu)
{
ArrayList<Student> stuList = stuGPA.toArrayList();
for (i = 0; i < stuList.size(); i++)
{
if (stuList.get(i) == stu)
{
return i + 1;
}
}
return 0;
}
I dont like using == to compare references so i'm working on changing that, but for now this seems to be functioning correctly. Ty for the comments, it inspired me to go a different route.
I'm creating a Stack Data Structure and am implementing it using a Linked List. I am using 3 java files - stack.java, stacktest.java and linkedList.java. The linked list works fine when I test it but the stack test is giving me the following errors
Is Empty?: true
Is Empty?: false
Exception in thread "main" java.lang.NullPointerException
at Stack.Peek(Stack.java:56)
at StackTest.main(StackTest.java:12)
Here is my stack.java file
import java.util.EmptyStackException;
public class Stack{
linkedList list;
int count;
public Stack()
{
list = new linkedList();
count = 0;
}
/**
* Adds a node to the head of the list
* #param c character to add
*/
public void Push(char c)
{
if(list.isEmpty())
{// If the list is empty
list.addFirst(c); // Add first
count++;
}
else
{
list.addAtEnd(c); // To the end (tail acts as head)
count++;
}
}
/**
* Removes a node from the head of the list
* #return char removed node
*/
public char Pop() throws EmptyStackException
{
if (!isEmpty())
{
return list.removeLast();
}
else
{
throw new EmptyStackException();
}
}
/**
* Returns the char from the head of the list
* #return char from top of the list
*/
public char Peek() throws EmptyStackException
{
if (!isEmpty())
{
return list.getTail().ch;
}
else
{
throw new EmptyStackException();
}
}
/**
* Is the list empty?
* #return true=yes false=no
*/
public boolean isEmpty()
{
return list.isEmpty();
}
/**
* Counts number of nodes within the list
* #return int # nodes in list
*/
public int getCount()
{
int counter = 0;
Node temp = list.getHead(); // Get head pointer.
while(temp.next != null) // Iterate until tail is reached.
counter++; // Increment counter on each node
return counter;
}
public void printStack()
{
list.printList();
}
}
My stacktest.java
import java.io.IOException;
public class StackTest {
public static void main(String args[]) throws IOException
{
Stack stackList = new Stack();
System.out.println("Is Empty?: " + stackList.isEmpty());
stackList.Push('A');
System.out.println("Is Empty?: " + stackList.isEmpty());
stackList.Pop();
stackList.Peek();
stackList.isEmpty();
stackList.getCount();
stackList.printStack();
}
}
And my linkedList.java
class Node
{
protected char ch;
protected Node next;
protected Node previous;
/**
* Construct a node with the given character value
* #param c - The character
*/
public Node (char c)
{
this.ch = c;
this.next = null;
this.previous = null;
}
}
public class linkedList
{ /** A reference to the head of the list */
protected Node head;
protected Node tail;
/**
* Construct a new empty list
*/
public linkedList()
{
head=null;
tail=null;
}
public Node getHead()
{
return head;
}
public Node getTail()
{
return tail;
}
/**
*Set c as first node in the list
*#param c The character to be inserted
*/
public void addFirst(char c)
{
Node newNode = new Node(c);
head=newNode; // Adding new element.
tail=newNode; // Head and tail will be the same.
}
/**
*Add a character to the end of the list
*#param c The character to be inserted
*/
public void addAtEnd(char c)
{
Node nod = new Node(c);
Node temp = head;
while (temp.next != null) // cycle until at end of list.
temp = temp.next;
temp.next=nod; // last element is new node.
nod.previous=temp; // linking last node with rest of list.
tail=nod; // new node is the tail.
}
/**
*Add a character in alphabetical order into the list
*#param c The character to be inserted
*/
public void addInOrder(char c)
{
Node n= new Node(c);
if(isEmpty())
{
addFirst(c);
}
else
{
Node pre=head;
Node succ= head.next;
if (n.ch < pre.ch)
{
n.next =head;// join node n to the list at the head.
head = n;// head is reading from n.
}
else
{
while(succ!=null && n.ch > succ.ch)
{ // find the position to insert the node
pre = succ;
succ = pre.next;
} //rearrange pointers
n.next = succ;
pre.next = n;
}
}
}
/**
*Test to see if this list is empty
*#returns true or false
*/
public boolean isEmpty()
{
return (head == null && tail == null);
}
/**
*removes a node from the head of the list
*#returns c The character from the removed node
*/
public char removeFirst()
{
if(!isEmpty())
{
// a temporary pointer to enable return of the char being removed
Node temp = head;
head = head.next; // move head pointer along the list
return temp.ch;
}
else
{
System.out.println("List is empty");
return '?'; //to indicate that the list is empty
}
}
/**
* removes a node from the tail of the list
* #return c The character from the removed node
*/
public char removeLast()
{
Node t = getTail(); // Retrieve tail
tail = t.previous; // Set tail to previous node
return t.ch; // return character
}
/**
*prints the characters in the list
*/
public void printList()
{
Node temp=head;
while(temp!=tail.next)
{
System.out.print(temp.ch + " ");
temp=temp.next;
}
System.out.println(); // After print, goes to new line.
}
}
I understand that I am using a variable which is null but can someone explain to me where I am going wrong
When you call addFirst(), it sets both the head and the tail to the new node. However, when you removeLast(), it only changes tail to null and leaves head set to the node you popped.
Then, when you call isEmpty(), since head is not null, it doesn't recognize that the list is empty and returns false.
You need to modify removeLast() to check whether you're removing the only element in the list, and update the head accordingly.
Once you have popped out your only element of the stack, the inner list is empty. Therefore list.getTail() will return null, and you cannot peek into your stack anymore.
In StackTest.java you are inserting one element into the stack, then popping it and then trying to peek into the stack. Your pop function is using removeLast method of linkedList.java. While you are correctly pointing the tail to tail.previous, you need to also check if the result of this leads to tail becoming null (which means you have removed the last element in your linked list). You should check for this in removeLast and make head = tail if this is the case:
public char removeLast()
{
Node t = getTail(); // Retrieve tail
tail = t.previous; // Set tail to previous node
if(tail == null){
head = tail;
}
return t.ch; // return character
}
This way isEmpty() method will always return true if you have popped out the last element in the list. You will have to make a similar change to removeFirst() as follows:
public char removeFirst()
{
if(!isEmpty())
{
// a temporary pointer to enable return of the char being removed
Node temp = head;
head = head.next; // move head pointer along the list
if(head == null){
tail = head;
}
return temp.ch;
}
else
{
System.out.println("List is empty");
return '?'; //to indicate that the list is empty
}
}
After this change your peek() method will now throw an EmptyStackException (which is desirable) instead of a NPE when you try to peek into an empty stack.
Might I also suggest that you don't need to traverse the whole list to add at the end of the list (on addAtEnd()). Since you already have the tail you can just append to the end of the tail pointer.
So I've stumped on this current problem I'm working on. Basically, I need to add an element to my array based binary search tree. According to my text it is similar to the compareTo method. I'm not even sure what direction to head in. I'm a complete noob when it comes to OOP so any help would be appreciated.
package lab9;
public class BinarySearchTreeArray<E> {
Entry<E> [] tree;
Entry<E> root;
int size;
public BinarySearchTreeArray()
{
tree = null;
size = 0;
}
public int size()
{
return size;
}
public boolean contains(Object obj)
{
Entry<E> temp = root;
int comp;
if (obj == null)
throw new NullPointerException();
while (obj != null)
{
comp = ((Comparable)obj).compareTo (temp.element);
if (comp == 0)
return true;
else if (comp < 0)
temp = temp.left;
else
temp = temp.right;
}//while
return false;
}//contains method
/*
* From the text:
* The definition of the add (E element) method is only a little more
* complicated than the definition of contains (Object obj). Basically,
* the add method starts at the root and branches down the tree
* searching for the element; if the search fails, the element is
* inserted as a leaf.
*/
public void add(E e)
{
Entry<E> node = new Entry<E>(e);
if (tree[parent] == null)
{
tree[0] = node;
size++;
}
else
{
tree[1] = node;
size++;
}
}//add method
/****************************************************************/
protected static class Entry<E>
{
private E element;
private Entry<E> parent, left, right;
public Entry(E e){this.element = element; left = right = null;}
public Entry<E> getLeft(){return left;}
public Entry<E> getRight(){return right;}
}
/****************************************************************/
public static void main(String[] args) {
BinarySearchTreeArray<String> bsta1 = new BinarySearchTreeArray<String>();
BinarySearchTreeArray<Integer> bsta2 = new BinarySearchTreeArray<Integer>();
bsta1.add("dog");
bsta1.add("tutle");
bsta1.add("cat");
bsta1.add("ferrit");
bsta1.add("shark");
bsta1.add("whale");
bsta1.add("porpoise");
bsta2.add(3);
bsta2.add(18);
bsta2.add(4);
bsta2.add(99);
bsta2.add(50);
bsta2.add(23);
bsta2.add(5);
bsta2.add(101);
bsta2.add(77);
bsta2.add(87);
}
}
The add method is indeed similar to your contains method. In a typical binary tree represented with structs/objects you would access the right and left subtrees using pointers (as in your example temp.left and temp.right). But, since you have a tree in an array you need to access that array by index, so the question is : How to access the index that corresponds to the left/right subtrees?
For that, you can use the following expression left = parent * 2 and right = parent * 2 + 1. I will provide you with one example of the add method that would add elements to a tree represented as an array of integers, where -1 represents no values or null in java.
public void add(E e)
{
Entry<E> node = new Entry<E>(e);
index = 0;
int comp;
boolean not_add = true;
while(not_add)
{
if (tree[index] == null) //if this node is empty
{
tree[index] = node;
size++;
not_add = true;
}
comp = ((Comparable)e).compareTo (tree[index].element);
if(comp == 0) not_add = true; // Same value
else if (comp < 0) index = index * 2; // should be insert on the left
else index = index * 2 + 1; // should be insert on the right
}
}