Cannot find symbol binary search tree java - java

When I'm trying to print to print out data I'm getting this error saying: Cannot find symbol.
Below is my method
public int heightOfBinaryTree(Node node) {
if (node == null) {
return 0;
} else {
return 1
+ Math.max(heightOfBinaryTree(node.left),
heightOfBinaryTree(node.right));
}
}
This is my print in the main
System.out.println(Math.max(heightOfBinaryTree(node.left)));
Full code
public class Binaireboom<Key extends Comparable<Key>, Value> {
private Node root; // root of BST
private class Node {
private Key key; // sorted by key
private Value val; // associated data
private Node left, right; // left and right subtrees
private int N; // number of nodes in subtree
private int aantal;
int height;
public Node(Key key, Value val, int N, int aantal) {
this.key = key;
this.val = val;
this.N = N;
this.aantal = aantal;
}
}
/**
* Initializes an empty symbol tables.
*/
public Binaireboom() {
}
/**
* Returns true if this symbol tables is empty.
*
* #return <tt>true</tt> if this symbol tables is empty; <tt>false</tt>
* otherwise
*/
public boolean isEmpty() {
return size() == 0;
}
/**
* Returns the number of key-value pairs in this symbol tables.
*
* #return the number of key-value pairs in this symbol tables.
*/
public int size() {
return size(root);
}
// return number of key-value pairs in BST rooted at x
private int size(Node x) {
if (x == null) {
return 0;
} else {
return x.N;
}
}
/**
* Does this symbol tables contain the given key?
*
* #param key the key
* #return <tt>true</tt> if this symbol tables contains <tt>key</tt> and
* <tt>false</tt> otherwise
* #throws NullPointerException if <tt>key</tt> is <tt>null</tt>
*/
public boolean contains(Key key) {
if (key == null) {
throw new NullPointerException("argument to contains() is null");
}
return get(key) != null;
}
/**
* Returns the value associated with the given key.
*
* #param key the key
* #return the value associated with the given key if the key is in the
* symbol tables and <tt>null</tt> if the key is not in the symbol tables
* #throws NullPointerException if <tt>key</tt> is <tt>null</tt>
*/
public Value get(Key key) {
return get(root, key);
}
private Value get(Node x, Key key) {
if (x == null) {
return null;
}
int cmp = key.compareTo(x.key);
if (cmp < 0) {
return get(x.left, key);
} else if (cmp > 0) {
return get(x.right, key);
} else {
return x.val;
}
}
public int getAantal(Key key) {
return getAantal(root, key);
}
private int getAantal(Node x, Key key) {
if (x == null) {
return 0;
}
int cmp = key.compareTo(x.key);
if (cmp < 0) {
return getAantal(x.left, key);
} else if (cmp > 0) {
return getAantal(x.right, key);
} else {
return x.aantal;
}
}
/**
* Inserts the specified key-value pair into the symbol tables, overwriting
* the old value with the new value if the symbol tables already contains
* the specified key. Deletes the specified key (and its associated value)
* from this symbol tables if the specified value is <tt>null</tt>.
*
* #param key the key
* #param val the value
* #throws NullPointerException if <tt>key</tt> is <tt>null</tt>
*/
public void put(Key key, Value val) {
if (key == null) {
throw new NullPointerException("first argument to put() is null");
}
if (val == null) {
delete(key);
return;
}
root = put(root, key, val);
assert check();
}
private Node put(Node x, Key key, Value val) {
if (x == null) {
return new Node(key, val, 1, 1);
}
int cmp = key.compareTo(x.key);
if (cmp < 0) {
x.left = put(x.left, key, val);
} else if (cmp > 0) {
x.right = put(x.right, key, val);
} else if (cmp == 0) {
x.aantal++;
} else {
x.val = val;
}
x.N = 1 + size(x.left) + size(x.right);
return x;
}
/**
* Removes the smallest key and associated value from the symbol tables.
*
* #throws NoSuchElementException if the symbol tables is empty
*/
public void deleteMin() {
if (isEmpty()) {
throw new NoSuchElementException("Symbol tables underflow");
}
root = deleteMin(root);
assert check();
}
private Node deleteMin(Node x) {
if (x.left == null) {
return x.right;
}
x.left = deleteMin(x.left);
x.N = size(x.left) + size(x.right) + 1;
return x;
}
/**
* Removes the largest key and associated value from the symbol tables.
*
* #throws NoSuchElementException if the symbol tables is empty
*/
public void deleteMax() {
if (isEmpty()) {
throw new NoSuchElementException("Symbol tables underflow");
}
root = deleteMax(root);
assert check();
}
private Node deleteMax(Node x) {
if (x.right == null) {
return x.left;
}
x.right = deleteMax(x.right);
x.N = size(x.left) + size(x.right) + 1;
return x;
}
/**
* Removes the specified key and its associated value from this symbol
* tables (if the key is in this symbol tables).
*
* #param key the key
* #throws NullPointerException if <tt>key</tt> is <tt>null</tt>
*/
public void delete(Key key) {
if (key == null) {
throw new NullPointerException("argument to delete() is null");
}
root = delete(root, key);
assert check();
}
private Node delete(Node x, Key key) {
if (x == null) {
return null;
}
int cmp = key.compareTo(x.key);
if (cmp < 0) {
x.left = delete(x.left, key);
} else if (cmp > 0) {
x.right = delete(x.right, key);
} else {
if (x.right == null) {
return x.left;
}
if (x.left == null) {
return x.right;
}
Node t = x;
x = min(t.right);
x.right = deleteMin(t.right);
x.left = t.left;
}
x.N = size(x.left) + size(x.right) + 1;
return x;
}
/**
* Returns the smallest key in the symbol tables.
*
* #return the smallest key in the symbol tables
* #throws NoSuchElementException if the symbol tables is empty
*/
public Key min() {
if (isEmpty()) {
throw new NoSuchElementException("called min() with empty symbol tables");
}
return min(root).key;
}
private Node min(Node x) {
if (x.left == null) {
return x;
} else {
return min(x.left);
}
}
/**
* Returns the largest key in the symbol tables.
*
* #return the largest key in the symbol tables
* #throws NoSuchElementException if the symbol tables is empty
*/
public Key max() {
if (isEmpty()) {
throw new NoSuchElementException("called max() with empty symbol tables");
}
return max(root).key;
}
private Node max(Node x) {
if (x.right == null) {
return x;
} else {
return max(x.right);
}
}
/**
* Returns the largest key in the symbol tables less than or equal to
* <tt>key</tt>.
*
* #param key the keys
* #return the largest key in the symbol tables less than or equal to
* <tt>key</tt>
* #throws NoSuchElementException if there is no such key
* #throws NullPointerException if <tt>key</tt> is <tt>null</tt>
*/
public Key floor(Key key) {
if (key == null) {
throw new NullPointerException("argument to floor() is null");
}
if (isEmpty()) {
throw new NoSuchElementException("called floor() with empty symbol tables");
}
Node x = floor(root, key);
if (x == null) {
return null;
} else {
return x.key;
}
}
private Node floor(Node x, Key key) {
if (x == null) {
return null;
}
int cmp = key.compareTo(x.key);
if (cmp == 0) {
return x;
}
if (cmp < 0) {
return floor(x.left, key);
}
Node t = floor(x.right, key);
if (t != null) {
return t;
} else {
return x;
}
}
/**
* Returns the smallest key in the symbol tables greater than or equal to
* <tt>key</tt>.
*
* #param key the keys
* #return the smallest key in the symbol tables greater than or equal to
* <tt>key</tt>
* #throws NoSuchElementException if there is no such key
* #throws NullPointerException if <tt>key</tt> is <tt>null</tt>
*/
public Key ceiling(Key key) {
if (key == null) {
throw new NullPointerException("argument to ceiling() is null");
}
if (isEmpty()) {
throw new NoSuchElementException("called ceiling() with empty symbol tables");
}
Node x = ceiling(root, key);
if (x == null) {
return null;
} else {
return x.key;
}
}
private Node ceiling(Node x, Key key) {
if (x == null) {
return null;
}
int cmp = key.compareTo(x.key);
if (cmp == 0) {
return x;
}
if (cmp < 0) {
Node t = ceiling(x.left, key);
if (t != null) {
return t;
} else {
return x;
}
}
return ceiling(x.right, key);
}
/**
* Return the kth smallest key in the symbol tables.
*
* #param k the order statistic
* #return the kth smallest key in the symbol tables
* #throws IllegalArgumentException unless <tt>k</tt> is between 0 and
* <em>N</em> − 1
*/
public Key select(int k) {
if (k < 0 || k >= size()) {
throw new IllegalArgumentException();
}
Node x = select(root, k);
return x.key;
}
// Return key of rank k.
private Node select(Node x, int k) {
if (x == null) {
return null;
}
int t = size(x.left);
if (t > k) {
return select(x.left, k);
} else if (t < k) {
return select(x.right, k - t - 1);
} else {
return x;
}
}
/**
* Return the number of keys in the symbol tables strictly less than
* <tt>key</tt>.
*
* #param key the key
* #return the number of keys in the symbol tables strictly less than
* <tt>key</tt>
* #throws NullPointerException if <tt>key</tt> is <tt>null</tt>
*/
public int rank(Key key) {
if (key == null) {
throw new NullPointerException("argument to rank() is null");
}
return rank(key, root);
}
// Number of keys in the subtree less than key.
private int rank(Key key, Node x) {
if (x == null) {
return 0;
}
int cmp = key.compareTo(x.key);
if (cmp < 0) {
return rank(key, x.left);
} else if (cmp > 0) {
return 1 + size(x.left) + rank(key, x.right);
} else {
return size(x.left);
}
}
/**
* Returns all keys in the symbol tables as an <tt>Iterable</tt>. To iterate
* over all of the keys in the symbol tables named <tt>st</tt>, use the
* foreach notation: <tt>for (Key key : st.keys())</tt>.
*
* #return all keys in the symbol tables
*/
public Iterable<Key> keys() {
return keys(min(), max());
}
/**
* Returns all keys in the symbol tables in the given range, as an
* <tt>Iterable</tt>.
*
* #return all keys in the sybol tables between <tt>lo</tt>
* (inclusive) and <tt>hi</tt> (exclusive)
* #throws NullPointerException if either <tt>lo</tt> or <tt>hi</tt>
* is <tt>null</tt>
*/
public Iterable<Key> keys(Key lo, Key hi) {
if (lo == null) {
throw new NullPointerException("first argument to keys() is null");
}
if (hi == null) {
throw new NullPointerException("second argument to keys() is null");
}
Queue<Key> queue = new Queue<Key>();
keys(root, queue, lo, hi);
return queue;
}
private void keys(Node x, Queue<Key> queue, Key lo, Key hi) {
if (x == null) {
return;
}
int cmplo = lo.compareTo(x.key);
int cmphi = hi.compareTo(x.key);
if (cmplo < 0) {
keys(x.left, queue, lo, hi);
}
if (cmplo <= 0 && cmphi >= 0) {
queue.enqueue(x.key);
}
if (cmphi > 0) {
keys(x.right, queue, lo, hi);
}
}
/**
* Returns the number of keys in the symbol tables in the given range.
*
* #return the number of keys in the sybol tables between <tt>lo</tt>
* (inclusive) and <tt>hi</tt> (exclusive)
* #throws NullPointerException if either <tt>lo</tt> or <tt>hi</tt>
* is <tt>null</tt>
*/
public int size(Key lo, Key hi) {
if (lo == null) {
throw new NullPointerException("first argument to size() is null");
}
if (hi == null) {
throw new NullPointerException("second argument to size() is null");
}
if (lo.compareTo(hi) > 0) {
return 0;
}
if (contains(hi)) {
return rank(hi) - rank(lo) + 1;
} else {
return rank(hi) - rank(lo);
}
}
/**
* Returns the height of the BST (for debugging).
*
* #return the height of the BST (a 1-node tree has height 0)
*/
public int height() {
return height(root);
}
private int height(Node x) {
if (x == null) {
return -1;
}
return 1 + Math.max(height(x.left), height(x.right));
}
/**
* Returns the keys in the BST in level orders (for debugging).
*
* #return the keys in the BST in level orders traversal
*/
public Iterable<Key> levelOrder() {
Queue<Key> keys = new Queue<Key>();
Queue<Node> queue = new Queue<Node>();
queue.enqueue(root);
while (!queue.isEmpty()) {
Node x = queue.dequeue();
if (x == null) {
continue;
}
keys.enqueue(x.key);
queue.enqueue(x.left);
queue.enqueue(x.right);
}
return keys;
}
/**
* ***********************
* Check integrity of BST data structures.
************************
*/
private boolean check() {
if (!isBST()) {
StdOut.println("Not in symmetric order");
}
if (!isSizeConsistent()) {
StdOut.println("Subtree counts not consistent");
}
if (!isRankConsistent()) {
StdOut.println("Ranks not consistent");
}
return isBST() && isSizeConsistent() && isRankConsistent();
}
// does this binary tree satisfy symmetric order?
// Note: this test also ensures that data structure is a binary tree since order is strict
private boolean isBST() {
return isBST(root, null, null);
}
// is the trees rooted at x a BST with all keys strictly between min and max
// (if min or max is null, treat as empty constraint)
// Credit: Bob Dondero's elegant solution
private boolean isBST(Node x, Key min, Key max) {
if (x == null) {
return true;
}
if (min != null && x.key.compareTo(min) <= 0) {
return false;
}
if (max != null && x.key.compareTo(max) >= 0) {
return false;
}
return isBST(x.left, min, x.key) && isBST(x.right, x.key, max);
}
// are the size fields correct?
private boolean isSizeConsistent() {
return isSizeConsistent(root);
}
private boolean isSizeConsistent(Node x) {
if (x == null) {
return true;
}
if (x.N != size(x.left) + size(x.right) + 1) {
return false;
}
return isSizeConsistent(x.left) && isSizeConsistent(x.right);
}
// check that ranks are consistent
private boolean isRankConsistent() {
for (int i = 0; i < size(); i++) {
if (i != rank(select(i))) {
return false;
}
}
for (Key key : keys()) {
if (key.compareTo(select(rank(key))) != 0) {
return false;
}
}
return true;
}
public int heightOfBinaryTree(Node node) {
if (node == null) {
return 0;
} else {
return 1
+ Math.max(heightOfBinaryTree(node.left),
heightOfBinaryTree(node.right));
}
}
/**
* Unit tests the <tt>BST</tt> data type.
*/
public static void main(String[] args) throws FileNotFoundException, IOException {
long startTime = System.currentTimeMillis();
//heightOfBinaryTree hbt = new heightOfBinaryTree();
Binaireboom<String, Integer> st = new Binaireboom<String, Integer>();
BufferedReader file = null;
int i = 0;
file = new BufferedReader(new FileReader(new File("")));
String TemporaryVar;
while ((TemporaryVar = file.readLine()) != null) {
TemporaryVar = TemporaryVar.replaceAll("[`~!##$%^&*()_|+\\-=?;:'\",.<>\\{\\}\\[\\]\\\\\\/]", "");
String[] words = TemporaryVar.split(" ");
for (String word : words) {
if (word == null) {
continue;
}
st.put(word, 1);
i++;
}
}
StdOut.println();
for (String s : st.keys()) {
StdOut.println(s + " " + st.getAantal(s));
}
System.out.println(i);
System.out.println();
System.out.println("elapsed: " + (System.currentTimeMillis() - startTime));
System.out.println(Math.max(heightOfBinaryTree(node.left)));
}
}

No where in your main method have you declared a value for node...
You need a declaration
Node node = new Node(args....)
or
Node node = someobject.getNode(arg..);
It wasnt immediately obvious to me how you construct a Node from this class.
ie where that would come from...

Related

Finding height in a binary tree using a queueList

I'm having a problem with my getHeight() method, it is not returning the correct height for the tree. I really think the problem has something to do with my QueueList Class but I can not for the life of me solve the issue. I'm open to suggestions on how to better implement a Binary search. Below is my QueueList Class.
package lab5;
import java.util.NoSuchElementException;
public class QueueList<E> implements Queue<E> {
private Node<E> front;
private Node<E> rear;
private int size = 0;
public QueueList (E it){
front = rear = new Node<E>(it);
size++;
}
public QueueList(){
front = rear = new Node<E>();
size=0;
}
public boolean isEmpty() {
return size==0;
}
public void enqueue(E it) {
rear.setNext(rear);
rear.setElement(it);
size++;
}
public void clear() {
front=new Node<E>();
rear=new Node<E>();
front.setNext(null);
rear.setNext(null);
front.setNext(null);
size=0;
}
public int size() {
return size;
}
public E front() {
return front.getElement();
}
public E dequeue() {
Node<E> temp = front;
if(isEmpty()){
throw new NoSuchElementException();
}
else{
front = front.getNext();
size--;
return temp.getElement();
}
}
}
Here is my Binary search tree class, all of my BSTNode Method works correctly so just assume that is not the issue.
package lab5;
public class BinarySearchTree<E extends Comparable<E>> {
private BSTNode root;
private int size;
public BinarySearchTree() {
root = null;
size = 0;
}
public BinarySearchTree(BSTNode node) {
root = node;
size = 1;
}
/**
* searches for a node that contains it.
*
* if it finds it, it returns that node
*
* else it returns null
*
* #param it
* - the element to look for
*
* #return the node that contains it
*
*/
public BSTNode search(E it) {
BSTNode<E> parent = null;
BSTNode<E> child = null;
BSTNode<E> node = root;
while (node != null && node.getElement() != it) {
parent = node;
int compareResult = it.compareTo(node.getElement());
if (compareResult < 0) {
node = node.getLeft();
} else {
node = node.getRight();
}
}
if (node == null) {
return null;
}
return node;
}
/**
* determines if the tree contains the element
*
* #return true if it is in the tree
*
*/
public boolean contains(E it) {
return (search(it) != null);
}
/**
* Add the element to the correct location
*
* all elements to the left are less than the parent
*
* all elements to the rights are greater than the parent
*
* Do not allow duplicates
*
* #param it
* the element to insert
*
*/
public void insert(E it) {
BSTNode<E> newNode = new BSTNode<E>(it);
if (root == null) {
root = newNode;
return;
}
BSTNode<E> parent = null;
BSTNode<E> node = root;
while (node != null) {
parent = node;
int compareResult = it.compareTo(node.getElement());
if (compareResult < 0) {
node = node.getLeft();
} else if (compareResult > 0) {
node = node.getRight();
} else {
// duplicate
return;
}
}
int res = it.compareTo(parent.getElement());
if (res < 0) {
parent.setLeft(newNode);
} else {
parent.setRight(newNode);
}
size++;
}
/**
* Removes the node that contains it.
*
* If the tree does not contain it, it prints that to
*
* the user and does nothing else.
*
* Otherwise it removes the node and maintains the
*
* BST properties
*
* if removing a node with two children, replace it
*
* with its in order predecessor.
*
* #param the
* element of the node you want to remove.
*
*/
public void remove(E it) {
BSTNode<E> parent = null;
BSTNode<E> child = null;
BSTNode<E> node = root;
// Find the node that contains it
while (node != null && node.getElement() != it) {
parent = node;
int compareResult = it.compareTo(node.getElement());
if (compareResult < 0) {
node = node.getLeft();
} else {
node = node.getRight();
}
}
if (node == null) {
System.out.println("failed to find: " + it + " for removal");
return;
}
if (node.isLeaf()) {
if (parent == null) {
root = null;
} else if (it.compareTo(parent.getElement()) < 0) {
parent.setLeft(null);
} else {
parent.setRight(null);
}
} else if (node.getLeft() == null) {
child = node.getRight();
swapElements(node, child);
node.setLeft(child.getLeft());
node.setRight(child.getRight());
} else if (node.getRight() == null) {
child = node.getLeft();
} else {
child = node.getLeft();
parent = null;
while (child.getRight() != null) {
parent = child;
child = parent.getRight();
}
if (parent == null) {
swapElements(node, child);
node.setLeft(child.getLeft());
} else {
swapElements(node, child);
parent.setRight(child.getLeft());
}
}
size--;
}
/**
* Returns the height of the tree
*
* if tree is empty, height is -1
*
* if tree only has one node, height is 0
*
* #return the integer height of the tree
*
*
*
*/
public int getHeight() {
int height = -1;
QueueList<BSTNode> q = new QueueList<BSTNode>();
if (root == null) {
return height;
}
q.enqueue(root);
while (!q.isEmpty()) {
int nodeCount = q.size();
height++;
while (nodeCount > 0) {
BSTNode<E> node = q.dequeue();
if (node.hasLeft()) {
q.enqueue(node.getLeft());
}
if (node.hasRight()) {
q.enqueue(node.getRight());
}
nodeCount--;
}
}
return height;
}
/**
* Helper method
*
* For removal you need to swap elements of nodes
*
* #param node1
* , node2 the nodes whose contents you are swapping
*
*/
private void swapElements(BSTNode node1, BSTNode node2) {
BSTNode temp = null;
temp.setElement(node1.getElement());
node1.setElement(node2.getElement());
node2.setElement(temp.getElement());
}
/**
* prints each level of the tree on its own line
*
* use your Queue class
*
*/
public void printLevelOrder() {
QueueList<BSTNode> q = new QueueList<BSTNode>();
q.enqueue(root);//You don't need to write the root here, it will be written in the loop
while (q.size() > 0)
{
BSTNode n = q.dequeue();
System.out.println(n.toString()); //Only write the value when you dequeue it
if (n.hasLeft())
{
q.enqueue(n.getLeft());//enqueue the left child
}
if (n.hasRight())
{
q.enqueue(n.getRight());//enque the right child
}
}
}
/**
* prints the tree in a depth-first fashion
*
* use your Stack class
*
*/
public void printByDepth() {
StackList<BSTNode> s = new StackList<BSTNode>();
s.push(root);
while (s.isEmpty() == false) {
BSTNode x = s.pop();
if (x.getRight() != null)
s.push(x.getRight());
if (x.getLeft() != null)
s.push(x.getRight());
System.out.print(" " + x.toString());
}
}
/**
* prints the tree in an inorder fashion.
*
* uses a stack to push left children onto the stack
*
*/
public void printInOrder() {
if (root == null)
return;
StackList s = new StackList();
BSTNode currentNode = root;
while (!s.isEmpty() || currentNode != null) {
if (currentNode != null) {
s.push(currentNode);
currentNode = currentNode.getLeft();
} else {
BSTNode n = null;
n.setElement(s.pop());
System.out.printf("%d ", n.toString());
currentNode = n.getRight();
}
}
}
}
As recursion is very popular when dealing with binary trees, you can use this solution:
public int getHeight() {
return getHeight(root, 0);
}
private int getHeight(BSTNode node, int currentHeight) {
if (node == null) {
return currentHeight;
}
int rightHeight = getHeight(node.getRight(), currentHeight + 1)
int leftHeight = getHeight(node.getLeft(), currentHeight + 1);
return Math.max(rightHeight, leftHeight);
}
Note that it returns height=0 for an empty tree.

Access a value in a generic array inside a generic class

I am making a program that creates a generic hashtable that has both generic keys and generic data. When I cast the data array as the type Person, a class I created, and I try to access the data stored inside an individual Person from my Driver class using a getter method, I get an Object-type returned. My question is how do I access a non-generic class's information through a generic class, since it is stored in a generic array.
This is how I constructed the hashtable:
//region Instance Variables
private int count;
private K[] keys;
private E[] data;
private boolean[] hasBeenUsed;
//endregion
//region Constructor
public Table(int capacity)
{
if (capacity <= 0)
throw new IllegalArgumentException("Capacity is negative.");
keys = (K[]) new Object[capacity];
data = (E[]) new Object[capacity];
hasBeenUsed = new boolean[capacity];
}
My data getters(part of the Table class):
public E[] getData()
{
return data;
}
public E getDataAt(int index)
{
return data[index];
}
This is where I am trying to access the information from my Driver class:
public void print(Table hash)
{
Person[] people = toArray(hash);
for (int i = 0; i < hash.getData().length; i++)
{
if (null == hash.getKeyAt(i))
System.out.println("NULL AT " + i);
else
System.out.println("Key: " + hash.getKeyAt(i) + " Data: " + hash.getDataAt(i));
}
}
private Person[] toArray(Table hash)
{
Person[] people = new Person[hash.getData().length];
for (int i = 0; i < hash.getData().length; i++)
{
people[i] = hash.getDataAt(i);
}
}
This is my entire Hashtable Class if it's needed:
public class Table<K,E>
{
//region Instance Variables
private int count;
private K[] keys;
private E[] data;
private boolean[] hasBeenUsed;
//endregion
//region Constructors
/**
* Constructor
* Instantiates the keys, data, and hasBeenUsed variables with a passed value of capacity
* #param capacity the size to give the three instance arrays
*/
#SuppressWarnings("unchecked")
public Table(int capacity)
{
if (capacity <= 0)
throw new IllegalArgumentException("Capacity is negative.");
keys = (K[]) new Object[capacity];
data = (E[]) new Object[capacity];
hasBeenUsed = new boolean[capacity];
}
/**
* Constructor
* Default-Sets arrays to size 10
*/
#SuppressWarnings("unchecked")
public Table()
{
keys = (K[]) new Object[10];
data = (E[]) new Object[10];
hasBeenUsed = new boolean[10];
}
//endregion
//region Public Methods
/**
* Put
* Adds a new set to the table
* #param key The new Key value
* #param data the new Data value
* #return null if this is a new set, the old data value if the key already exists
*/
public E put(K key, E data)
{
int index = findIndex(key);
E answer;
if (index != -1)
{
answer = (E) this.data[index];
this.data[index] = data;
return answer;
} else if (count < this.data.length)
{
index = hash(key);
while (keys[index] != null)
{
System.out.println("Collision!");
index = nextIndex(index, key);
}
keys[index] = key;
this.data[index] = data;
hasBeenUsed[index] = true;
count++;
return null;
} else
System.out.println("ERROR IN PUT");
return null;
}
/**
* Remove
* Removes a key-data set from the table
* #return the value removed
*/
#SuppressWarnings("unchecked")
public E remove(K key)
{
int index = findIndex(key);
E answer = null;
if (index != -1)
{
answer = (E) data[index];
keys[index] = null;
data[index] = null;
count--;
}
return answer;
}
/**
* Contains Key
* Checks if the passed key exists
* #param key generic type key to check for
* #return true if the key exists
*/
public boolean containsKey(K key)
{
for (int i = 0; i < data.length; i++)
{
if (hasBeenUsed[i])
{
if (keys[i].equals(key))
{
return true;
}
}
}
return false;
}
/**
* Get
* Retrieves the data held stored with key
* #param key the key to access
* #return the data at key, null if key does not exist
*/
#SuppressWarnings("unchecked")
public E get(K key)
{
int index = findIndex(key);
if (index == -1)
return null;
else
return (E) data[index];
}
//endregion
//region Private Methods
//Locates the index value of key
private int findIndex(K key)
{
int count = 0;
int i = hash(key);
while ((count < data.length) && (hasBeenUsed[i]))
{
if (key.equals(keys[i]))
return i;
count++;
i = nextIndex(i, key);
}
return -1;
}
//Hashes the key
private int hash(K key)
{
return Math.abs(key.hashCode()) % data.length;
}
private int hash2(K key)
{
return 1 + (Math.abs(key.hashCode()) % (data.length-2));
}
//Determines if the next index is valid
private int nextIndex(int i, K key)
{
return (i + hash2(key)) % data.length;
}
//endregion
//region Getters and Setters
public int getCount()
{
return count;
}
public void setCount(int count)
{
this.count = count;
}
public K[] getKeys()
{
return keys;
}
public K getKeyAt(int index)
{
return keys[index];
}
public void setKeys(K[] keys)
{
this.keys = keys;
}
public E[] getData()
{
return data;
}
public E getDataAt(int index)
{
return data[index];
}
public void setData(E[] data)
{
this.data = data;
}
//endregion
}
EDIT
I edited the print method, and now I am getting a ClassCastException
Here is my new print method:
public void print(Table<Integer, Person> hash)
{
for (int i = 0; i < hash.getKeys().length; i++)
{
if (null == hash.getKeyAt(i))
System.out.println("NULL AT " + hash.getKeyAt(i));
else
{
System.out.println("Data at key " + hash.getKeyAt(i) + ": \n");
hash.getDataAt(i).printInfo();
}
}
}
You Table is actually generic. So when you want a new Table instance, you can say new Table<KEY_TYPE, VALUE_TYPE>() which will not need you to cast anywhere.
If you're not sure how to create an instance of generic class, please check https://docs.oracle.com/javase/tutorial/java/generics/types.html.

How to implement remove method in Trie data structure?

I am trying to implement PatriciaTrie data structure. I was recently asked this question in a coding interview through Google Docs. But I was not able to answer this.
I made some progress by adding insert method in the below code but got stuck on the remove method in the PatriciaTrie code - not sure how to implement that -
Below is my PatriciaTrie code -
public class PatriciaTrie {
protected static class Edge {
Node target;
TTString label;
public Edge(Node target, TTString label) {
this.target = target;
this.label = label;
}
}
protected static class Node {
Edge[] edges; // the children of this node
int numberOfChildren; // the number of children
public Node() {
edges = new Edge[128];
numberOfChildren = 0;
}
}
/**
* number of strings stored in the trie
*/
protected int number;
/**
* This is root
*/
protected Node root;
public PatriciaTrie() {
root = new Node();
number = 0;
}
/**
* Add the x to this trie
* #param x the string to add
* #return true if x was successfully added or false if x is already in the trie
*/
public boolean insert(TTString x) {
Node current = root;
for (int i = 0; i < x.length(); i++) {
TTString ch = x.subString(i, 1);
if (current.edges[x.charAt(i)] != null) {
Node child = current.edges[x.charAt(i)].target;
current = child;
} else {
current.edges[x.charAt(i)] = new Edge(new Node(), ch);
current.numberOfChildren++;
current = current.edges[x.charAt(i)].target;
}
if (i == x.length() - 1)
return true;
}
return false;
}
/**
* Remove x from this trie
* #param x the string to remove
* #return true if x was successfully removed or false if x is not stored in the trie
*/
public boolean remove(TTString x) {
// not sure how to do this
return false;
}
}
And below is my TTString class -
public class TTString {
int i; // index of first character
int m; // length
byte[] data; // data
public TTString(String s) {
data = s.getBytes();
i = 0;
m = s.length();
}
protected TTString(byte[] data, int i, int m) {
this.data = data;
this.i = i;
this.m = m;
}
public TTString subString(int j, int n) {
if (j < 0 || j >= m) throw new IndexOutOfBoundsException();
if (n < 0 || j + n > m) throw new IndexOutOfBoundsException();
return new TTString(data, i+j, n);
}
/**
* The length of this string
* #return
*/
public int length() {
return m;
}
/**
* Return the character at index j
* #param j
* #return
*/
public char charAt(int j) {
return (char)data[i+j];
}
}
Any thoughts on how to implement remove method here?
One idea is: descend from the root to the leaf corresponding to the last character of x (assuming there is path containing x, otherwise there's nothing to change), remembering last fork on your path in the process (first fork is at the root). When you at the leaf, remove all edges/nodes from the last fork till the leaf.
I have implemented it in C# on TRIE data structure for the string code is follow. You can see the complete code here http://devesh4blog.wordpress.com/2013/11/16/real-time-auto-complete-using-trie-in-c/
public void RemoveWord(string word, TRIENode rootNode, string id)
{
int len = word.Length;
if (len == 0)
{
rootNode.PrefixCount--;
if (rootNode.PrefixCount == 0)
rootNode.IsCompleteWord = false;
rootNode.Ids.Remove(id);
return;
}
for (int i = 0; i < len; i++)
{
string key = word.Substring(i, 1);
string lowerVersionKey = key.ToLower();
rootNode.PrefixCount--;
rootNode = rootNode.Children[lowerVersionKey];
}
rootNode.Ids.Remove(id);
if (rootNode.Ids.Count == 0)
rootNode.IsCompleteWord = false;
}
This is my code and sample tests:
protected static class Edge {
Node target;
TTString label;
public Edge(Node target, TTString label) {
this.target = target;
this.label = label;
}
}
protected static class Node {
Edge[] edges; // the children of this node
int numberOfChildren; // the number of children
// isEnd is true means this node is a string's end node.
boolean isEnd;
public Node() {
edges = new Edge[128];
numberOfChildren = 0;
isEnd = false;
}
}
/**
* number of strings stored in the trie
*/
protected int number;
/**
* This is root
*/
protected Node root;
public PatriciaTrie() {
root = new Node();
number = 0;
}
/**
* Add the x to this trie
*
* #param x
* the string to add
* #return true if x was successfully added or false if x is already in the
* trie
*/
public boolean insert(TTString x) {
// not sure what I am supposed to do here?
Node current = root;
for (int i = 0; i < x.length(); i++) {
TTString ch = x.subString(i, 1);
if (current.edges[x.charAt(i)] != null) {
Node child = current.edges[x.charAt(i)].target;
current = child;
} else {
current.edges[x.charAt(i)] = new Edge(new Node(), ch);
current.numberOfChildren++;
current = current.edges[x.charAt(i)].target;
}
if (i == x.length() - 1) {
// mark this node is the string x's end node.
current.isEnd = true;
return true;
}
}
return false;
}
// find the string x in the trie, if true, return the x.
public TTString find(TTString x) {
boolean isOk = false;
Node current = root;
for (int i = 0; i < x.length(); i++) {
if (current.edges[x.charAt(i)] != null) {
current = current.edges[x.charAt(i)].target;
} else {
isOk = false;
}
if (i == x.length() - 1 && current.isEnd == true) {
isOk = true;
}
}
if (isOk == false)
return null;
else
return x;
}
public boolean remove(TTString x) {
Node current = root;
for (int i = 0; i < x.length(); i++) {
if (current.edges[x.charAt(i)] != null) {
current = current.edges[x.charAt(i)].target;
} else {
return false;
}
if (i == x.length() - 1) {
// delete the string x.
current.isEnd = false;
return true;
}
}
return false;
}
void run() {
/*
* Here is the sample patricialTrie whose edges are labeled with
* letters.
*/
TTString tmp = new TTString("ABCD");
System.out.println(insert(tmp) ? "YES" : "NO");
Node current = root;
for (int i = 0; i < tmp.length(); i++) {
System.out.println(current.edges[tmp.charAt(i)].label.charAt(0));
current = current.edges[tmp.charAt(i)].target;
}
tmp = new TTString("ABCDE");
insert(tmp);
tmp = new TTString("ABDF");
insert(tmp);
/*
* remove method
*/
tmp = new TTString("ABCDE");
System.out.println(remove(tmp) ? "YES" : "NO");
System.out.println(find(tmp) == null ? "NULL" : find(tmp));
tmp = new TTString("ABCD");
System.out.println(find(tmp) == null ? "NULL" : find(tmp));
}
public static void main(String args[]) {
new PatriciaTrie().run();
}

Linear Probing on Java HashTable implementation

So I have a HashTable implementation here that I wrote using only Arrays and had a little bit of help with the code. Unfortunately, I don't quite understand one of the lines someone added while running the "get" or "put" method. What exactly is happening in the while loop below? It is a method for linear probing correct? Also why is the loop checking the conditions it's checking?
Specifically,
int hash = hashThis(key);
while(data[hash] != AVAILABLE && data[hash].key() != key) {
hash = (hash + 1) % capacity;
}
Here's the whole Java class below for full reference.
public class Hashtable2 {
private Node[] data;
private int capacity;
private static final Node AVAILABLE = new Node("Available", null);
public Hashtable2(int capacity) {
this.capacity = capacity;
data = new Node[capacity];
for(int i = 0; i < data.length; i++) {
data[i] = AVAILABLE;
}
}
public int hashThis(String key) {
return key.hashCode() % capacity;
}
public Object get(String key) {
int hash = hashThis(key);
while(data[hash] != AVAILABLE && data[hash].key() != key) {
hash = (hash + 1) % capacity;
}
return data[hash].element();
}
public void put(String key, Object element) {
if(key != null) {
int hash = hashThis(key);
while(data[hash] != AVAILABLE && data[hash].key() != key) {
hash = (hash + 1) % capacity;
}
data[hash] = new Node(key, element);
}
}
public String toString(){
String s="<";
for (int i=0;i<this.capacity;i++)
{
s+=data[i]+", ";
}
s+=">";
return s;
}
Thank you.
I just rewrote some part of the code and added the findHash-method - try to avoid code-duplication!
private int findHash(String key) {
int hash = hashThis(key);
// search for the next available element or for the next matching key
while(data[hash] != AVAILABLE && data[hash].key() != key) {
hash = (hash + 1) % capacity;
}
return hash;
}
public Object get(String key) {
return data[findHash(key)].element();
}
public void put(String key, Object element) {
data[findHash(key)] = new Node(key, element);
}
What you asked for is - what exactly does this findHash-loop? The data was initialized with AVAILABLE - meaning: the data does not (yet) contain any actual data. Now - when we add an element with put - first a hashValue is calculated, that is just an index in the data array where to put the data. Now - if we encounter that the position has already been taken by another element with the same hash value but a different key, we try to find the next AVAILABLE position. And the get method essentially works the same - if a data element with a different key is detected, the next element is probed and so on.
The data itself is a so called ring-buffer. That is, it is searched until the end of the array and is next search again at the beginning, starting with index 0. This is done with the modulo % operator.
Alright?
Sample Hashtable implementation using Generics and Linear Probing for collision resolution. There are some assumptions made during implementation and they are documented in javadoc above class and methods.
This implementation doesn't have all the methods of Hashtable like keySet, putAll etc but covers most frequently used methods like get, put, remove, size etc.
There is repetition of code in get, put and remove to find the index and it can be improved to have a new method to find index.
class HashEntry<K, V> {
private K key;
private V value;
public HashEntry(K key, V value) {
this.key = key;
this.value = value;
}
public void setKey(K key) { this.key = key; }
public K getKey() { return this.key; }
public void setValue(V value) { this.value = value; }
public V getValue() { return this.value; }
}
/**
* Hashtable implementation ...
* - with linear probing
* - without loadfactor & without rehash implementation.
* - throws exception when table is full
* - returns null when trying to remove non existent key
*
* #param <K>
* #param <V>
*/
public class Hashtable<K, V> {
private final static int DEFAULT_CAPACITY = 16;
private int count;
private int capacity;
private HashEntry<K, V>[] table;
public Hashtable() {
this(DEFAULT_CAPACITY);
}
public Hashtable(int capacity) {
super();
this.capacity = capacity;
table = new HashEntry[capacity];
}
public boolean isEmpty() { return (count == 0); }
public int size() { return count; }
public void clear() { table = new HashEntry[this.capacity]; count = 0; }
/**
* Returns null if either probe count is higher than capacity else couldn't find the element.
*
* #param key
* #return
*/
public V get(K key) {
V value = null;
int probeCount = 0;
int hash = this.hashCode(key);
while (table[hash] != null && !table[hash].getKey().equals(key) && probeCount <= this.capacity) {
hash = (hash + 1) % this.capacity;
probeCount++;
}
if (table[hash] != null && probeCount <= this.capacity) {
value = table[hash].getValue();
}
return value;
}
/**
* Check on the no of probes done and terminate if probe count reaches to its capacity.
*
* Throw Exception if table is full.
*
* #param key
* #param value
* #return
* #throws Exception
*/
public V put(K key, V value) throws Exception {
int probeCount = 0;
int hash = this.hashCode(key);
while (table[hash] != null && !table[hash].getKey().equals(key) && probeCount <= this.capacity) {
hash = (hash + 1) % this.capacity;
probeCount++;
}
if (probeCount <= this.capacity) {
if (table[hash] != null) {
table[hash].setValue(value);
} else {
table[hash] = new HashEntry(key, value);
count++;
}
return table[hash].getValue();
} else {
throw new Exception("Table Full!!");
}
}
/**
* If key present then mark table[hash] = null & return value, else return null.
*
* #param key
* #return
*/
public V remove(K key) {
V value = null;
int probeCount = 0;
int hash = this.hashCode(key);
while (table[hash] != null && !table[hash].getKey().equals(key) && probeCount <= this.capacity) {
hash = (hash + 1) % this.capacity;
probeCount++;
}
if (table[hash] != null && probeCount <= this.capacity) {
value = table[hash].getValue();
table[hash] = null;
count--;
}
return value;
}
public boolean contains(Object value) {
return this.containsValue(value);
}
public boolean containsKey(Object key) {
for (HashEntry<K, V> entry : table) {
if (entry != null && entry.getKey().equals(key)) {
return true;
}
}
return false;
}
public boolean containsValue(Object value) {
for (HashEntry<K, V> entry : table) {
if (entry != null && entry.getValue().equals(value)) {
return true;
}
}
return false;
}
#Override
public String toString() {
StringBuilder data = new StringBuilder();
data.append("{");
for (HashEntry<K, V> entry : table) {
if (entry != null) {
data.append(entry.getKey()).append("=").append(entry.getValue()).append(", ");
}
}
if (data.toString().endsWith(", ")) {
data.delete(data.length() - 2, data.length());
}
data.append("}");
return data.toString();
}
private int hashCode(K key) { return (key.hashCode() % this.capacity); }
public static void main(String[] args) throws Exception {
Hashtable<Integer, String> table = new Hashtable<Integer, String>(2);
table.put(1, "1");
table.put(2, "2");
System.out.println(table);
table.put(1, "3");
table.put(2, "4");
System.out.println(table);
table.remove(1);
System.out.println(table);
table.put(1, "1");
System.out.println(table);
System.out.println(table.get(1));
System.out.println(table.get(3));
// table is full so below line
// will throw an exception
table.put(3, "2");
}
}
Sample run of the above code.
{2=2, 1=1}
{2=4, 1=3}
{2=4}
{2=4, 1=1}
1
null
Exception in thread "main" java.lang.Exception: Table Full!!
at Hashtable.put(Hashtable.java:95)
at Hashtable.main(Hashtable.java:177)

Java Singly Linked Integer List, write function thats returns a reference to element with index I in the list

I have been trying to write a Java function IntList get(int i) that is supposed to return a reference to the i-th element in a singly linked integer list.
My problem is that the function returns null, even if I try to reference an existing element!
public class IntList {
private int info; //the int data of this list element
private IntList next; //the rest of the list
/**
* Sets up a new instance of IntList corresponding to the given info and next.
* #param info the int data of this list element
* #param next the rest of the list
*/
public IntList(int info, IntList next) {
this.info = info;
this.next = next;
}
/**
* A new list where the given info has been prepended.
* #param info the int data of the new list element
* #return a new instance of IntList
*/
/*
public IntList prepend(int info) {
return new IntList(info, this);
}
*/
/**
* A new list where the given info has been appended.
* #param info the int data of the new list element
* #return a new instance of IntList
*/
public IntList append(int info) {
if(next == null) {
return new IntList(this.info, new IntList(info, null));
} else {
return new IntList(this.info, next.append(info));
}
}
/**
* Commputes the sum of all elements of this list.
* #return the sum of all elements
*/
public int sum() {
if(next == null) {
return info;
} else {
return info + next.sum();
}
}
/**
* Auxiliary function for the reversal of this list.
* #param acc the list elements accumulated so far
* #return a new instance of IntList
*/
private IntList reverseAux(IntList acc) {
if(next == null) {
return new IntList(info, acc);
} else {
return next.reverseAux(new IntList(info, acc));
}
}
/**
* A new list with the elements of this list in reverse order.
* #return a new instance of the IntList
*/
public IntList reverse() {
return reverseAux(null);
}
/**
* String representation of this list.
*/
#Override
public String toString() {
if(next == null) {
return "" + info;
} else {
return info + " , " + next;
}
}
/**
* An integer array is converted to a list
* #param values is an array containing integer elements
* #return a new instance of IntList
*/
public static IntList fromArray(int[] values) {
int n = values.length;
IntList res = new IntList(values[0] , null);
for(int i = 1; i < n ; i ++) {
res = res.append(values[i]);
}
return res;
}
/**
* The length of a given IntList object is determined
* #return the length of the list
*/
public int length() {
int counter = 1;
while(next != null) {
counter = counter + 1;
next = next.next;
}
return counter;
}
public IntList get(int i) {
for(int k = 0 ; k < i - 1 ; k ++) {
if(next != null) {
next = next.next;
}
}
return next;
}
public static void main(String[] args) {
IntList lst = new IntList(1, null);
for(int i = 2 ; i < 10 ; i ++) {
lst = lst.append(i);
}
System.out.println(lst);
System.out.println(lst.reverse());
System.out.println(lst.sum());
int[] values = new int[4];
values[0] = 3;
values[1] = 4;
values[2] = 5;
values[3] = 8;
System.out.println(fromArray(values));
System.out.println(lst.length());
System.out.println(fromArray(values).length());
System.out.println(lst.get(2));
}
}
Since my implementation of the list does not require two separate classes for nodes and the list itself, I cannot find any valuable information on the web (most people use two classes).
This one works without checking for IndexOutOfBoundsException:
public IntList get(int i) {
IntList current = this;
for(int k = 0 ; k < i - 1 ; k ++) {
if(current.next != null) {
current = current.next;
}
}
return current;
}
Your length method modifies next. Make it recursive (or make a new variable to step through your list):
public int length() {
if(next != null) {
return 1 + next.length();
}
else {
return 1;
}
}
Your get method also modifies the original list. Recursive solution is:
public IntList get(int i) {
if (i < 0) {
throw new IndexOutOfBoundsException("Index is negative!");
}
if (i == 0) {
return this;
} else if (next != null) {
return next.get(i - 1);
}
throw new IndexOutOfBoundsException("Index exceeds bounds");
}
I think you want something like this...
public IntList append(int info) {
if(next == null) {
return new IntList(info, this);
} else {
return new IntList(info, next);
}
}

Categories

Resources