I am working on a Binary Search Tree algorithm (called BST in the code) and whenever I run the program it just keeps running for a long time. I know this means that there is an infinite loop but I can't figure out what/where is the problem (I've been trying for a while). I've had this problem once before and never figured that out either. If anyone could help find out where the loop is, what to change it to and also explain why it causes it I would be extremely grateful for the knowledge as it would also help me for future endeavors. Here is the code:
import java.util.Queue;
import java.util.ArrayDeque;
public class BST<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
public Node(Key key, Value val, int N) {
this.key = key;
this.val = val;
this.N = N;
}
}
// is the symbol table empty?
public boolean isEmpty() {
return size() == 0;
}
// return number of key-value pairs in BST
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;
}
/***********************************************************************
* Search BST for given key, and return associated value if found,
* return null if not found
***********************************************************************/
// does there exist a key-value pair with given key?
public boolean contains(Key key) {
return get(key) != null;
}
// return value associated with the given key, or null if no such key exists
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;
}
/***********************************************************************
* Insert key-value pair into BST
* If key already exists, update with new value
***********************************************************************/
public void put(Key key, Value val) {
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);
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 x.val = val;
x.N = 1 + size(x.left) + size(x.right);
return x;
}
/***********************************************************************
* Delete
***********************************************************************/
public void deleteMin() {
if (isEmpty()) throw new RuntimeException("Symbol table 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;
}
public void deleteMax() {
if (isEmpty()) throw new RuntimeException("Symbol table 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;
}
public void delete(Key key) {
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;
}
/***********************************************************************
* Min, max, floor, and ceiling
***********************************************************************/
public Key min() {
if (isEmpty()) return null;
return min(root).key;
}
private Node min(Node x) {
if (x.left == null) return x;
else return min(x.left);
}
public Key max() {
if (isEmpty()) return null;
return max(root).key;
}
private Node max(Node x) {
if (x.right == null) return x;
else return max(x.right);
}
public Key floor(Key key) {
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;
}
public Key ceiling(Key key) {
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);
}
/***********************************************************************
* Rank and selection
***********************************************************************/
public Key select(int k) {
if (k < 0 || k >= size()) return null;
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;
}
public int rank(Key key) {
return rank(key, root);
}
// Number of keys in the subtree less than x.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);
}
/***********************************************************************
* Range count and range search.
***********************************************************************/
public Iterable<Key> keys() {
return keys(min(), max());
}
public Iterable<Key> keys(Key lo, Key hi) {
Queue<Key> queue = new ArrayDeque<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.offer(x.key);
if (cmphi > 0) keys(x.right, queue, lo, hi);
}
public int size(Key lo, Key hi) {
if (lo.compareTo(hi) > 0) return 0;
if (contains(hi)) return rank(hi) - rank(lo) + 1;
else return rank(hi) - rank(lo);
}
// height of this BST (one-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));
}
/*************************************************************************
* Check integrity of BST data structure
*************************************************************************/
private boolean check() {
if (!isBST()) System.out.println("Not in symmetric order");
if (!isSizeConsistent()) System.out.println("Subtree counts not consistent");
if (!isRankConsistent()) System.out.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 tree 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;
}
/*****************************************************************************
* Test client
*****************************************************************************/
public static void main(String[] args) {
BST<String, Integer> st = new BST<String, Integer>();
for (int i = 0; !System.out.equals(i); i++) {
String key = System.out.toString();
st.put(key, i);
}
for (String s : st.keys())
System.out.println(s + " " + st.get(s));
}
}
Thank you in advance to anyone who ofers help!
for (int i = 0; !System.out.equals(i); i++)
system out won't be ever equals an integer
Related
I made my own implementation of Java's HashMap after looking at the source code and watching a fiew videos on it. I only added the key methods, and this is what I came up with:
public class MyHashMap {
private Node[] arr;
private int n;
public MyHashMap() {
n = 16;
arr = new Node[n];
}
public void put(int key, int value) {
int index = key & (n - 1);
if (arr[index] == null) {
arr[index] = new Node(key, value);
} else {
Node node = arr[index];
if(node.key == key) {
node.value = value;
return;
}
while (node.next != null) {
if(node.key == key) {
node.value = value;
return;
}
node = node.next;
}
node.next = new Node(key, value);
}
}
public int get(int key) {
int index = key & (n - 1);
if(arr[index] == null) {
return -1;
} else {
Node node = arr[index];
while(node != null) {
if(node.key == key) {
return node.value;
}
}
return -1;
}
}
public void remove(int key) {
int index = key & (n - 1);
if(arr[index] == null) {
return;
} else {
Node node = arr[index];
if(node.next == null && node.key == key) {
arr[index] = null;
return;
}
while(node.next != null) {
if(node.key == key) {
node.next = node.next.next;
return;
}
}
}
}
private class Node {
int key, value;
Node next;
Node(int key, int value) {
this.key = key;
this.value = value;
}
}
}
I can do relatively small commands without it taking to long, like this:
MyHashMap hashMap = new MyHashMap();
hashMap.put(1, 1);
hashMap.put(2, 2);
System.out.println(hashMap.get(1)); // returns 1
System.out.println(hashMap.get(3)); // returns -1 (not found)
hashMap.put(2, 1); // update the existing value
System.out.println(hashMap.get(2)); // returns 1
hashMap.remove(2); // remove the mapping for 2
System.out.println(hashMap.get(2)); // returns -1 (not found)
But as soon as I do more things, it takes a much longer time. I tried to see if Java's HashMap was as slow, but it took barely any time. What makes my implementation so much slower? It's not just a few milliseconds, it's about 5 seconds slower when my commands aren't even that much.
I am making a trie data structure. I want to find the number of occurrences of specific word in that trie e.g. if the word 'similar' is coming four times in a trie, the program should give the output of that word as 4. Can someone guide me in the right direction? Here is my code of class which is telling the index of that specific word.
public class TST<Value> {
private int N; // size
private Node root; // root of TST
private class Node {
private char c; // character
private Node left, mid, right; // left, middle, and right subtries
private Value val; // value associated with string
}
// return number of key-value pairs
public int size() {
return N;
}
public boolean contains(String key) {
return get(key) != null;
}
public Value get(String key) {
if (key == null) throw new NullPointerException();
if (key.length() == 0) throw new IllegalArgumentException("key must have length >= 1");
Node x = get(root, key, 0);
if (x == null) return null;
return x.val;
}
// return subtrie corresponding to given key
private Node get(Node x, String key, int d) {
if (key == null) throw new NullPointerException();
if (key.length() == 0) throw new IllegalArgumentException("key must have length >= 1");
if (x == null) return null;
char c = key.charAt(d);
if (c < x.c) return get(x.left, key, d);
else if (c > x.c) return get(x.right, key, d);
else if (d < key.length() - 1) return get(x.mid, key, d+1);
else return x;
}
public void put(String s, Value val) {
if (!contains(s)) N++;
root = put(root, s, val, 0);
}
private Node put(Node x, String s, Value val, int d) {
char c = s.charAt(d);
if (x == null) {
x = new Node();
x.c = c;
}
if (c < x.c) x.left = put(x.left, s, val, d);
else if (c > x.c) x.right = put(x.right, s, val, d);
else if (d < s.length() - 1) x.mid = put(x.mid, s, val, d+1);
else x.val = val;
return x;
}
Sorry in advance for all the code provided, because I am unsure where the problem may be, I am adding the whole thing.
I am having trouble getting my program to output anything (just blank space). A great deal of this code comes straight from our book and what isn't is also from previous (yet similar) programs that I have gotten to work. I have been mainly focusing on the levelOrder and insert methods, though I'm thinking it may be the latter.
import java.util.Scanner;
import java.lang.*;
public class AVLTree {
private static class AvlNode {
int key;
AvlNode left;
AvlNode right;
int height; //height difference between right and left subtrees at node
AvlNode(int x) {
key = x;
left = right = null;
height = 0;
}
AvlNode( int x, AvlNode l, AvlNode r) {
key = x;
left = l;
right = r;
}
}
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
boolean keepRunning = true;
while (keepRunning) {
System.out.print(">> Enter choice [1-7] from menu below: \n");
System.out.println("\t 1) Insert node");
System.out.println("\t 2) Remove node");
System.out.println("\t 3) Print level order");
System.out.println("\t 4) Exit program ");
int choice = input.nextInt();
int value;
switch (choice)
{
case 1:
System.out.print("Enter element to insert: ");
value = input.nextInt();
insert(value, root);
break;
case 2:
System.out.print("Enter element to remove: ");
value = input.nextInt();
remove(value);
break;
case 3:
levelOrder();
System.out.println("");
break;
case 4:
keepRunning = false;
break;
default:
System.out.println("Invalid Choice!");
keepRunning = false;
}
}
}
private static AvlNode root;
public AvlNode getroot() {
return root;
}
private static int height(AvlNode t) {
if(t == null) {
return 1;
}
else
return t.height;
}
private static final int ALLOWED_IMBALANCE = 1;
private static AvlNode balance(AvlNode t) {
if (t == null) {
return t;
}
if (height(t.left) - height(t.right) > ALLOWED_IMBALANCE) {
if (height(t.left.left) >= height(t.left.right)) {
t = singleRotateLL(t);
} else {
t = doubleRotateLR(t);
}
} else {
if (height(t.right) - height(t.left) > ALLOWED_IMBALANCE) {
if (height(t.right.right) >= height(t.right.left)) {
t = singleRotateRL(t);
} else {
t = doubleRotateRL(t);
}
}
}
t.height = Math.max(height(t.left), height(t.right)) + 1;
return t;
}
//public methods for insert, remove, findMin, findMax, find....
//The find function will not require modification because they do not change the structure of the tree
private static AvlNode singleRotateLL(AvlNode k2) {
AvlNode k1 = k2.left; //next make "poiner" adjustments for the LL rotate operation
k2.left = k1.right;
k1.right = k2;
k2.height = Math.max(height(k2.left), height(k2.right)) + 1;
k1.height = Math.max(height(k1.left), height(k1.right)) + 1;
return k1;
}
private static AvlNode doubleRotateLR(AvlNode k3) {
AvlNode k1 = k3.left; //next make "poiner" adjustments for the LL rotate operation
AvlNode k2 = k1.right;
k1.right = k2.left;
k3.left = k2.right;
k2.left = k1;
k2.right = k3;
k1.height = Math.max(height(k1.left), height(k1.right)) + 1;
k2.height = Math.max(height(k2.left), height(k2.right)) + 1;
k3.height = Math.max(height(k3.left), height(k3.right)) + 1;
return k2;
}
private static AvlNode singleRotateRL(AvlNode k2) {
AvlNode k1 = k2.right; //next make "poiner" adjustments for the LL rotate operation
k2.right = k1.left;
k1.left = k2;
k2.height = Math.max(height(k2.right), height(k2.left)) + 1;
k1.height = Math.max(height(k1.right), height(k1.left)) + 1;
return k1;
}
private static AvlNode doubleRotateRL(AvlNode k3) {
AvlNode k1 = k3.right; //next make "poiner" adjustments for the LL rotate operation
AvlNode k2 = k1.left;
k1.left = k2.right;
k3.right = k2.left;
k2.right = k1;
k2.left = k3;
k1.height = Math.max(height(k1.right), height(k1.left)) + 1;
k2.height = Math.max(height(k2.right), height(k2.left)) + 1;
k3.height = Math.max(height(k3.right), height(k3.left)) + 1;
return k2;
}
private static AvlNode insert(int x, AvlNode t) {
if(t == null)
return new AvlNode(x, null, null);
int compareResult = Integer.compare(x, t.key);
if(compareResult < 0) {
t.left = insert(x, t.left);
}
else if(compareResult > 0) {
t.right = insert(x, t.right);
}
else; // duplicate, do nothing
return balance(t);
}
public int findMin() {
return findMin(root).key;
}
private static AvlNode findMin(AvlNode t) {
if (t == null) {
return null;
}
if (t.left == null) {
return t;
}
return findMin(t.left);
}
public static void remove(int x) {
remove(x, root);
}
private static AvlNode remove(int x, AvlNode t) {
if (t == null) {
return t;
}
int compareResult = Integer.compare(x, t.key);
if (compareResult < 0) {
t.left = remove(x, t.left);
}
else if (compareResult > 0) {
t.right = remove(x, t.right);
}
else if ((t.left != null) && (t.right != null)) {
t.key = findMin(t.right).key;
t.right = remove(t.key, t.right);
}
else {
t = (t.left != null) ? t.left : t.right;
}
return balance(t);
}
private static void levelOrder() { //prints the level order traversal of the tree
int h = height(root);
for(int i = 1; i <= h; i++) {
printLevel(root, i);
}
}
private static void printLevel(AvlNode t, int level) {
if(t == null) {
return;
}
if(level == 1) {
System.out.print(t.key + " ");
}
else if(level > 1) {
printLevel(t.left, level - 1);
printLevel(t.right, level - 1);
}
}
}
You had to do two changes, one is to initialize root and the first time, and the second one is to change the height accordingly.
Just change the following class & function :
private static AvlNode insert(int x, AvlNode t) {
if (t == null && root==null)
return (root = new AvlNode(x, null, null));
else if (t==null) {
return new AvlNode(x, null, null);
}
t.height++;
int compareResult = Integer.compare(x, t.key);
if (compareResult < 0) {
t.left = insert(x, t.left);
} else if (compareResult > 0) {
t.right = insert(x, t.right);
} else {
t.height--;
}
return balance(t);
}
private static class AvlNode {
int key;
AvlNode left;
AvlNode right;
int height=0;
AvlNode(int x, AvlNode l, AvlNode r) {
key = x;
left = l;
right = r;
this.height++;
}
}
I'm using a BST. Given a key, how will I find the successor key? This is the code I have so far. I've managed to insert a new key and retrieve a value given the key. Now, I need to finish the next method. How would I approach this?
class BST<K extends Comparable<K>, V> implements RangeMap<K,V> {
class Node {
Node left;
Node right;
Node parent;
KVPair<K,V> kv;
K key;
V value;
public Node(K key, V value) {
this.key = key;
this.value = value;
parent = left = right = sentinel;
}
}
private Node root;
public void add(K key, V value) {
// TODO: Implement me(basic score)
root = add (root, key, value);
}
private Node add(Node x, K key, V value){
if (x == null){
return new Node(key, value); }
int cmp = key.compareTo(x.key);
if (cmp < 0){
x.left = add(x.left, key, value);}
else if (cmp > 0 ){
x.right = add(x.right, key, value);}
else if (cmp == 0){
x.value = value;}
return x;
}
public V get(K key) {
Node x = root;
while (x != null){
int cmp = key.compareTo(x.key);
if (cmp < 0){
x = x.left;}
else if (cmp > 0 ){
x = x.right;}
else if (cmp == 0){
return x.value;}
}
return null;
}
public K next(K key) {
You would need a private method to getNode of key
Then you get successor of that node and return its value
You should also update your "V get(K key)" method to use the getNode(K Key) method to avoid code duplication
I've written all 3 methods below
private Node getNode(K key) {
Node x = root;
while (x != null){
int cmp = key.compareTo(x.key);
if (cmp < 0){
x = x.left;
} else if (cmp > 0 ) {
x = x.right;
} else if (cmp == 0){
return x;
}
}
return null;
}
public K next(K key) {
Node x = getNode(key);
if (x.right != null) {
x = x.right;
while (x.left != null) {
x = x.left;
}
return x.key;
}
Node p = x.parent;
while (p != null && p.right == x) {
p = p.parent;
x = x.parent;
}
return p.key;
}
public V get(K key) {
Node x = getNode(key);
return x==null?null:x.value;
}
When I use MapEntry[] entry = (MapEntry[]) new Object[capacity],
it tells me java.lang.ClassCastException.
How can this happen? I am confused about this. (Since it seems I should do the casting because it's generic)
I found some tutorial and they were using like this:
table = new Entry[capacity];
(http://www.javamadesoeasy.com/2015/02/hashmap-custom-implementation.html)
it did not even do the casting.
My codes are below.
public class MyHashMap<K, V> {
private class MapEntry {
K key;
V value;
MapEntry next;
MapEntry(K key, V value) {
this.key = key;
this.value = value;
}
}
private int size = 0;
private int capacity;
MapEntry[] entry;
#SuppressWarnings("unchecked")
MyHashMap() {
capacity = 10;
entry = (MapEntry[]) new Object[capacity];
}
#SuppressWarnings("unchecked")
MyHashMap(int capacity) {
entry = (MapEntry[]) new Object[capacity];
}
public void put(K key, V value) {
int hash = hashCode(key);
MapEntry newNode = new MapEntry(key, value);
if (entry[hash % capacity] == null) {
entry[hash % capacity] = newNode;
} else {
if (key == entry[hash % capacity].key) {
entry[hash % capacity].value = value;
} else {
MapEntry nextNode = entry[hash % capacity].next;
while (nextNode != null) {
if (key == nextNode.key) {
nextNode.value = value;
return;
}
nextNode = nextNode.next;
}
nextNode = newNode;
}
}
}
public V get(K key) {
int hash = hashCode(key);
MapEntry node = entry[hash % capacity];
if (node == null) {
return null;
}
if (node.key == key) {
return node.value;
}
while (key != node.key) {
node = node.next;
if (node.key == key) {
return node.value;
}
}
return null;
}
public boolean contains(K key) {
return get(key) != null;
}
public int size() {
return size;
}
public void remove(K key) {
int hash = hashCode(key);
MapEntry node = entry[hash % capacity];
if (node == null) return;
if (key == node.key) {
entry[hash % capacity] = node.next;
}
MapEntry pre = node;
while (key != node.key) {
node = node.next;
if (key == node.key) {
pre.next = node.next;
return;
}
pre = pre.next;
}
}
private int hashCode(K key) {
return Math.abs(key.hashCode());
}
public void display(){
for(int i = 0; i < capacity; i++){
if(entry[i] != null){
MapEntry node = entry[i];
while(node != null){
System.out.print("{" + node.key + "=" + node.value + "}" + " ");
node = node.next;
}
}
}
}
public static void main(String[] args) {
MyHashMap<Integer, Integer> hashMapCustom = new MyHashMap<Integer, Integer>();
hashMapCustom.put(21, 12);
hashMapCustom.put(25, 121);
hashMapCustom.put(30, 151);
hashMapCustom.put(33, 15);
hashMapCustom.put(35, 89);
System.out.println("value corresponding to key 21="
+ hashMapCustom.get(21));
System.out.println("value corresponding to key 51="
+ hashMapCustom.get(51));
System.out.print("Displaying : ");
hashMapCustom.display();
System.out.print("Displaying : ");
hashMapCustom.display();
}
}
You can't convert a class of an array by just casting that's yhe reason you get ClassCastException. You should use
`Arrays.copyof ().`
CustomType[]ca=Arrays.copyOf(array,array.length,CustomType[].class);
I have figured out how this work.
(Creation of array whose component type is either a type parameter, a concrete parameterized type or a bounded wildcard parameterized type, is type-unsafe.)
entry = (MapEntry[]) Array.newInstance(MapEntry.class, capacity);
In this way, there can be no errors.
There is another question with good solution.
How to create a generic array in Java?