Skip to content

Instantly share code, notes, and snippets.

@s
Last active April 25, 2021 12:26
Show Gist options
  • Save s/d0dcfadc8a89b6f8fddc5b9e22e0d6fe to your computer and use it in GitHub Desktop.
Save s/d0dcfadc8a89b6f8fddc5b9e22e0d6fe to your computer and use it in GitHub Desktop.
MinStack implementation
package nl.saidozcan;
import java.lang.ref.WeakReference;
import java.util.Stack;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
//================================================================================
// WeakBox
// This class is a wrapper around any generic value to make it weak referenced to
// avoid memory leaks in certain situations where, say class A holds a strong ref
// to class B and vice versa.
//================================================================================
class WeakBox<Element> {
//================================================================================
// Properties
//================================================================================
private WeakReference<Element> weakRef;
//================================================================================
// Lifecycle
//================================================================================
public WeakBox(Element val) {
if (val != null) {
this.weakRef = new WeakReference<Element>(val);
}
}
//================================================================================
// Public
//================================================================================
public Element getValue() {
return this.weakRef.get();
}
}
//================================================================================
// MinStack
// MinStack is a generic Stack which works with any type of types as elements
// if the given type implements Comparable protocol. MinStack accomplishes following
// operations on constant time: push, pop, top, getMin.
//================================================================================
class MinStack<T extends Comparable> implements Stackable {
//================================================================================
// Properties
//================================================================================
// Stacks
private Stack<WeakBox<T>> valuesStack;
private Stack<WeakBox<T>> minStack;
// Thread safety
private final ReadWriteLock readWriteLock;
private final Lock readLock;
private final Lock writeLock;
//================================================================================
// Lifecycle
//================================================================================
public MinStack() {
valuesStack = new Stack<WeakBox<T>>();
minStack = new Stack<WeakBox<T>>();
readWriteLock = new ReentrantReadWriteLock();
readLock = readWriteLock.readLock();
writeLock = readWriteLock.writeLock();
}
//================================================================================
// Properties
//================================================================================
public void push(T val) {
if (val == null) return;
// Entering the critical section
writeLock.lock();
// Creating the WeakBox
WeakBox<T> newValueWeakBox = new WeakBox(val);
if (newValueWeakBox == null) return;
// Pushing to the values stack
valuesStack.push(newValueWeakBox);
if (shouldAddValueToMinStack(val)) {
minStack.push(newValueWeakBox);
}
// Leaving the critical section
writeLock.unlock();
}
public void pop() {
writeLock.lock();
valuesStack.pop();
minStack.pop();
writeLock.unlock();
}
public T top() {
readLock.lock();
T poppedElement = valuesStack.peek().getValue();
readLock.unlock();
return poppedElement;
}
public T getMin() {
readLock.lock();
T minElement = minStack.peek().getValue();
readLock.unlock();
return minElement;
}
private boolean shouldAddValueToMinStack(T val) {
// If the min stack is empty add the new value directly
if (minStack.isEmpty()) return true;
// If the new value is less than the minStack.peek()
// Then push the new value to the stack
WeakBox<T> peekedValueFromMinStack = minStack.peek();
T unwrappedPeekedVal = peekedValueFromMinStack.getValue();
if (unwrappedPeekedVal.equals(null)) return false;
return val.compareTo(unwrappedPeekedVal) < 0;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment