Insert in Binary Search Tree with duplicate Keys? - java

Right now when I'm inserting Keys/Values into the BST and then searching them I get null values. I would like to get some assistance on how to handle with duplicate keys.
private Node put(Node root, final Key key, final Value value) {
if (root == null)
return new Node(key, value, 1);
final int result = key.compareTo(root.key);
if (result > 0)
root.right = put(root.right, key, value);
else if (result <= 0) {
root.left = put(root.left, key, value);
}
root.size = size(root.left) + size(root.right) + 1;
return root;
}
private Value get(final Node root, final Key key) {
if (root == null)
return null;
final int result = key.compareTo(root.key);
if (result > 0)
return get(root.right, key);
else if (result <= 0)
return get(root.left, key);
return root.value;
}

Your get code needs an == check. Your <= 0 check is grabbing the node to the left where you want < 0. Your == check should return the root.value.
Something like:
private Value get(final Node root, final Key key) {
if (root == null)
return null;
final int result = key.compareTo(root.key);
if (result > 0)
return get(root.right, key);
else if (result < 0)
return get(root.left, key);
else if (result == 0)
return root.value;
else
return null; //key not found
}

Related

Why Is My Implementation Of HashMap Much, Much, Slower Than Java's HashMap?

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.

why ConcurrentHashMap doesn't use 'CAS' but use 'synchronized' when tabAt[i] is not null

final V putVal(K key, V value, boolean onlyIfAbsent) {
if (key == null || value == null) throw new NullPointerException();
int hash = spread(key.hashCode());
int binCount = 0;
for (Node<K,V>[] tab = table;;) {
Node<K,V> f; int n, i, fh;
if (tab == null || (n = tab.length) == 0)
tab = initTable();
else if ((f = tabAt(tab, i = (n - 1) & hash)) == null) {
if (casTabAt(tab, i, null,
new Node<K,V>(hash, key, value, null)))
break; // no lock when adding to empty bin
}
else if ((fh = f.hash) == MOVED)
tab = helpTransfer(tab, f);
else {
V oldVal = null;
synchronized (f) {
if (tabAt(tab, i) == f) {
if (fh >= 0) {
binCount = 1;
for (Node<K,V> e = f;; ++binCount) {
K ek;
if (e.hash == hash &&
((ek = e.key) == key ||
(ek != null && key.equals(ek)))) {
oldVal = e.val;
if (!onlyIfAbsent)
e.val = value;
break;
}
Node<K,V> pred = e;
if ((e = e.next) == null) {
pred.next = new Node<K,V>(hash, key,
value, null);
break;
}
}
}
else if (f instanceof TreeBin) {
Node<K,V> p;
binCount = 2;
if ((p = ((TreeBin<K,V>)f).putTreeVal(hash, key,
value)) != null) {
oldVal = p.val;
if (!onlyIfAbsent)
p.val = value;
}
}
}
}
if (binCount != 0) {
if (binCount >= TREEIFY_THRESHOLD)
treeifyBin(tab, i);
if (oldVal != null)
return oldVal;
break;
}
}
}
addCount(1L, binCount);
return null;
}
When tabAt(tab, i = (n - 1) & hash)) is null, it use CAS to add/modify a node, but when is not null, it use synchronized (f). I think it can still use CAS of last node or node with key that need put of tabAt(tab, i = (n - 1) & hash)) to add/modify a node. But why not? My idea is wrong.

Java program to find the number of occurrences of specific word in a trie

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;
}

BST: How to find the successor key given a key?

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;
}

Infinite loop inside a binary search tree algorithm

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

Categories