data_structures_free

This commit is contained in:
2014-03-24 18:47:50 +01:00
commit 6f92828c96
65 changed files with 4738 additions and 0 deletions

View File

@@ -0,0 +1,115 @@
package net.datastructures;
import java.util.Comparator;
//begin#fragment AVLTree
/** Implementation of an AVL tree. */
//end#fragment AVLTree
/**
* AVLTree class - implements an AVL Tree by extending a binary
* search tree.
*
* @author Michael Goodrich, Roberto Tamassia, Eric Zamore
*/
//begin#fragment AVLTree
public class AVLTree<K,V>
extends BinarySearchTree<K,V> implements Dictionary<K,V> {
public AVLTree(Comparator<K> c) { super(c); }
public AVLTree() { super(); }
/** Nested class for the nodes of an AVL tree. */
protected static class AVLNode<K,V> extends BTNode<Entry<K,V>> {
protected int height; // we add a height field to a BTNode
AVLNode() {/* default constructor */}
/** Preferred constructor */
AVLNode(Entry<K,V> element, BTPosition<Entry<K,V>> parent,
BTPosition<Entry<K,V>> left, BTPosition<Entry<K,V>> right) {
super(element, parent, left, right);
height = 0;
if (left != null)
height = Math.max(height, 1 + ((AVLNode<K,V>) left).getHeight());
if (right != null)
height = Math.max(height, 1 + ((AVLNode<K,V>) right).getHeight());
} // we assume that the parent will revise its height if needed
public void setHeight(int h) { height = h; }
public int getHeight() { return height; }
}
/** Creates a new binary search tree node (overrides super's version). */
protected BTPosition<Entry<K,V>> createNode(Entry<K,V> element,
BTPosition<Entry<K,V>> parent, BTPosition<Entry<K,V>> left,
BTPosition<Entry<K,V>> right) {
return new AVLNode<K,V>(element,parent,left,right); // now use AVL nodes
}
/** Returns the height of a node (call back to an AVLNode). */
protected int height(Position<Entry<K,V>> p) {
return ((AVLNode<K,V>) p).getHeight();
}
/** Sets the height of an internal node (call back to an AVLNode). */
protected void setHeight(Position<Entry<K,V>> p) {
((AVLNode<K,V>) p).setHeight(1+Math.max(height(left(p)), height(right(p))));
}
/** Returns whether a node has balance factor between -1 and 1. */
protected boolean isBalanced(Position<Entry<K,V>> p) {
int bf = height(left(p)) - height(right(p));
return ((-1 <= bf) && (bf <= 1));
}
//end#fragment AVLTree
//begin#fragment AVLTree2
/** Returns a child of p with height no smaller than that of the other child */
//end#fragment AVLTree2
/**
* Return a child of p with height no smaller than that of the
* other child.
*/
//begin#fragment AVLTree2
protected Position<Entry<K,V>> tallerChild(Position<Entry<K,V>> p) {
if (height(left(p)) > height(right(p))) return left(p);
else if (height(left(p)) < height(right(p))) return right(p);
// equal height children - break tie using parent's type
if (isRoot(p)) return left(p);
if (p == left(parent(p))) return left(p);
else return right(p);
}
/**
* Rebalance method called by insert and remove. Traverses the path from
* zPos to the root. For each node encountered, we recompute its height
* and perform a trinode restructuring if it's unbalanced.
*/
protected void rebalance(Position<Entry<K,V>> zPos) {
if(isInternal(zPos))
setHeight(zPos);
while (!isRoot(zPos)) { // traverse up the tree towards the root
zPos = parent(zPos);
setHeight(zPos);
if (!isBalanced(zPos)) {
// perform a trinode restructuring at zPos's tallest grandchild
Position<Entry<K,V>> xPos = tallerChild(tallerChild(zPos));
zPos = restructure(xPos); // tri-node restructure (from parent class)
setHeight(left(zPos)); // recompute heights
setHeight(right(zPos));
setHeight(zPos);
}
}
}
// overridden methods of the dictionary ADT
//end#fragment AVLTree2
/**
* Inserts an item into the dictionary and returns the newly created
* entry.
*/
//begin#fragment AVLTree2
public Entry<K,V> insert(K k, V v) throws InvalidKeyException {
Entry<K,V> toReturn = super.insert(k, v); // calls our createNode method
rebalance(actionPos); // rebalance up from the insertion position
return toReturn;
}
//end#fragment AVLTree2
/** Removes and returns an entry from the dictionary. */
//begin#fragment AVLTree2
public Entry<K,V> remove(Entry<K,V> ent) throws InvalidEntryException {
Entry<K,V> toReturn = super.remove(ent);
if (toReturn != null) // we actually removed something
rebalance(actionPos); // rebalance up the tree
return toReturn;
}
} // end of AVLTree class
//end#fragment AVLTree2

View File

@@ -0,0 +1,119 @@
package net.datastructures;
import java.util.Comparator;
//begin#fragment AVLTree
/** Implementation of an AVL tree. */
//end#fragment AVLTree
/**
* AVLTree class - implements an AVL Tree by extending a binary
* search tree.
*
* @author Michael Goodrich, Roberto Tamassia, Eric Zamore
*/
//begin#fragment AVLTree
public class AVLTreeMap<K,V>
extends BinarySearchTreeMap<K,V> implements Map<K,V> {
public AVLTreeMap(Comparator<K> c) { super(c); }
public AVLTreeMap() { super(); }
/** Nested class for the nodes of an AVL tree. */
protected static class AVLNode<K,V> extends BTNode<Entry<K,V>> {
protected int height; // we add a height field to a BTNode
AVLNode() {/* default constructor */}
/** Preferred constructor */
AVLNode(Entry<K,V> element, BTPosition<Entry<K,V>> parent,
BTPosition<Entry<K,V>> left, BTPosition<Entry<K,V>> right) {
super(element, parent, left, right);
height = 0;
if (left != null)
height = Math.max(height, 1 + ((AVLNode<K,V>) left).getHeight());
if (right != null)
height = Math.max(height, 1 + ((AVLNode<K,V>) right).getHeight());
} // we assume that the parent will revise its height if needed
public void setHeight(int h) { height = h; }
public int getHeight() { return height; }
}
/** Creates a new binary search tree node (overrides super's version). */
protected BTPosition<Entry<K,V>> createNode(Entry<K,V> element,
BTPosition<Entry<K,V>> parent, BTPosition<Entry<K,V>> left,
BTPosition<Entry<K,V>> right) {
return new AVLNode<K,V>(element,parent,left,right); // now use AVL nodes
}
/** Returns the height of a node (call back to an AVLNode). */
protected int height(Position<Entry<K,V>> p) {
return ((AVLNode<K,V>) p).getHeight();
}
/** Sets the height of an internal node (call back to an AVLNode). */
protected void setHeight(Position<Entry<K,V>> p) {
((AVLNode<K,V>) p).setHeight(1+Math.max(height(left(p)), height(right(p))));
}
/** Returns whether a node has balance factor between -1 and 1. */
protected boolean isBalanced(Position<Entry<K,V>> p) {
int bf = height(left(p)) - height(right(p));
return ((-1 <= bf) && (bf <= 1));
}
//end#fragment AVLTree
//begin#fragment AVLTree2
/** Returns a child of p with height no smaller than that of the other child */
//end#fragment AVLTree2
/**
* Return a child of p with height no smaller than that of the
* other child.
*/
//begin#fragment AVLTree2
protected Position<Entry<K,V>> tallerChild(Position<Entry<K,V>> p) {
if (height(left(p)) > height(right(p))) return left(p);
else if (height(left(p)) < height(right(p))) return right(p);
// equal height children - break tie using parent's type
if (isRoot(p)) return left(p);
if (p == left(parent(p))) return left(p);
else return right(p);
}
/**
* Rebalance method called by insert and remove. Traverses the path from
* zPos to the root. For each node encountered, we recompute its height
* and perform a trinode restructuring if it's unbalanced.
*/
protected void rebalance(Position<Entry<K,V>> zPos) {
if(isInternal(zPos))
setHeight(zPos);
while (!isRoot(zPos)) { // traverse up the tree towards the root
zPos = parent(zPos);
setHeight(zPos);
if (!isBalanced(zPos)) {
// perform a trinode restructuring at zPos's tallest grandchild
Position<Entry<K,V>> xPos = tallerChild(tallerChild(zPos));
zPos = restructure(xPos); // tri-node restructure (from parent class)
setHeight(left(zPos)); // recompute heights
setHeight(right(zPos));
setHeight(zPos);
}
}
}
// overridden methods of the dictionary ADT
//end#fragment AVLTree2
/**
* If there is an entry with the specified key, replaces the value of
* this entry with the specified value and returns the old value. Else,
* adds a new entry with the specified key and value and returns null.
*/
//begin#fragment AVLTree2
public V put(K k, V v) throws InvalidKeyException {
V toReturn = super.put(k, v); // calls our createNode method if k is new
rebalance(actionPos); // rebalance up from the insertion position
return toReturn;
}
//end#fragment AVLTree2
/**
* If there is an entry with the specified key, removes this entry and
* returns its value. Else, returns null.
*/
//begin#fragment AVLTree2
public V remove(K k) throws InvalidKeyException {
V toReturn = super.remove(k);
if (toReturn != null) // we actually removed something
rebalance(actionPos); // rebalance up the tree
return toReturn;
}
} // end of AVLTree class
//end#fragment AVLTree2

View File

@@ -0,0 +1,75 @@
package net.datastructures;
//begin#fragment vector
/** Realization of an indexed list by means of an array, which is doubled
* when the size of the indexed list exceeds the capacity of the array.
//end#fragment vector
*
* @author Roberto Tamassia, Michael Goodrich
//begin#fragment vector
*/
public class ArrayIndexList<E> implements IndexList<E> {
private E[] A; // array storing the elements of the indexed list
private int capacity = 16; // initial length of array A
private int size = 0; // number of elements stored in the indexed list
/** Creates the indexed list with initial capacity 16. */
public ArrayIndexList() {
A = (E[]) new Object[capacity]; // the compiler may warn, but this is ok
}
//end#fragment vector
/** Returns the number of elements in the indexed list. */
public int size() {
return size;
}
/** Returns whether the indexed list is empty. */
public boolean isEmpty() {
return size() == 0;
}
/** Returns the element stored at the given index. */
public E get(int r)
throws IndexOutOfBoundsException {
checkIndex(r, size());
return A[r];
}
/** Replaces the element stored at the given index. */
public E set(int r, E e)
throws IndexOutOfBoundsException {
checkIndex(r, size());
E temp = A[r];
A[r] = e;
return temp;
}
//begin#fragment vector list
/** Inserts an element at the given index. */
public void add(int r, E e)
throws IndexOutOfBoundsException {
checkIndex(r, size() + 1);
if (size == capacity) { // an overflow
capacity *= 2;
E[] B =(E[]) new Object[capacity];
for (int i=0; i<size; i++)
B[i] = A[i];
A = B;
}
for (int i=size-1; i>=r; i--) // shift elements up
A[i+1] = A[i];
A[r] = e;
size++;
}
/** Removes the element stored at the given index. */
public E remove(int r)
throws IndexOutOfBoundsException {
checkIndex(r, size());
E temp = A[r];
for (int i=r; i<size-1; i++) // shift elements down
A[i] = A[i+1];
size--;
return temp;
}
//end#fragment vector
/** Checks whether the given index is in the range [0, n - 1] */
protected void checkIndex(int r, int n) //
throws IndexOutOfBoundsException { //
if (r < 0 || r >= n)
throw new IndexOutOfBoundsException("Illegal index: " + r);
}
}

View File

@@ -0,0 +1,192 @@
package net.datastructures;
import java.util.ArrayList;
import java.util.Iterator;
/**
* A speedy implementation of the CompleteBinaryTree interface using
* a vector. Within the vector, there is a null element at rank 0,
* the root of the tree at rank 1, and the rest of the tree is
* contained as follows. If node <code>n</code> has rank <i>i</i>,
* then the left child of <code>n</code> will have rank 2*<i>i</i>,
* and the right child of <code>n</code> will have rank 2*<i>i</i> +
* 1. Traversing the contents of the vector in order of increasing
* rank yields a level-order traversal
*
* @author Michael Goodrich, Eric Zamore
* @see BinaryTree
* @see CompleteBinaryTree
*/
//begin#fragment VectorHeap
public class ArrayListCompleteBinaryTree<E>
implements CompleteBinaryTree<E> {
protected ArrayList<BTPos<E>> T; // indexed list of tree positions
/** Nested class for a index list-based complete binary tree node. */
protected static class BTPos<E> implements Position<E> {
E element; // element stored at this position
int index; // index of this position in the array list
public BTPos(E elt, int i) {
element = elt;
index = i;
}
public E element() { return element; }
public int index() { return index; }
public E setElement(E elt) {
E temp = element;
element = elt;
return temp;
}
//end#fragment VectorHeap
public String toString() {
return("[" + element + "," + index + "]");
}
//begin#fragment VectorHeap
}
/** default constructor */
public ArrayListCompleteBinaryTree() {
T = new ArrayList<BTPos<E>>();
T.add(0, null); // the location at rank 0 is deliberately empty
}
/** Returns the number of (internal and external) nodes. */
public int size() { return T.size() - 1; }
/** Returns whether the tree is empty. */
public boolean isEmpty() { return (size() == 0); }
//end#fragment VectorHeap
//begin#fragment VectorHeap2
/** Returns whether v is an internal node. */
public boolean isInternal(Position<E> v) throws InvalidPositionException {
return hasLeft(v); // if v has a right child it will have a left child
}
/** Returns whether v is an external node. */
public boolean isExternal(Position<E> v) throws InvalidPositionException {
return !isInternal(v);
}
/** Returns whether v is the root node. */
public boolean isRoot(Position<E> v) throws InvalidPositionException {
BTPos<E> vv = checkPosition(v);
return vv.index() == 1;
}
/** Returns whether v has a left child. */
public boolean hasLeft(Position<E> v) throws InvalidPositionException {
BTPos<E> vv = checkPosition(v);
return 2*vv.index() <= size();
}
/** Returns whether v has a right child. */
public boolean hasRight(Position<E> v) throws InvalidPositionException {
BTPos<E> vv = checkPosition(v);
return 2*vv.index() + 1 <= size();
}
/** Returns the root of the tree. */
public Position<E> root() throws EmptyTreeException {
if (isEmpty()) throw new EmptyTreeException("Tree is empty");
return T.get(1);
}
/** Returns the left child of v. */
public Position<E> left(Position<E> v)
throws InvalidPositionException, BoundaryViolationException {
if (!hasLeft(v)) throw new BoundaryViolationException("No left child");
BTPos<E> vv = checkPosition(v);
return T.get(2*vv.index());
}
/** Returns the right child of v. */
public Position<E> right(Position<E> v)
throws InvalidPositionException {
if (!hasRight(v)) throw new BoundaryViolationException("No right child");
BTPos<E> vv = checkPosition(v);
return T.get(2*vv.index() + 1);
}
//end#fragment VectorHeap2
//begin#fragment VectorHeap3
/** Returns the parent of v. */
public Position<E> parent(Position<E> v)
throws InvalidPositionException, BoundaryViolationException {
if (isRoot(v)) throw new BoundaryViolationException("No parent");
BTPos<E> vv = checkPosition(v);
return T.get(vv.index()/2);
}
//end#fragment VectorHeap3
/** Returns an iterable collection of the children of v. */
public Iterable<Position<E>> children(Position<E> v) throws InvalidPositionException {
PositionList<Position<E>> children = new NodePositionList<Position<E>>();
if (hasLeft(v))
children.addLast(left(v));
if (hasRight(v))
children.addLast(right(v));
return children;
}
/** Returns an iterable collection of all the nodes in the tree. */
public Iterable<Position<E>> positions() {
ArrayList<Position<E>> P = new ArrayList<Position<E>>();
Iterator<BTPos<E>> iter = T.iterator();
iter.next(); // skip the first position
while (iter.hasNext())
P.add(iter.next());
return P;
}
//begin#fragment VectorHeap3
/** Replaces the element at v. */
public E replace(Position<E> v, E o) throws InvalidPositionException {
BTPos<E> vv = checkPosition(v);
return vv.setElement(o);
}
/** Adds an element just after the last node (in a level numbering). */
public Position<E> add(E e) {
int i = size() + 1;
BTPos<E> p = new BTPos<E>(e,i);
T.add(i, p);
return p;
}
/** Removes and returns the element at the last node. */
public E remove() throws EmptyTreeException {
if(isEmpty()) throw new EmptyTreeException("Tree is empty");
return T.remove(size()).element();
}
/** Determines whether the given position is a valid node. */
protected BTPos<E> checkPosition(Position<E> v)
throws InvalidPositionException
{
if (v == null || !(v instanceof BTPos))
throw new InvalidPositionException("Position is invalid");
return (BTPos<E>) v;
}
//end#fragment VectorHeap3
// Additional Methods
/** Returns the sibling of v. */
public Position<E> sibling(Position<E> v)
throws InvalidPositionException, BoundaryViolationException {
try {
Position<E> p = parent(v);
Position<E> lc = left(p);
if (v == lc)
return right(p);
else
return lc;
}
catch(BoundaryViolationException e) {
throw new BoundaryViolationException("Node has no sibling");
}
}
/** Swaps the elements at two nodes. */
public void swapElements(Position<E> v, Position<E> w)
throws InvalidPositionException {
BTPos<E> vv = checkPosition(v);
BTPos<E> ww = checkPosition(w);
E temp = vv.element();
vv.setElement(ww.element());
ww.setElement(temp);
}
//begin#fragment VectorHeap3
/** Returns an iterator of the elements stored at all nodes in the tree. */
public Iterator<E> iterator() {
ArrayList<E> list = new ArrayList<E>();
Iterator<BTPos<E>> iter = T.iterator();
iter.next(); // skip the first element
while (iter.hasNext())
list.add(iter.next().element());
return list.iterator();
}
//end#fragment VectorHeap3
/** Returns a String representing this complete binary tree. */
public String toString() { return T.toString(); }
//begin#fragment VectorHeap3
}
//end#fragment VectorHeap3

View File

@@ -0,0 +1,189 @@
package net.datastructures;
//begin#fragment ArrayStack
/**
* Implementation of the stack ADT using a fixed-length array. An
* exception is thrown if a push operation is attempted when the size
* of the stack is equal to the length of the array. This class
* includes the main methods of the built-in class java.util.Stack.
//end#fragment ArrayStack
*
* @author Natasha Gelfand
* @author Roberto Tamassia
* @see FullStackException
//begin#fragment ArrayStack
*/
//begin#fragment ArrayStack
public class ArrayStack<E> implements Stack<E> {
//end#fragment ArrayStack
/**
* Length of the array used to implement the stack.
*/
//begin#fragment ArrayStack
protected int capacity; // The actual capacity of the stack array
//end#fragment ArrayStack
/**
* Default array capacity.
*/
//begin#fragment ArrayStack
public static final int CAPACITY = 1000; // default array capacity
//end#fragment ArrayStack
/**
* Array used to implement the stack.
*/
//begin#fragment ArrayStack
protected E S[]; // Generic array used to implement the stack
//end#fragment ArrayStack
/**
* Index of the top element of the stack in the array.
*/
//begin#fragment ArrayStack
protected int top = -1; // index for the top of the stack
//end#fragment ArrayStack
/**
* Initializes the stack to use an array of default length.
*/
//begin#fragment ArrayStack
public ArrayStack() {
this(CAPACITY); // default capacity
}
//end#fragment ArrayStack
/**
* Initializes the stack to use an array of given length.
* @param cap length of the array.
*/
//begin#fragment ArrayStack
public ArrayStack(int cap) {
capacity = cap;
S = (E[]) new Object[capacity]; // compiler may give warning, but this is ok
}
//end#fragment ArrayStack
/**
* Returns the number of elements in the stack.
* This method runs in O(1) time.
* @return number of elements in the stack.
*/
//begin#fragment ArrayStack
public int size() {
return (top + 1);
}
//end#fragment ArrayStack
/**
* Testes whether the stack is empty.
* This method runs in O(1) time.
* @return true if the stack is empty, false otherwise.
*/
//begin#fragment ArrayStack
public boolean isEmpty() {
return (top < 0);
}
//end#fragment ArrayStack
/**
* Inserts an element at the top of the stack.
* This method runs in O(1) time.
* @return element inserted.
* @param element element to be inserted.
* @exception FullStackException if the array storing the elements is full.
*/
//begin#fragment ArrayStack
public void push(E element) throws FullStackException {
if (size() == capacity)
throw new FullStackException("Stack is full.");
S[++top] = element;
}
//end#fragment ArrayStack
/**
* Inspects the element at the top of the stack.
* This method runs in O(1) time.
* @return top element in the stack.
* @exception EmptyStackException if the stack is empty.
*/
//begin#fragment ArrayStack
public E top() throws EmptyStackException {
if (isEmpty())
throw new EmptyStackException("Stack is empty.");
return S[top];
}
//end#fragment ArrayStack
/**
* Removes the top element from the stack.
* This method runs in O(1) time.
* @return element removed.
* @exception EmptyStackException if the stack is empty.
*/
//begin#fragment ArrayStack
public E pop() throws EmptyStackException {
E element;
if (isEmpty())
throw new EmptyStackException("Stack is empty.");
element = S[top];
S[top--] = null; // dereference S[top] for garbage collection.
return element;
}
//end#fragment ArrayStack
/**
* Returns a string representation of the stack as a list of elements,
* with the top element at the end: [ ... , prev, top ].
* This method runs in O(n) time, where n is the size of the stack.
* @return textual representation of the stack.
*/
//begin#fragment ArrayStack2
public String toString() {
String s;
s = "[";
if (size() > 0) s+= S[0];
if (size() > 1)
for (int i = 1; i <= size()-1; i++) {
s += ", " + S[i];
}
return s + "]";
}
//end#fragment ArrayStack2
/**
* Prints status information about a recent operation and the stack.
* @param op operation performed
* @param element element returned by the operation
* @return information about the operation performed, the element
* returned by the operation and the content of the stack after
* the operation.
*/
//begin#fragment ArrayStack2
// Prints status information about a recent operation and the stack.
public void status(String op, Object element) {
System.out.print("------> " + op); // print this operation
System.out.println(", returns " + element); // what was returned
System.out.print("result: size = " + size() + ", isEmpty = " + isEmpty());
System.out.println(", stack: " + this); // contents of the stack
}
//end#fragment ArrayStack2
//begin#fragment ArrayStack2
/**
* Test our program by performing a series of operations on stacks,
* printing the operations performed, the returned elements and the
* contents of the stack involved, after each operation.
*/
public static void main(String[] args) {
Object o;
ArrayStack<Integer> A = new ArrayStack<Integer>();
A.status("new ArrayStack<Integer> A", null);
A.push(7);
A.status("A.push(7)", null);
o = A.pop();
A.status("A.pop()", o);
A.push(9);
A.status("A.push(9)", null);
o = A.pop();
A.status("A.pop()", o);
ArrayStack<String> B = new ArrayStack<String>();
B.status("new ArrayStack<String> B", null);
B.push("Bob");
B.status("B.push(\"Bob\")", null);
B.push("Alice");
B.status("B.push(\"Alice\")", null);
o = B.pop();
B.status("B.pop()", o);
B.push("Eve");
B.status("B.push(\"Eve\")", null);
}
}
//end#fragment ArrayStack2

View File

@@ -0,0 +1,43 @@
package net.datastructures;
//begin#fragment BTNode
/**
* Class implementing a node of a binary tree by storing references to
* an element, a parent node, a left node, and a right node.
//end#fragment BTNode
*
* @author Luca Vismara, Roberto Tamassia, Michael Goodrich
//begin#fragment BTNode
*/
public class BTNode<E> implements BTPosition<E> {
private E element; // element stored at this node
private BTPosition<E> left, right, parent; // adjacent nodes
//end#fragment BTNode
/** Default constructor */
public BTNode() { }
//begin#fragment BTNode
/** Main constructor */
public BTNode(E element, BTPosition<E> parent,
BTPosition<E> left, BTPosition<E> right) {
setElement(element);
setParent(parent);
setLeft(left);
setRight(right);
}
/** Returns the element stored at this position */
public E element() { return element; }
/** Sets the element stored at this position */
public void setElement(E o) { element=o; }
/** Returns the left child of this position */
public BTPosition<E> getLeft() { return left; }
/** Sets the left child of this position */
public void setLeft(BTPosition<E> v) { left=v; }
/** Returns the right child of this position */
public BTPosition<E> getRight() { return right; }
/** Sets the right child of this position */
public void setRight(BTPosition<E> v) { right=v; }
/** Returns the parent of this position */
public BTPosition<E> getParent() { return parent; }
/** Sets the parent of this position */
public void setParent(BTPosition<E> v) { parent=v; }
}
//end#fragment BTNode

View File

@@ -0,0 +1,20 @@
package net.datastructures;
//begin#fragment BTPos
/**
* Interface for a node of a binary tree. It maintains an element, a
* parent node, a left node, and a right node.
//end#fragment BTPos
*
* @author Michael Goodrich
//begin#fragment BTPos
*/
public interface BTPosition<E> extends Position<E> { // inherits element()
public void setElement(E o);
public BTPosition<E> getLeft();
public void setLeft(BTPosition<E> v);
public BTPosition<E> getRight();
public void setRight(BTPosition<E> v);
public BTPosition<E> getParent();
public void setParent(BTPosition<E> v);
}
//end#fragment BTPos

View File

@@ -0,0 +1,268 @@
package net.datastructures;
import java.util.Comparator;
import java.util.Iterator;
/**
* Realization of a dictionary by means of a binary search tree.
* @author Michael Goodrich, Eric Zamore
*/
//begin#fragment BinarySearchTree
// Realization of a dictionary by means of a binary search tree
public class BinarySearchTree<K,V>
extends LinkedBinaryTree<Entry<K,V>> implements Dictionary<K,V> {
//end#fragment BinarySearchTree
// Instance variables:
//begin#fragment BinarySearchTree
protected Comparator<K> C; // comparator
protected Position<Entry<K,V>>
actionPos; // insert node or removed node's parent
protected int numEntries = 0; // number of entries
/** Creates a BinarySearchTree with a default comparator. */
public BinarySearchTree() {
C = new DefaultComparator<K>();
addRoot(null);
}
//end#fragment BinarySearchTree
/** Creates a BinarySearchTree with the given comparator. */
//begin#fragment BinarySearchTree
public BinarySearchTree(Comparator<K> c) {
C = c;
addRoot(null);
}
/** Nested class for location-aware binary search tree entries */
protected static class BSTEntry<K,V> implements Entry<K,V> {
protected K key;
protected V value;
protected Position<Entry<K,V>> pos;
BSTEntry() { /* default constructor */ }
BSTEntry(K k, V v, Position<Entry<K,V>> p) {
key = k; value = v; pos = p;
}
public K getKey() { return key; }
public V getValue() { return value; }
public Position<Entry<K,V>> position() { return pos; }
}
//end#fragment BinarySearchTree
// Auxiliary methods:
//begin#fragment BinarySearchTree
/** Extracts the key of the entry at a given node of the tree. */
protected K key(Position<Entry<K,V>> position) {
return position.element().getKey();
}
/** Extracts the value of the entry at a given node of the tree. */
protected V value(Position<Entry<K,V>> position) {
return position.element().getValue();
}
/** Extracts the entry at a given node of the tree. */
protected Entry<K,V> entry(Position<Entry<K,V>> position) {
return position.element();
}
/** Replaces an entry with a new entry (and reset the entry's location) */
protected void replaceEntry(Position <Entry<K,V>> pos, Entry<K,V> ent) {
((BSTEntry<K,V>) ent).pos = pos;
replace(pos, ent);
}
//end#fragment BinarySearchTree
//begin#fragment BinarySearchTree2
/** Checks whether a given key is valid. */
protected void checkKey(K key) throws InvalidKeyException {
if(key == null) // just a simple test for now
throw new InvalidKeyException("null key");
}
/** Checks whether a given entry is valid. */
protected void checkEntry(Entry<K,V> ent) throws InvalidEntryException {
if(ent == null || !(ent instanceof BSTEntry))
throw new InvalidEntryException("invalid entry");
}
/** Auxiliary method for inserting an entry at an external node */
protected Entry<K,V> insertAtExternal(Position<Entry<K,V>> v, Entry<K,V> e) {
expandExternal(v,null,null);
replace(v, e);
numEntries++;
return e;
}
/** Auxiliary method for removing an external node and its parent */
protected void removeExternal(Position<Entry<K,V>> v) {
removeAboveExternal(v);
numEntries--;
}
/** Auxiliary method used by find, insert, and remove. */
protected Position<Entry<K,V>> treeSearch(K key, Position<Entry<K,V>> pos) {
if (isExternal(pos)) return pos; // key not found; return external node
else {
K curKey = key(pos);
int comp = C.compare(key, curKey);
if (comp < 0)
return treeSearch(key, left(pos)); // search left subtree
else if (comp > 0)
return treeSearch(key, right(pos)); // search right subtree
return pos; // return internal node where key is found
}
}
//end#fragment BinarySearchTree2
/** Adds to L all entries in the subtree rooted at v having keys
* equal to k. */
//begin#fragment BinarySearchTree2
// Adds to L all entries in the subtree rooted at v having keys equal to k
protected void addAll(PositionList<Entry<K,V>> L,
Position<Entry<K,V>> v, K k) {
if (isExternal(v)) return;
Position<Entry<K,V>> pos = treeSearch(k, v);
if (!isExternal(pos)) { // we found an entry with key equal to k
addAll(L, left(pos), k);
L.addLast(pos.element()); // add entries in inorder
addAll(L, right(pos), k);
} // this recursive algorithm is simple, but it's not the fastest
}
//end#fragment BinarySearchTree2
//begin#fragment BinarySearchTree3
// methods of the dictionary ADT
//end#fragment BinarySearchTree3
/** Returns the number of entries in the tree. */
//begin#fragment BinarySearchTree3
public int size() { return numEntries; }
//end#fragment BinarySearchTree3
/** Returns whether the tree is empty. */
//begin#fragment BinarySearchTree3
public boolean isEmpty() { return size() == 0; }
//end#fragment BinarySearchTree3
/** Returns an entry containing the given key. Returns null if no
* such entry exists. */
//begin#fragment BinarySearchTree3
public Entry<K,V> find(K key) throws InvalidKeyException {
checkKey(key); // may throw an InvalidKeyException
Position<Entry<K,V>> curPos = treeSearch(key, root());
actionPos = curPos; // node where the search ended
if (isInternal(curPos)) return entry(curPos);
return null;
}
//end#fragment BinarySearchTree3
/** Returns an iterable collection of all the entries containing the
* given key. */
//begin#fragment BinarySearchTree3
public Iterable<Entry<K,V>> findAll(K key) throws InvalidKeyException {
checkKey(key); // may throw an InvalidKeyException
PositionList<Entry<K,V>> L = new NodePositionList<Entry<K,V>>();
addAll(L, root(), key);
return L;
}
//end#fragment BinarySearchTree3
/** Inserts an entry into the tree and returns the newly created entry. */
//begin#fragment BinarySearchTree3
public Entry<K,V> insert(K k, V x) throws InvalidKeyException {
checkKey(k); // may throw an InvalidKeyException
Position<Entry<K,V>> insPos = treeSearch(k, root());
while (!isExternal(insPos)) // iterative search for insertion position
insPos = treeSearch(k, left(insPos));
actionPos = insPos; // node where the new entry is being inserted
return insertAtExternal(insPos, new BSTEntry<K,V>(k, x, insPos));
}
//end#fragment BinarySearchTree3
/** Removes and returns a given entry. */
//begin#fragment BinarySearchTree3
public Entry<K,V> remove(Entry<K,V> ent) throws InvalidEntryException {
checkEntry(ent); // may throw an InvalidEntryException
Position<Entry<K,V>> remPos = ((BSTEntry<K,V>) ent).position();
Entry<K,V> toReturn = entry(remPos); // entry to be returned
if (isExternal(left(remPos))) remPos = left(remPos); // left easy case
else if (isExternal(right(remPos))) remPos = right(remPos); // right easy case
else { // entry is at a node with internal children
Position<Entry<K,V>> swapPos = remPos; // find node for moving entry
remPos = right(swapPos);
do
remPos = left(remPos);
while (isInternal(remPos));
replaceEntry(swapPos, (Entry<K,V>) parent(remPos).element());
}
actionPos = sibling(remPos); // sibling of the leaf to be removed
removeExternal(remPos);
return toReturn;
}
//end#fragment BinarySearchTree3
/** Returns an iterator containing all entries in the tree. */
public Iterable<Entry<K,V>> entries() {
PositionList<Entry<K,V>> entries = new NodePositionList<Entry<K,V>>();
Iterable<Position<Entry<K,V>>> positer = positions();
for (Position<Entry<K,V>> cur: positer)
if (isInternal(cur))
entries.addLast(cur.element());
return entries;
}
/**
* Performs a tri-node restructuring. Assumes the nodes are in one
* of following configurations:
*
* <pre>
* z=c z=c z=a z=a
* / \ / \ / \ / \
* y=b t4 y=a t4 t1 y=c t1 y=b
* / \ / \ / \ / \
* x=a t3 t1 x=b x=b t4 t2 x=c
* / \ / \ / \ / \
* t1 t2 t2 t3 t2 t3 t3 t4
* </pre>
* @return the new root of the restructured subtree
*/
protected Position<Entry<K,V>> restructure(Position<Entry<K,V>> x) {
BTPosition<Entry<K,V>> a, b, c, t1, t2, t3, t4;
Position<Entry<K,V>> y = parent(x); // assumes x has a parent
Position<Entry<K,V>> z = parent(y); // assumes y has a parent
boolean xLeft = (x == left(y));
boolean yLeft = (y == left(z));
BTPosition<Entry<K,V>> xx = (BTPosition<Entry<K,V>>)x,
yy = (BTPosition<Entry<K,V>>)y, zz = (BTPosition<Entry<K,V>>)z;
if (xLeft && yLeft) {
a = xx; b = yy; c = zz;
t1 = a.getLeft(); t2 = a.getRight(); t3 = b.getRight(); t4 = c.getRight();
}
else if (!xLeft && yLeft) {
a = yy; b = xx; c = zz;
t1 = a.getLeft(); t2 = b.getLeft(); t3 = b.getRight(); t4 = c.getRight();
}
else if (xLeft && !yLeft) {
a = zz; b = xx; c = yy;
t1 = a.getLeft(); t2 = b.getLeft(); t3 = b.getRight(); t4 = c.getRight();
}
else { // right-right
a = zz; b = yy; c = xx;
t1 = a.getLeft(); t2 = b.getLeft(); t3 = c.getLeft(); t4 = c.getRight();
}
// put b at z's place
if (isRoot(z)) {
root = b;
b.setParent(null);
}
else {
BTPosition<Entry<K,V>> zParent = (BTPosition<Entry<K,V>>)parent(z);
if (z == left(zParent)) {
b.setParent(zParent);
zParent.setLeft(b);
}
else { // z was a right child
b.setParent(zParent);
zParent.setRight(b);
}
}
// place the rest of the nodes and their children
b.setLeft(a);
a.setParent(b);
b.setRight(c);
c.setParent(b);
a.setLeft(t1);
t1.setParent(a);
a.setRight(t2);
t2.setParent(a);
c.setLeft(t3);
t3.setParent(c);
c.setRight(t4);
t4.setParent(c);
// Reset the location-aware entries
((BSTEntry<K,V>) a.element()).pos = a;
((BSTEntry<K,V>) b.element()).pos = b;
((BSTEntry<K,V>) c.element()).pos = c;
return b; // the new root of this subtree
}
//begin#fragment BinarySearchTree3
} // entries() method is omitted here
//end#fragment BinarySearchTree3

View File

@@ -0,0 +1,276 @@
package net.datastructures;
import java.util.Comparator;
import java.util.Iterator;
/**
* Realization of a map by means of a binary search tree.
* @author Michael Goodrich, Eric Zamore
*/
//begin#fragment BinarySearchTree
// Realization of a map by means of a binary search tree
public class BinarySearchTreeMap<K,V>
extends LinkedBinaryTree<Entry<K,V>> implements Map<K,V> {
//end#fragment BinarySearchTree
// Instance variables:
//begin#fragment BinarySearchTree
protected Comparator<K> C; // comparator
protected Position<Entry<K,V>>
actionPos; // insert node or removed node's parent
protected int numEntries = 0; // number of entries
/** Creates a BinarySearchTreeMap with a default comparator. */
public BinarySearchTreeMap() {
C = new DefaultComparator<K>();
addRoot(null);
}
//end#fragment BinarySearchTree
/** Creates a BinarySearchTreeMap with the given comparator. */
//begin#fragment BinarySearchTree
public BinarySearchTreeMap(Comparator<K> c) {
C = c;
addRoot(null);
}
/** Nested class for location-aware binary search tree entries */
protected static class BSTEntry<K,V> implements Entry<K,V> {
protected K key;
protected V value;
protected Position<Entry<K,V>> pos;
BSTEntry() { /* default constructor */ }
BSTEntry(K k, V v, Position<Entry<K,V>> p) {
key = k; value = v; pos = p;
}
public K getKey() { return key; }
public V getValue() { return value; }
public Position<Entry<K,V>> position() { return pos; }
}
//end#fragment BinarySearchTree
// Auxiliary methods:
//begin#fragment BinarySearchTree
/** Extracts the key of the entry at a given node of the tree. */
protected K key(Position<Entry<K,V>> position) {
return position.element().getKey();
}
/** Extracts the value of the entry at a given node of the tree. */
protected V value(Position<Entry<K,V>> position) {
return position.element().getValue();
}
/** Extracts the entry at a given node of the tree. */
protected Entry<K,V> entry(Position<Entry<K,V>> position) {
return position.element();
}
//end#fragment BinarySearchTree
//begin#fragment BinarySearchTree2
/** Replaces an entry with a new entry (and reset the entry's location) */
protected V replaceEntry(Position <Entry<K,V>> pos, Entry<K,V> ent) {
((BSTEntry<K,V>) ent).pos = pos;
return replace(pos, ent).getValue();
}
/** Checks whether a given key is valid. */
protected void checkKey(K key) throws InvalidKeyException {
if(key == null) // just a simple test for now
throw new InvalidKeyException("null key");
}
/** Checks whether a given entry is valid. */
protected void checkEntry(Entry<K,V> ent) throws InvalidEntryException {
if(ent == null || !(ent instanceof BSTEntry))
throw new InvalidEntryException("invalid entry");
}
/** Auxiliary method for inserting an entry at an external node */
protected Entry<K,V> insertAtExternal(Position<Entry<K,V>> v, Entry<K,V> e) {
expandExternal(v,null,null);
replace(v, e);
numEntries++;
return e;
}
/** Auxiliary method for removing an external node and its parent */
protected void removeExternal(Position<Entry<K,V>> v) {
removeAboveExternal(v);
numEntries--;
}
/** Auxiliary method used by get, put, and remove. */
protected Position<Entry<K,V>> treeSearch(K key, Position<Entry<K,V>> pos) {
if (isExternal(pos)) return pos; // key not found; return external node
else {
K curKey = key(pos);
int comp = C.compare(key, curKey);
if (comp < 0)
return treeSearch(key, left(pos)); // search left subtree
else if (comp > 0)
return treeSearch(key, right(pos)); // search right subtree
return pos; // return internal node where key is found
}
}
//end#fragment BinarySearchTree2
/** Adds to L all entries in the subtree rooted at v having keys
* equal to k. */
//begin#fragment BinarySearchTree3
// methods of the map ADT
//end#fragment BinarySearchTree3
/** Returns the number of entries in the tree. */
//begin#fragment BinarySearchTree3
public int size() { return numEntries; }
//end#fragment BinarySearchTree3
/** Returns whether the tree is empty. */
//begin#fragment BinarySearchTree3
public boolean isEmpty() { return size() == 0; }
//end#fragment BinarySearchTree3
/**
* Returns the value of the entry containing the given key. Returns
* null if no such entry exists.
*/
//begin#fragment BinarySearchTree3
public V get(K key) throws InvalidKeyException {
checkKey(key); // may throw an InvalidKeyException
Position<Entry<K,V>> curPos = treeSearch(key, root());
actionPos = curPos; // node where the search ended
if (isInternal(curPos)) return value(curPos);
return null;
}
//end#fragment BinarySearchTree3
/**
* If there is an entry with the specified key, replaces the value of
* this entry with the specified value and returns the old value. Else,
* adds a new entry with the specified key and value and returns null.
*/
//begin#fragment BinarySearchTree3
public V put(K k, V x) throws InvalidKeyException {
checkKey(k); // may throw an InvalidKeyException
Position<Entry<K,V>> insPos = treeSearch(k, root());
BSTEntry<K,V> e = new BSTEntry<K,V>(k, x, insPos);
actionPos = insPos; // node where the entry is being inserted
if (isExternal(insPos)) { // we need a new node, key is new
insertAtExternal(insPos, e).getValue();
return null;
}
return replaceEntry(insPos, e); // key already exists
}
//end#fragment BinarySearchTree3
/**
* If there is an entry with the specified key, removes this entry and
* returns its value. Else, returns null.
*/
//begin#fragment BinarySearchTree3
public V remove(K k) throws InvalidKeyException {
checkKey(k); // may throw an InvalidKeyException
Position<Entry<K,V>> remPos = treeSearch(k, root());
if (isExternal(remPos)) return null; // key not found
Entry<K,V> toReturn = entry(remPos); // old entry
if (isExternal(left(remPos))) remPos = left(remPos); // left easy case
else if (isExternal(right(remPos))) remPos = right(remPos); // right easy case
else { // entry is at a node with internal children
Position<Entry<K,V>> swapPos = remPos; // find node for moving entry
remPos = right(swapPos);
do
remPos = left(remPos);
while (isInternal(remPos));
replaceEntry(swapPos, (Entry<K,V>) parent(remPos).element());
}
actionPos = sibling(remPos); // sibling of the leaf to be removed
removeExternal(remPos);
return toReturn.getValue();
}
//end#fragment BinarySearchTree3
/** Returns an iterable object containing all keys in the tree. */
public Iterable<K> keySet() {
PositionList<K> keys = new NodePositionList<K>();
Iterable<Position<Entry<K,V>>> positer = positions();
for (Position<Entry<K,V>> cur: positer)
if (isInternal(cur))
keys.addLast(key(cur));
return keys;
}
/** Returns an iterable object containing all values in the tree. */
public Iterable<V> values() {
PositionList<V> vals = new NodePositionList<V>();
Iterable<Position<Entry<K,V>>> positer = positions();
for (Position<Entry<K,V>> cur: positer)
if (isInternal(cur))
vals.addLast(value(cur));
return vals;
}
/** Returns an iterable object containing all entries in the tree. */
public Iterable<Entry<K,V>> entrySet() {
PositionList<Entry<K,V>> entries = new NodePositionList<Entry<K,V>>();
Iterable<Position<Entry<K,V>>> positer = positions();
for (Position<Entry<K,V>> cur: positer)
if (isInternal(cur))
entries.addLast(cur.element());
return entries;
}
/**
* Performs a tri-node restructuring. Assumes the nodes are in one
* of following configurations:
*
* <pre>
* z=c z=c z=a z=a
* / \ / \ / \ / \
* y=b t4 y=a t4 t1 y=c t1 y=b
* / \ / \ / \ / \
* x=a t3 t1 x=b x=b t4 t2 x=c
* / \ / \ / \ / \
* t1 t2 t2 t3 t2 t3 t3 t4
* </pre>
* @return the new root of the restructured subtree
*/
protected Position<Entry<K,V>> restructure(Position<Entry<K,V>> x) {
BTPosition<Entry<K,V>> a, b, c, t1, t2, t3, t4;
Position<Entry<K,V>> y = parent(x); // assumes x has a parent
Position<Entry<K,V>> z = parent(y); // assumes y has a parent
boolean xLeft = (x == left(y));
boolean yLeft = (y == left(z));
BTPosition<Entry<K,V>> xx = (BTPosition<Entry<K,V>>)x,
yy = (BTPosition<Entry<K,V>>)y, zz = (BTPosition<Entry<K,V>>)z;
if (xLeft && yLeft) {
a = xx; b = yy; c = zz;
t1 = a.getLeft(); t2 = a.getRight(); t3 = b.getRight(); t4 = c.getRight();
}
else if (!xLeft && yLeft) {
a = yy; b = xx; c = zz;
t1 = a.getLeft(); t2 = b.getLeft(); t3 = b.getRight(); t4 = c.getRight();
}
else if (xLeft && !yLeft) {
a = zz; b = xx; c = yy;
t1 = a.getLeft(); t2 = b.getLeft(); t3 = b.getRight(); t4 = c.getRight();
}
else { // right-right
a = zz; b = yy; c = xx;
t1 = a.getLeft(); t2 = b.getLeft(); t3 = c.getLeft(); t4 = c.getRight();
}
// put b at z's place
if (isRoot(z)) {
root = b;
b.setParent(null);
}
else {
BTPosition<Entry<K,V>> zParent = (BTPosition<Entry<K,V>>)parent(z);
if (z == left(zParent)) {
b.setParent(zParent);
zParent.setLeft(b);
}
else { // z was a right child
b.setParent(zParent);
zParent.setRight(b);
}
}
// place the rest of the nodes and their children
b.setLeft(a);
a.setParent(b);
b.setRight(c);
c.setParent(b);
a.setLeft(t1);
t1.setParent(a);
a.setRight(t2);
t2.setParent(a);
c.setLeft(t3);
t3.setParent(c);
c.setRight(t4);
t4.setParent(c);
// Reset the location-aware entries
((BSTEntry<K,V>) a.element()).pos = a;
((BSTEntry<K,V>) b.element()).pos = b;
((BSTEntry<K,V>) c.element()).pos = c;
return b; // the new root of this subtree
}
//begin#fragment BinarySearchTree3
}
//end#fragment BinarySearchTree3

View File

@@ -0,0 +1,22 @@
package net.datastructures;
//begin#fragment Tree
/**
* An interface for a binary tree, where each node can have zero, one,
* or two children.
//end#fragment Tree
* @author Michael Goodrich
//begin#fragment Tree
*/
public interface BinaryTree<E> extends Tree<E> {
/** Returns the left child of a node. */
public Position<E> left(Position<E> v)
throws InvalidPositionException, BoundaryViolationException;
/** Returns the right child of a node. */
public Position<E> right(Position<E> v)
throws InvalidPositionException, BoundaryViolationException;
/** Returns whether a node has a left child. */
public boolean hasLeft(Position<E> v) throws InvalidPositionException;
/** Returns whether a node has a right child. */
public boolean hasRight(Position<E> v) throws InvalidPositionException;
}
//end#fragment Tree

View File

@@ -0,0 +1,13 @@
package net.datastructures;
/**
* Signals that the boundaries of a data structure have been illegally
* traversed (e.g. past the end of a list).
* @author Roberto Tamassia
*/
public class BoundaryViolationException extends RuntimeException {
public BoundaryViolationException (String message) {
super (message);
}
}

View File

@@ -0,0 +1,25 @@
package net.datastructures;
/**
* An interface for a complete binary tree. A binary tree with height
* <tt>h</tt> is <b>complete</b> if the levels 0,1,2,...,<tt>h</tt> -
* 1 have the maximum number of nodes possible (that is, level
* <tt>i</tt> has 2<sup>i</sup> nodes, for 0 <= <tt>i</tt> <=
* <tt>h</tt> - 1) and in level <tt>h</tt> - 1 all the internal nodes
* are to the left of the external nodes.
*
* @author Michael Goodrich
*/
//begin#fragment HeapTree
public interface CompleteBinaryTree<E> extends BinaryTree<E> {
//end#fragment HeapTree
/** Adds an element to the tree just after the last node. Returns
* the newly created position. */
//begin#fragment HeapTree
public Position<E> add(E elem);
//end#fragment HeapTree
/** Removes and returns the element stored in the last node of the
* tree. */
//begin#fragment HeapTree
public E remove();
}
//end#fragment HeapTree

View File

@@ -0,0 +1,20 @@
package net.datastructures;
import java.util.Iterator;
//begin#fragment CC
/** This class extends DFS to compute the connected components of a graph. */
public class ComponentsDFS<V, E> extends DFS<V, E, Object, Integer> {
protected Integer compNumber; // Connected component number
protected Object COMPONENT = new Object(); // Connected comp. selector
protected void setup() { compNumber = 1; }
protected void startVisit(Vertex<V> v) { v.put(COMPONENT, compNumber);}
protected Integer finalResult(Integer dfsResult) {
for (Vertex<V> v : graph.vertices()) // check for any unvisited vertices
if (v.get(STATUS) == UNVISITED) {
compNumber += 1; // we have found another connected component
dfsTraversal(v); // visit all the vertices of this component
}
return compNumber;
}
}
//end#fragment CC

View File

@@ -0,0 +1,24 @@
package net.datastructures;
import java.util.Iterator;
import java.lang.Boolean;
//begin#fragment ConnectivityTesterDFS
/** This class specializes DFS to determine whether the graph is connected. */
public class ConnectivityDFS<V, E> extends DFS <V, E, Object, Boolean> {
protected int reached;
//end#fragment ConnectivityTesterDFS
/** Executes the DFS algorithm.
* @param graph Input graph
* @param start Start vertex
* @param info unused
* @return {@link Boolean} with value <tt>true</tt> if the graph is
* connected, <tt>false</tt> otherwise
*/
//begin#fragment ConnectivityTesterDFS
protected void setup() { reached = 0; }
protected void startVisit(Vertex<V> v) { reached++; }
protected Boolean finalResult(Boolean dfsResult) {
return new Boolean(reached == graph.numVertices());
}
}
//end#fragment ConnectivityTesterDFS

101
net/datastructures/DFS.java Normal file
View File

@@ -0,0 +1,101 @@
package net.datastructures;
import java.util.Iterator;
//begin#fragment DFS
/** Generic DFS traversal of a graph using the template method pattern.
* Parameterized types:
* V, the type for the elements stored at vertices
* E, the type for the elements stored at edges
* I, the type for the information object passed to the execute method
* R, the type for the result object returned by the DFS
*/
public class DFS<V, E, I, R> {
protected Graph<V, E> graph; // The graph being traversed
protected Vertex<V> start; // The start vertex for the DFS
protected I info; // Information object passed to DFS
protected R visitResult; // The result of a recursive traversal call
protected static Object STATUS = new Object(); // The status attribute
protected static Object VISITED = new Object(); // Visited value
protected static Object UNVISITED = new Object(); // Unvisited value
//end#fragment DFS
//begin#fragment DFS2
/** Execute a depth first search traversal on graph g, starting
* from a start vertex s, passing in an information object (in) */
public R execute(Graph<V, E> g, Vertex<V> s, I in) {
graph = g;
start = s;
info = in;
for(Vertex<V> v: graph.vertices()) unVisit(v); // mark vertices as unvisited
for(Edge<E> e: graph.edges()) unVisit(e); // mark edges as unvisited
setup(); // perform any necessary setup prior to DFS traversal
return finalResult(dfsTraversal(start));
}
/** Recursive template method for a generic DFS traversal. */
protected R dfsTraversal(Vertex<V> v) {
initResult();
if (!isDone())
startVisit(v);
if (!isDone()) {
visit(v);
for (Edge<E> e: graph.incidentEdges(v)) {
if (!isVisited(e)) {
// found an unexplored edge, explore it
visit(e);
Vertex<V> w = graph.opposite(v, e);
if (!isVisited(w)) {
// w is unexplored, this is a discovery edge
traverseDiscovery(e, v);
if (isDone()) break;
visitResult = dfsTraversal(w); // get result from DFS-tree child
if (isDone()) break;
}
else {
// w is explored, this is a back edge
traverseBack(e, v);
if (isDone()) break;
}
}
}
}
if(!isDone())
finishVisit(v);
return result();
}
//end#fragment DFS2
//begin#fragment decorations
/** Mark a position (vertex or edge) as visited. */
protected void visit(DecorablePosition<?> p) { p.put(STATUS, VISITED); }
/** Mark a position (vertex or edge) as unvisited. */
protected void unVisit(DecorablePosition<?> p) { p.put(STATUS, UNVISITED); }
/** Test if a position (vertex or edge) has been visited. */
protected boolean isVisited(DecorablePosition<?> p) {
return (p.get(STATUS) == VISITED);
}
//end#fragment decorations
// Auxiliary methods (all initially null) for specializing a generic DFS
//begin#fragment auxiliary
/** Setup method that is called prior to the DFS execution. */
protected void setup() {}
/** Initializes result (called first, once per vertex visited). */
protected void initResult() {}
/** Called when we encounter a vertex (v). */
protected void startVisit(Vertex<V> v) {}
/** Called after we finish the visit for a vertex (v). */
protected void finishVisit(Vertex<V> v) {}
/** Called when we traverse a discovery edge (e) from a vertex (from). */
protected void traverseDiscovery(Edge<E> e, Vertex<V> from) {}
/** Called when we traverse a back edge (e) from a vertex (from). */
protected void traverseBack(Edge<E> e, Vertex<V> from) {}
/** Determines whether the traversal is done early. */
protected boolean isDone() { return false; /* default value */ }
/** Returns a result of a visit (if needed). */
protected R result() { return null; /* default value */ }
/** Returns the final result of the DFS execute method. */
protected R finalResult(R r) { return r; /* default value */ }
//end#fragment auxiliary
//begin#fragment Tail
} // end of DFS class
//end#fragment Tail

View File

@@ -0,0 +1,32 @@
package net.datastructures;
/**
* A simple node class for a doubly-linked list. Each node has a
* reference to a stored element, a previous node, and a next node.
* This class differs from the <code>DNode</code> class in that it
* does not implement the <code>Position</code> interface, for
* simplification purposes.
*
* @author Roberto Tamassia
* @see DNode
* @see Position
*/
//begin#fragment DLNode
public class DLNode<E> {
private E element;
private DLNode<E> next, prev;
DLNode() { this(null, null, null); }
DLNode(E e, DLNode<E> p, DLNode<E> n) {
element = e;
next = n;
prev = p;
}
public void setElement(E newElem) { element = newElem; }
public void setNext(DLNode<E> newNext) { next = newNext; }
public void setPrev(DLNode<E> newPrev) { prev = newPrev; }
public E getElement() { return element; }
public DLNode<E> getNext() { return next; }
public DLNode<E> getPrev() { return prev; }
}
//end#fragment DLNode

View File

@@ -0,0 +1,32 @@
package net.datastructures;
/**
* A simple node class for a doubly-linked list. Each DNode has a
* reference to a stored element, a previous node, and a next node.
*
* @author Roberto Tamassia
*/
//begin#fragment DNode
public class DNode<E> implements Position<E> {
private DNode<E> prev, next; // References to the nodes before and after
private E element; // Element stored in this position
/** Constructor */
public DNode(DNode<E> newPrev, DNode<E> newNext, E elem) {
prev = newPrev;
next = newNext;
element = elem;
}
// Method from interface Position
public E element() throws InvalidPositionException {
if ((prev == null) && (next == null))
throw new InvalidPositionException("Position is not in a list!");
return element;
}
// Accessor methods
public DNode<E> getNext() { return next; }
public DNode<E> getPrev() { return prev; }
// Update methods
public void setNext(DNode<E> newNext) { next = newNext; }
public void setPrev(DNode<E> newPrev) { prev = newPrev; }
public void setElement(E newElement) { element = newElement; }
}
//end#fragment DNode

View File

@@ -0,0 +1,13 @@
package net.datastructures;
/**
* An interface for a position that can be marked with an arbitrary
* number of decorations.
*
* @author Roberto Tamassia, Michael Goodrich
*/
//begin#fragment Decorable
public interface DecorablePosition<E>
extends Position<E>, Map<Object,Object> {
} // no new methods needed -- this is a mixture of Position and Map.
//end#fragment Decorable

View File

@@ -0,0 +1,22 @@
package net.datastructures;
import java.util.Comparator;
import java.io.Serializable;
/** Comparator based on the natural ordering
*
* @author Michael Goodrich
*/
//begin#fragment DefaultComparator
public class DefaultComparator<E> implements Comparator<E> {
//end#fragment DefaultComparator
/** Compares two given elements
*
* @return a negative integer if <tt>a</tt> is less than <tt>b</tt>,
* zero if <tt>a</tt> equals <tt>b</tt>, or a positive integer if
* <tt>a</tt> is greater than <tt>b</tt>
*/
//begin#fragment DefaultComparator
public int compare(E a, E b) throws ClassCastException {
return ((Comparable<E>) a).compareTo(b);
}
}
//end#fragment DefaultComparator

View File

@@ -0,0 +1,45 @@
package net.datastructures;
//begin#fragment Deque
/**
* Interface for a deque: a collection of objects that are inserted
* and removed at both ends; a subset of java.util.LinkedList methods.
*
* @author Roberto Tamassia
* @author Michael Goodrich
*/
public interface Deque<E> {
/**
* Returns the number of elements in the deque.
*/
public int size();
/**
* Returns whether the deque is empty.
*/
public boolean isEmpty();
/**
* Returns the first element; an exception is thrown if deque is empty.
*/
public E getFirst() throws EmptyDequeException;
/**
* Returns the last element; an exception is thrown if deque is empty.
*/
public E getLast() throws EmptyDequeException;
/**
* Inserts an element to be the first in the deque.
*/
public void addFirst (E element);
/**
* Inserts an element to be the last in the deque.
*/
public void addLast (E element);
/**
* Removes the first element; an exception is thrown if deque is empty.
*/
public E removeFirst() throws EmptyDequeException;
/**
* Removes the last element; an exception is thrown if deque is empty.
*/
public E removeLast() throws EmptyDequeException;
}
//end#fragment Deque

View File

@@ -0,0 +1,46 @@
package net.datastructures;
import java.util.Iterator;
/**
* An interface for a dictionary storing (key-value) pairs.
* @author Michael Goodrich
*/
//begin#fragment Dictionary
public interface Dictionary<K,V> {
//end#fragment Dictionary
/** Returns the number of entries in the dictionary. */
//begin#fragment Dictionary
public int size();
//end#fragment Dictionary
/** Returns whether the dictionary is empty. */
//begin#fragment Dictionary
public boolean isEmpty();
//end#fragment Dictionary
/** Returns an entry containing the given key, or <tt>null</tt> if
* no such entry exists. */
//begin#fragment Dictionary
public Entry<K,V> find(K key)
throws InvalidKeyException;
//end#fragment Dictionary
/** Returns an iterator containing all the entries containing the
* given key, or an empty iterator if no such entries exist. */
//begin#fragment Dictionary
public Iterable<Entry<K,V>> findAll(K key)
throws InvalidKeyException;
//end#fragment Dictionary
/** Inserts an item into the dictionary. Returns the newly created
* entry. */
//begin#fragment Dictionary
public Entry<K,V> insert(K key, V value)
throws InvalidKeyException;
//end#fragment Dictionary
/** Removes and returns the given entry from the dictionary. */
//begin#fragment Dictionary
public Entry<K,V> remove(Entry<K,V> e)
throws InvalidEntryException;
//end#fragment Dictionary
/** Returns an iterator containing all the entries in the dictionary. */
//begin#fragment Dictionary
public Iterable<Entry<K,V>> entries();
}
//end#fragment Dictionary

View File

@@ -0,0 +1,97 @@
package net.datastructures;
import java.util.Iterator;
import java.lang.reflect.Field;
/**
* Dijkstra's algorithm for the single-source shortest path problem in
* an undirected graph whose edges have integer weights.
*
* <p>To execute the algorithm, use the {@link
* #execute(Graph,Vertex,Object) execute} method, and then make
* subsequent calls to the {@link #getDist(Vertex) getDist} method to
* obtain the shortest distance from the start to any given vertex.
*
* @author Roberto Tamassia, Michael Goodrich, Eric Zamore
*/
//begin#fragment execute
/* Dijkstra's algorithm for the single-source shortest path problem
* in an undirected graph whose edges have non-negative integer weights. */
public class Dijkstra<V, E> {
/** Infinity value. */
protected static final Integer INFINITE = Integer.MAX_VALUE;
/** Input graph. */
protected Graph<V, E> graph;
/** Decoration key for edge weights */
protected Object WEIGHT;
/** Decoration key for vertex distances */
protected Object DIST = new Object();
/** Decoration key for entries in the priority queue */
protected Object ENTRY = new Object();
/** Auxiliary priority queue. */
protected AdaptablePriorityQueue<Integer, Vertex<V>> Q;
/** Executes Dijkstra's algorithm.
* @param g Input graph
* @param s Source vertex
* @param w Weight decoration object */
public void execute(Graph<V, E> g, Vertex<V> s, Object w) {
graph = g;
WEIGHT = w;
DefaultComparator dc = new DefaultComparator();
Q = new HeapAdaptablePriorityQueue<Integer, Vertex<V>>(dc);
dijkstraVisit(s);
}
/** Get the distance of a vertex from the source vertex.
//end#fragment execute
* This method returns the length of a shortest path from the source
* to <tt>u</tt> after {@link #execute(Graph,Vertex,Object) execute}
* has been called.
//begin#fragment execute
* @param u Start vertex for the shortest path tree */
public int getDist(Vertex<V> u) {
return (Integer) u.get(DIST);
}
//end#fragment execute
//begin#fragment dijkstraVisit
/** The actual execution of Dijkstra's algorithm.
* @param v source vertex.
*/
protected void dijkstraVisit (Vertex<V> v) {
// store all the vertices in priority queue Q
for (Vertex<V> u: graph.vertices()) {
int u_dist;
if (u==v)
u_dist = 0;
else
u_dist = INFINITE;
Entry<Integer, Vertex<V>> u_entry = Q.insert(u_dist, u); // autoboxing
u.put(ENTRY, u_entry);
}
// grow the cloud, one vertex at a time
while (!Q.isEmpty()) {
// remove from Q and insert into cloud a vertex with minimum distance
Entry<Integer, Vertex<V>> u_entry = Q.min();
Vertex<V> u = u_entry.getValue();
int u_dist = u_entry.getKey();
Q.remove(u_entry); // remove u from the priority queue
u.put(DIST,u_dist); // the distance of u is final
u.remove(ENTRY); // remove the entry decoration of u
if (u_dist == INFINITE)
continue; // unreachable vertices are not processed
// examine all the neighbors of u and update their distances
for (Edge<E> e: graph.incidentEdges(u)) {
Vertex<V> z = graph.opposite(u,e);
Entry<Integer, Vertex<V>> z_entry
= (Entry<Integer, Vertex<V>>) z.get(ENTRY);
if (z_entry != null) { // check that z is in Q, i.e., not in the cloud
int e_weight = (Integer) e.get(WEIGHT);
int z_dist = z_entry.getKey();
if ( u_dist + e_weight < z_dist ) // relaxation of edge e = (u,z)
Q.replaceKey(z_entry, u_dist + e_weight);
}
}
}
}
//end#fragment dijkstraVisit
} // end of Dijkstra class

View File

@@ -0,0 +1,6 @@
package net.datastructures;
/**
* An interface for an edge of a graph.
* @author Roberto Tamassia
*/
public interface Edge<E> extends DecorablePosition<E> { }

View File

@@ -0,0 +1,45 @@
package net.datastructures;
import java.util.Iterator;
import java.util.NoSuchElementException;
import java.lang.UnsupportedOperationException;
/**
* A simple iterator class for lists. The elements of a list are
* returned by this iterator. No copy of the list is made, so any
* changes to the list are reflected in the iterator.
*
* @author Michael Goodrich, Eric Zamore, Roberto Tamassia
*/
//begin#fragment Iterator
public class ElementIterator<E> implements Iterator<E> {
protected PositionList<E> list; // the underlying list
protected Position<E> cursor; // the next position
/** Creates an element iterator over the given list. */
public ElementIterator(PositionList<E> L) {
list = L;
cursor = (list.isEmpty())? null : list.first();
}
//end#fragment Iterator
/** Returns whether the iterator has a next object. */
//begin#fragment Iterator
public boolean hasNext() { return (cursor != null); }
//end#fragment Iterator
/** Returns the next object in the iterator. */
//begin#fragment Iterator
public E next() throws NoSuchElementException {
if (cursor == null)
throw new NoSuchElementException("No next element");
E toReturn = cursor.element();
cursor = (cursor == list.last())? null : list.next(cursor);
return toReturn;
}
//end#fragment Iterator
/** Throws an {@link UnsupportedOperationException} in all cases,
* because removal is not a supported operation in this iterator.
*/
public void remove() throws UnsupportedOperationException {
throw new UnsupportedOperationException("remove");
}
//begin#fragment Iterator
}
//end#fragment Iterator

View File

@@ -0,0 +1,16 @@
package net.datastructures;
/**
* Runtime exception thrown when one tries to perform an access or
* removal operation on an empty deque.
*
* @author Natasha Gelfand
* @author Michael T. Goodrich
* @author Roberto Tamassia
*/
public class EmptyDequeException extends RuntimeException {
public EmptyDequeException(String err) {
super(err);
}
}

View File

@@ -0,0 +1,11 @@
package net.datastructures;
/**
* Thrown when a list cannot fulfill the requested operation because
* it is empty.
* @author Roberto Tamassia
*/
public class EmptyListException extends RuntimeException {
public EmptyListException (String message) {
super (message);
}
}

View File

@@ -0,0 +1,11 @@
package net.datastructures;
/**
* Thrown when a priority queue cannot fulfill the requested operation
* because it is empty.
* @author Roberto Tamassia
*/
public class EmptyPriorityQueueException extends RuntimeException {
public EmptyPriorityQueueException (String message) {
super (message);
}
}

View File

@@ -0,0 +1,15 @@
package net.datastructures;
/**
* Runtime exception thrown when one tries to perform operation front
* or dequeue on an empty queue.
* @author Natasha Gelfand
* @author Michael T. Goodrich
* @author Roberto Tamassia
*/
public class EmptyQueueException extends RuntimeException {
public EmptyQueueException(String err) {
super(err);
}
}

View File

@@ -0,0 +1,16 @@
package net.datastructures;
//begin#fragment EmptyStackException
/**
* Runtime exception thrown when one tries to perform operation top or
* pop on an empty stack.
//end#fragment EmptyStackException
* @author Roberto Tamassia
//begin#fragment EmptyStackException
*/
public class EmptyStackException extends RuntimeException {
public EmptyStackException(String err) {
super(err);
}
}
//end#fragment EmptyStackException

View File

@@ -0,0 +1,11 @@
package net.datastructures;
/**
* Runtime exception thrown when one tries to access the root of an
* empty tree.
*/
public class EmptyTreeException extends RuntimeException {
public EmptyTreeException(String err) {
super(err);
}
}

View File

@@ -0,0 +1,11 @@
package net.datastructures;
//begin#fragment Entry
/** Interface for a key-value pair entry **/
public interface Entry<K,V> {
/** Returns the key stored in this entry. */
public K getKey();
/** Returns the value stored in this entry. */
public V getValue();
}
//end#fragment Entry

View File

@@ -0,0 +1,49 @@
package net.datastructures;
import net.datastructures.Position;
import net.datastructures.BinaryTree;
//begin#fragment EulerTour
/**
* Template for algorithms traversing a binary tree using an Euler
* tour. The subclasses of this class will redefine some of the
* methods of this class to create a specific traversal.
*/
public abstract class EulerTour<E, R> {
protected BinaryTree<E> tree;
/** Execution of the traversal. This abstract method must be
* specified in a concrete subclass. */
public abstract R execute(BinaryTree<E> T);
/** Initialization of the traversal */
protected void init(BinaryTree<E> T) { tree = T; }
/** Template method */
protected R eulerTour(Position<E> v) {
TourResult<R> r = new TourResult<R>();
visitLeft(v, r);
if (tree.hasLeft(v))
r.left = eulerTour(tree.left(v)); // recursive traversal
visitBelow(v, r);
if (tree.hasRight(v))
r.right = eulerTour(tree.right(v)); // recursive traversal
visitRight(v, r);
return r.out;
}
// Auxiliary methods that can be redefined by subclasses:
/** Method called for the visit on the left */
protected void visitLeft(Position<E> v, TourResult<R> r) {}
/** Method called for the visit on from below */
protected void visitBelow(Position<E> v, TourResult<R> r) {}
/** Method called for the visit on the right */
protected void visitRight(Position<E> v, TourResult<R> r) {}
//end#fragment EulerTour
//begin#fragment TourResult
public class TourResult<R> {
public R left;
public R right;
public R out;
}
//end#fragment TourResult
//begin#fragment EulerTour
}
//end#fragment EulerTour

View File

@@ -0,0 +1,54 @@
package net.datastructures;
import java.util.Iterator;
//begin#fragment FindCycleDFS
/** This class specializes DFS to find a cycle. */
//end#fragment FindCycleDFS
/* @author Roberto Tamassia, Michael Goodrich, Eric Zamore
*/
//begin#fragment FindCycleDFS
public class FindCycleDFS<V, E>
extends DFS<V, E, Object, Iterable<Position>> {
protected PositionList<Position> cycle; // sequence of edges of the cycle
protected boolean done;
protected Vertex<V> cycleStart;
//end#fragment FindCycleDFS
/**
* Executes the DFS algorithm.
* @param info unused
* @return {@link Iterable} collection containing the vertices and
* edges of a cycle.
*/
//begin#fragment FindCycleDFS
public void setup() {
cycle = new NodePositionList<Position>();
done = false;
}
protected void startVisit(Vertex<V> v) { cycle.addLast(v); }
protected void finishVisit(Vertex<V> v) {
cycle.remove(cycle.last()); // remove v from cycle
if (!cycle.isEmpty()) cycle.remove(cycle.last()); // remove edge into v from cycle
}
protected void traverseDiscovery(Edge<E> e, Vertex<V> from) {
cycle.addLast(e);
}
protected void traverseBack(Edge<E> e, Vertex<V> from) {
cycle.addLast(e); // back edge e creates a cycle
cycleStart = graph.opposite(from, e);
cycle.addLast(cycleStart); // first vertex completes the cycle
done = true;
}
protected boolean isDone() { return done; }
public Iterable<Position> finalResult(Iterable<Position> r) {
// remove the vertices and edges from start to cycleStart
if (!cycle.isEmpty()) {
for (Position<Position> p: cycle.positions()) {
if (p.element() == cycleStart)
break;
cycle.remove(p); // remove vertex from cycle
}
}
return cycle; // list of the vertices and edges of the cycle
}
}
//end#fragment FindCycleDFS

View File

@@ -0,0 +1,38 @@
package net.datastructures;
//begin#fragment FindPathDFS
/** Class specializing DFS to find a path between a start vertex and a target
* vertex. It assumes the target vertex is passed as the info object to the
* execute method. It returns an iterable list of the vertices and edges
* comprising the path from start to info. The returned path is empty if
* info is unreachable from start. */
public class FindPathDFS<V, E>
extends DFS<V, E, Vertex<V>, Iterable<Position>> {
protected PositionList<Position> path;
protected boolean done;
/** Setup method to initialize the path. */
public void setup() {
path = new NodePositionList<Position>();
done = false;
}
protected void startVisit(Vertex<V> v) {
path.addLast(v); // add vertex v to path
if (v == info)
done = true;
}
protected void finishVisit(Vertex<V> v) {
path.remove(path.last()); // remove v from path
if(!path.isEmpty()) // if v is not the start vertex
path.remove(path.last()); // remove discovery edge into v from path
}
protected void traverseDiscovery(Edge<E> e, Vertex<V> from) {
path.addLast(e); // add edge e to the path
}
protected boolean isDone() {
return done;
}
public Iterable<Position> finalResult(Iterable<Position> r) {
return path;
}
}
//end#fragment FindPathDFS

View File

@@ -0,0 +1,13 @@
package net.datastructures;
//begin#fragment FullStackException
/**
* Runtime exception thrown when the capacity of the array used by an
* ArrayStack has been exceeded.
* @see ArrayStack
*/
public class FullStackException extends RuntimeException {
public FullStackException(String err) {
super(err);
}
}
//end#fragment FullStackException

View File

@@ -0,0 +1,47 @@
package net.datastructures;
import java.util.Iterator;
/**
* An interface for a graph.
* @author Roberto Tamassia
*/
//begin#fragment Graph
public interface Graph<V, E> {
/** Returns the number of vertices of the graph */
public int numVertices();
/** Returns the number of edges of the graph */
public int numEdges();
/** Returns the vertices of the graph as an iterable collection */
public Iterable<Vertex<V>> vertices();
/** Returns the edges of the graph as an iterable collection */
public Iterable<Edge<E>> edges();
/** Replaces the element of a given vertex with a new element and
returns the old element */
public V replace(Vertex<V> p, V o) throws InvalidPositionException;
/** Replaces the element of a given edge with a new element and
returns the old element */
public E replace(Edge<E> p, E o) throws InvalidPositionException;
/** Returns the edges incident on a vertex as an iterable collection */
public Iterable<Edge<E>> incidentEdges(Vertex<V> v)
throws InvalidPositionException;
/** Returns the endvertices of a vertex as an array of length 2 */
public Vertex[] endVertices(Edge<E> e) throws InvalidPositionException;
/** Returns the other endvertex of an incident edge */
public Vertex<V> opposite(Vertex<V> v, Edge<E> e)
throws InvalidPositionException;
/** Tests whether two vertices are adjacent */
public boolean areAdjacent(Vertex<V> u, Vertex<V> v)
throws InvalidPositionException;
/** Inserts and return a new vertex with a given element */
public Vertex<V> insertVertex(V o);
/** Inserts and return a new edge with a given element between two
vertices */
public Edge<E> insertEdge(Vertex<V> u, Vertex<V> v, E o)
throws InvalidPositionException;
/** Removes a vertex and all its incident edges and returns the
element stored at the removed vertex */
public V removeVertex(Vertex<V> v) throws InvalidPositionException;
/** Removes an edge and return its element */
public E removeEdge(Edge<E> e) throws InvalidPositionException;
}
//end#fragment Graph

View File

@@ -0,0 +1,177 @@
package net.datastructures;
import java.util.Iterator;
//begin#fragment Header
/** A hash table with linear probing and the MAD hash function */
//end#fragment Header
/**
* A hash table data structure that uses linear probing to handle
* collisions. The hash function uses the built-in hashCode method
* and the multiply-add-and-divide method. The load factor is alwyas
* kept less than or equal to 0.5. When the load factor reaches 0.5,
* the entries are rehashed into a new bucket array with twice the
* capacity.
*
* @author Roberto Tamassia, Michael Goodrich, Eric Zamore
*/
//begin#fragment Header
public class HashTableMap<K,V> implements Map<K,V> {
//end#fragment Header
/** Nested class for an entry in a hash table. */
//begin#fragment Header
public static class HashEntry<K,V> implements Entry<K,V> {
protected K key;
protected V value;
public HashEntry(K k, V v) { key = k; value = v; }
public V getValue() { return value; }
public K getKey() { return key; }
public V setValue(V val) {
V oldValue = value;
value = val;
return oldValue;
}
public boolean equals(Object o) {
HashEntry<K,V> ent;
try { ent = (HashEntry<K,V>) o; }
catch (ClassCastException ex) { return false; }
return (ent.getKey() == key) && (ent.getValue() == value);
}
//end#fragment Header
/** Entry visualization. */
public String toString() {
return "(" + key + "," + value + ")";
}
//begin#fragment Header
}
protected Entry<K,V> AVAILABLE = new HashEntry<K,V>(null, null);
protected int n = 0; // number of entries in the dictionary
protected int prime, capacity; // prime factor and capacity of bucket array
protected Entry<K,V>[] bucket;// bucket array
protected long scale, shift; // the shift and scaling factors
//end#fragment Header
/** Creates a hash table with prime factor 109345121 and capacity 1000. */
public HashTableMap() { this(109345121,1000); }
//begin#fragment Header
/** Creates a hash table with prime factor 109345121 and given capacity. */
public HashTableMap(int cap) { this(109345121, cap); }
/** Creates a hash table with the given prime factor and capacity. */
public HashTableMap(int p, int cap) {
prime = p;
capacity = cap;
bucket = (Entry<K,V>[]) new Entry[capacity]; // safe cast
java.util.Random rand = new java.util.Random();
scale = rand.nextInt(prime-1) + 1;
shift = rand.nextInt(prime);
}
/** Determines whether a key is valid. */
protected void checkKey(K k) {
if (k == null) throw new InvalidKeyException("Invalid key: null.");
}
/** Hash function applying MAD method to default hash code. */
public int hashValue(K key) {
return (int) ((Math.abs(key.hashCode()*scale + shift) % prime) % capacity);
}
//end#fragment Header
//begin#fragment Linear
/** Returns the number of entries in the hash table. */
public int size() { return n; }
/** Returns whether or not the table is empty. */
public boolean isEmpty() { return (n == 0); }
/** Returns an iterable object containing all of the keys. */
public Iterable<K> keySet() {
PositionList<K> keys = new NodePositionList<K>();
for (int i=0; i<capacity; i++)
if ((bucket[i] != null) && (bucket[i] != AVAILABLE))
keys.addLast(bucket[i].getKey());
return keys;
}
/** Helper search method - returns index of found key or -(a + 1),
* where a is the index of the first empty or available slot found. */
protected int findEntry(K key) throws InvalidKeyException {
int avail = -1;
checkKey(key);
int i = hashValue(key);
int j = i;
do {
Entry<K,V> e = bucket[i];
if ( e == null) {
if (avail < 0)
avail = i; // key is not in table
break;
}
if (key.equals(e.getKey())) // we have found our key
return i; // key found
if (e == AVAILABLE) { // bucket is deactivated
if (avail < 0)
avail = i; // remember that this slot is available
}
i = (i + 1) % capacity; // keep looking
} while (i != j);
return -(avail + 1); // first empty or available slot
}
/** Returns the value associated with a key. */
public V get (K key) throws InvalidKeyException {
int i = findEntry(key); // helper method for finding a key
if (i < 0) return null; // there is no value for this key, so reutrn null
return bucket[i].getValue(); // return the found value in this case
}
//end#fragment Linear
//begin#fragment Linear2
/** Put a key-value pair in the map, replacing previous one if it exists. */
public V put (K key, V value) throws InvalidKeyException {
int i = findEntry(key); //find the appropriate spot for this entry
if (i >= 0) // this key has a previous value
return ((HashEntry<K,V>) bucket[i]).setValue(value); // set new value
if (n >= capacity/2) {
rehash(); // rehash to keep the load factor <= 0.5
i = findEntry(key); //find again the appropriate spot for this entry
}
bucket[-i-1] = new HashEntry<K,V>(key, value); // convert to proper index
n++;
return null; // there was no previous value
}
/** Doubles the size of the hash table and rehashes all the entries. */
protected void rehash() {
capacity = 2*capacity;
Entry<K,V>[] old = bucket;
bucket = (Entry<K,V>[]) new Entry[capacity]; // new bucket is twice as big
java.util.Random rand = new java.util.Random();
scale = rand.nextInt(prime-1) + 1; // new hash scaling factor
shift = rand.nextInt(prime); // new hash shifting factor
for (int i=0; i<old.length; i++) {
Entry<K,V> e = old[i];
if ((e != null) && (e != AVAILABLE)) { // a valid entry
int j = - 1 - findEntry(e.getKey());
bucket[j] = e;
}
}
}
/** Removes the key-value pair with a specified key. */
public V remove (K key) throws InvalidKeyException {
int i = findEntry(key); // find this key first
if (i < 0) return null; // nothing to remove
V toReturn = bucket[i].getValue();
bucket[i] = AVAILABLE; // mark this slot as deactivated
n--;
return toReturn;
}
//end#fragment Linear2
/** Returns an iterable object containing all of the entries. */
public Iterable<Entry<K,V>> entrySet() {
PositionList<Entry<K,V>> entries = new NodePositionList<Entry<K,V>>();
for (int i=0; i<capacity; i++)
if ((bucket[i] != null) && (bucket[i] != AVAILABLE))
entries.addLast(bucket[i]);
return entries;
}
/** Returns an iterable object containing all of the values. */
public Iterable<V> values() {
PositionList<V> values = new NodePositionList<V>();
for (int i=0; i<capacity; i++)
if ((bucket[i] != null) && (bucket[i] != AVAILABLE))
values.addLast(bucket[i].getValue());
return values;
}
//begin#fragment Linear2
}
//end#fragment Linear2

View File

@@ -0,0 +1,128 @@
package net.datastructures;
import java.util.Comparator;
//begin#fragment HeapPriorityQueue
/**
* Realization of a priority queue by means of a heap. A complete
* binary tree realized by means of an array list is used to
* represent the heap.
//end#fragment HeapPriorityQueue
*
* @author Roberto Tamassia, Michael Goodrich, Eric Zamore
//begin#fragment HeapPriorityQueue
*/
public class HeapPriorityQueue<K,V> implements PriorityQueue<K,V> {
protected CompleteBinaryTree<Entry<K,V>> heap; // underlying heap
protected Comparator<K> comp; // comparator for the keys
/** Inner class for heap entries. */
protected static class MyEntry<K,V> implements Entry<K,V> {
protected K key;
protected V value;
public MyEntry(K k, V v) { key = k; value = v; }
public K getKey() { return key; }
public V getValue() { return value; }
public String toString() { return "(" + key + "," + value + ")"; }
}
/** Creates an empty heap with the default comparator */
public HeapPriorityQueue() {
heap = new ArrayListCompleteBinaryTree<Entry<K,V>>(); // use an array list
comp = new DefaultComparator<K>(); // use the default comparator
}
/** Creates an empty heap with the given comparator */
public HeapPriorityQueue(Comparator<K> c) {
heap = new ArrayListCompleteBinaryTree<Entry<K,V>>();
comp = c;
}
//end#fragment HeapPriorityQueue
/** Sets the comparator used for comparing items in the heap.
* @throws IllegalStateException if priority queue is not empty */
public void setComparator(Comparator<K> c) throws IllegalStateException {
if(!isEmpty()) // this is only allowed if the priority queue is empty
throw new IllegalStateException("Priority queue is not empty");
comp = c;
}
//begin#fragment HeapPriorityQueue
/** Returns the size of the heap */
public int size() { return heap.size(); }
/** Returns whether the heap is empty */
public boolean isEmpty() { return heap.size() == 0; }
//end#fragment HeapPriorityQueue
//begin#fragment mainMethods
/** Returns but does not remove an entry with minimum key */
public Entry<K,V> min() throws EmptyPriorityQueueException {
if (isEmpty())
throw new EmptyPriorityQueueException("Priority queue is empty");
return heap.root().element();
}
/** Inserts a key-value pair and returns the entry created */
public Entry<K,V> insert(K k, V x) throws InvalidKeyException {
checkKey(k); // may throw an InvalidKeyException
Entry<K,V> entry = new MyEntry<K,V>(k,x);
upHeap(heap.add(entry));
return entry;
}
/** Removes and returns an entry with minimum key */
public Entry<K,V> removeMin() throws EmptyPriorityQueueException {
if (isEmpty())
throw new EmptyPriorityQueueException("Priority queue is empty");
Entry<K,V> min = heap.root().element();
if (size() == 1)
heap.remove();
else {
heap.replace(heap.root(), heap.remove());
downHeap(heap.root());
}
return min;
}
/** Determines whether a given key is valid */
protected void checkKey(K key) throws InvalidKeyException {
try {
comp.compare(key,key);
}
catch(Exception e) {
throw new InvalidKeyException("Invalid key");
}
}
//end#fragment mainMethods
//begin#fragment auxiliary
/** Performs up-heap bubbling */
protected void upHeap(Position<Entry<K,V>> v) {
Position<Entry<K,V>> u;
while (!heap.isRoot(v)) {
u = heap.parent(v);
if (comp.compare(u.element().getKey(), v.element().getKey()) <= 0) break;
swap(u, v);
v = u;
}
}
/** Performs down-heap bubbling */
protected void downHeap(Position<Entry<K,V>> r) {
while (heap.isInternal(r)) {
Position<Entry<K,V>> s; // the position of the smaller child
if (!heap.hasRight(r))
s = heap.left(r);
else if (comp.compare(heap.left(r).element().getKey(),
heap.right(r).element().getKey()) <=0)
s = heap.left(r);
else
s = heap.right(r);
if (comp.compare(s.element().getKey(), r.element().getKey()) < 0) {
swap(r, s);
r = s;
}
else
break;
}
}
/** Swaps the entries of the two given positions */
protected void swap(Position<Entry<K,V>> x, Position<Entry<K,V>> y) {
Entry<K,V> temp = x.element();
heap.replace(x, y.element());
heap.replace(y, temp);
}
/** Text visualization for debugging purposes */
public String toString() {
return heap.toString();
}
//end#fragment auxiliary
}

View File

@@ -0,0 +1,33 @@
package net.datastructures;
import java.util.Iterator;
/**
* An interface for array lists.
* @author Roberto Tamassia, Michael Goodrich
*/
//begin#fragment Header
public interface IndexList<E> {
//end#fragment Header
//begin#fragment Iterator
// ... the other List methods ...
//end#fragment Iterator
//begin#fragment List
/** Returns the number of elements in this list. */
public int size();
/** Returns whether the list is empty. */
public boolean isEmpty();
/** Inserts an element e to be at index i, shifting all elements after this. */
public void add(int i, E e)
throws IndexOutOfBoundsException;
/** Returns the element at index i, without removing it. */
public E get(int i)
throws IndexOutOfBoundsException;
/** Removes and returns the element at index i, shifting the elements after this. */
public E remove(int i)
throws IndexOutOfBoundsException;
/** Replaces the element at index i with e, returning the previous element at i. */
public E set(int i, E e)
throws IndexOutOfBoundsException;
//end#fragment List
//begin#fragment Tail
}
//end#fragment Tail

View File

@@ -0,0 +1,10 @@
package net.datastructures;
/**
* Thrown when an entry is discovered to be invalid.
* @author Eric Zamore
*/
public class InvalidEntryException extends RuntimeException {
public InvalidEntryException (String message) {
super (message);
}
}

View File

@@ -0,0 +1,11 @@
package net.datastructures;
/**
* Thrown when a key is determined to be invalid.
* @author Roberto Tamassia
*/
public class InvalidKeyException extends RuntimeException {
public InvalidKeyException (String message) {
super (message);
}
public static final long serialVersionUID = 424242L;
}

View File

@@ -0,0 +1,18 @@
package net.datastructures;
/**
* Thrown when a position is determined to be invalid.
* @author Roberto Tamassia, Michael Goodrich
*/
//begin#fragment InvalidPositionException
// A run-time exception for invalid positions
public class InvalidPositionException extends RuntimeException {
public InvalidPositionException(String err) {
super(err);
}
//end#fragment InvalidPositionException
public InvalidPositionException() {
/* default constructor */
}
//begin#fragment InvalidPositionException
}
//end#fragment InvalidPositionException

View File

@@ -0,0 +1,314 @@
package net.datastructures;
import java.util.Iterator;
//begin#fragment LinkedBinaryTree
/**
* An implementation of the BinaryTree interface by means of a linked structure.
//end#fragment LinkedBinaryTree
* This class serves as a superclass for the BinarySearchTree
* implementation. This design decision was made to emphasize the
* conceptual relationship that a BinarySearchTree is a specialized
* LinkedBinaryTree. An unwanted side-effect of this is that the
* {@link #size() size} method returns the number of total nodes
* whereas the {@link BinarySearchTree#size() size} method in the
* {@link BinarySearchTree BinarySearchTree} class returns the number
* of internal nodes only. For this reason, the the {@link #size
* size} variable instead of the {@link #size() size} method is used
* within this class.
*
* @author Luca Vismara, Roberto Tamassia, Michael Goodrich, Eric
* Zamore
* @see BinaryTree
//begin#fragment LinkedBinaryTree
*/
public class LinkedBinaryTree<E> implements BinaryTree<E> {
protected BTPosition<E> root; // reference to the root
protected int size; // number of nodes
/** Creates an empty binary tree. */
public LinkedBinaryTree() {
root = null; // start with an empty tree
size = 0;
}
/** Returns the number of nodes in the tree. */
public int size() {
return size;
}
//end#fragment LinkedBinaryTree
/** Returns whether the tree is empty. */
public boolean isEmpty() {
return (size == 0);
}
//begin#fragment LinkedBinaryTree
/** Returns whether a node is internal. */
public boolean isInternal(Position<E> v) throws InvalidPositionException {
checkPosition(v); // auxiliary method
return (hasLeft(v) || hasRight(v));
}
//end#fragment LinkedBinaryTree
/** Returns whether a node is external. */
public boolean isExternal(Position<E> v) throws InvalidPositionException {
return !isInternal(v);
}
//begin#fragment LinkedBinaryTree
/** Returns whether a node is the root. */
public boolean isRoot(Position<E> v) throws InvalidPositionException {
checkPosition(v);
return (v == root());
}
/** Returns whether a node has a left child. */
public boolean hasLeft(Position<E> v) throws InvalidPositionException {
BTPosition<E> vv = checkPosition(v);
return (vv.getLeft() != null);
}
//end#fragment LinkedBinaryTree
/** Returns whether a node has a right child. */
public boolean hasRight(Position<E> v) throws InvalidPositionException {
BTPosition<E> vv = checkPosition(v);
return (vv.getRight() != null);
}
//begin#fragment LinkedBinaryTree
/** Returns the root of the tree. */
public Position<E> root() throws EmptyTreeException {
if (root == null)
throw new EmptyTreeException("The tree is empty");
return root;
}
/** Returns the left child of a node. */
public Position<E> left(Position<E> v)
throws InvalidPositionException, BoundaryViolationException {
BTPosition<E> vv = checkPosition(v);
Position<E> leftPos = vv.getLeft();
if (leftPos == null)
throw new BoundaryViolationException("No left child");
return leftPos;
}
//end#fragment LinkedBinaryTree
/** Returns the right child of a node. */
public Position<E> right(Position<E> v)
throws InvalidPositionException, BoundaryViolationException {
BTPosition<E> vv = checkPosition(v);
Position<E> rightPos = vv.getRight();
if (rightPos == null)
throw new BoundaryViolationException("No right child");
return rightPos;
}
//begin#fragment LinkedBinaryTree2
/** Returns the parent of a node. */
public Position<E> parent(Position<E> v)
throws InvalidPositionException, BoundaryViolationException {
BTPosition<E> vv = checkPosition(v);
Position<E> parentPos = vv.getParent();
if (parentPos == null)
throw new BoundaryViolationException("No parent");
return parentPos;
}
/** Returns an iterable collection of the children of a node. */
public Iterable<Position<E>> children(Position<E> v)
throws InvalidPositionException {
PositionList<Position<E>> children = new NodePositionList<Position<E>>();
if (hasLeft(v))
children.addLast(left(v));
if (hasRight(v))
children.addLast(right(v));
return children;
}
/** Returns an iterable collection of the tree nodes. */
public Iterable<Position<E>> positions() {
PositionList<Position<E>> positions = new NodePositionList<Position<E>>();
if(size != 0)
preorderPositions(root(), positions); // assign positions in preorder
return positions;
}
/** Returns an iterator of the elements stored at the nodes */
public Iterator<E> iterator() {
Iterable<Position<E>> positions = positions();
PositionList<E> elements = new NodePositionList<E>();
for (Position<E> pos: positions)
elements.addLast(pos.element());
return elements.iterator(); // An iterator of elements
}
/** Replaces the element at a node. */
public E replace(Position<E> v, E o)
throws InvalidPositionException {
BTPosition<E> vv = checkPosition(v);
E temp = v.element();
vv.setElement(o);
return temp;
}
//end#fragment LinkedBinaryTree2
//begin#fragment LinkedBinaryTree3
// Additional accessor method
/** Return the sibling of a node */
public Position<E> sibling(Position<E> v)
throws InvalidPositionException, BoundaryViolationException {
BTPosition<E> vv = checkPosition(v);
BTPosition<E> parentPos = vv.getParent();
if (parentPos != null) {
BTPosition<E> sibPos;
BTPosition<E> leftPos = parentPos.getLeft();
if (leftPos == vv)
sibPos = parentPos.getRight();
else
sibPos = parentPos.getLeft();
if (sibPos != null)
return sibPos;
}
throw new BoundaryViolationException("No sibling");
}
// Additional update methods
/** Adds a root node to an empty tree */
public Position<E> addRoot(E e) throws NonEmptyTreeException {
if(!isEmpty())
throw new NonEmptyTreeException("Tree already has a root");
size = 1;
root = createNode(e,null,null,null);
return root;
}
/** Inserts a left child at a given node. */
public Position<E> insertLeft(Position<E> v, E e)
throws InvalidPositionException {
BTPosition<E> vv = checkPosition(v);
Position<E> leftPos = vv.getLeft();
if (leftPos != null)
throw new InvalidPositionException("Node already has a left child");
BTPosition<E> ww = createNode(e, vv, null, null);
vv.setLeft(ww);
size++;
return ww;
}
//end#fragment LinkedBinaryTree3
/** Inserts a right child at a given node. */
public Position<E> insertRight(Position<E> v, E e)
throws InvalidPositionException {
BTPosition<E> vv = checkPosition(v);
Position<E> rightPos = vv.getRight();
if (rightPos != null)
throw new InvalidPositionException("Node already has a right child");
BTPosition<E> w = createNode(e, vv, null, null);
vv.setRight(w);
size++;
return w;
}
//begin#fragment LinkedBinaryTree4
/** Removes a node with zero or one child. */
public E remove(Position<E> v)
throws InvalidPositionException {
BTPosition<E> vv = checkPosition(v);
BTPosition<E> leftPos = vv.getLeft();
BTPosition<E> rightPos = vv.getRight();
if (leftPos != null && rightPos != null)
throw new InvalidPositionException("Cannot remove node with two children");
BTPosition<E> ww; // the only child of v, if any
if (leftPos != null)
ww = leftPos;
else if (rightPos != null)
ww = rightPos;
else // v is a leaf
ww = null;
if (vv == root) { // v is the root
if (ww != null)
ww.setParent(null);
root = ww;
}
else { // v is not the root
BTPosition<E> uu = vv.getParent();
if (vv == uu.getLeft())
uu.setLeft(ww);
else
uu.setRight(ww);
if(ww != null)
ww.setParent(uu);
}
size--;
return v.element();
}
//end#fragment LinkedBinaryTree4
//begin#fragment LinkedBinaryTree5
/** Attaches two trees to be subtrees of an external node. */
public void attach(Position<E> v, BinaryTree<E> T1, BinaryTree<E> T2)
throws InvalidPositionException {
BTPosition<E> vv = checkPosition(v);
if (isInternal(v))
throw new InvalidPositionException("Cannot attach from internal node");
int newSize = size + T1.size() + T2.size();
if (!T1.isEmpty()) {
BTPosition<E> r1 = checkPosition(T1.root());
vv.setLeft(r1);
r1.setParent(vv); // T1 should be invalidated
}
if (!T2.isEmpty()) {
BTPosition<E> r2 = checkPosition(T2.root());
vv.setRight(r2);
r2.setParent(vv); // T2 should be invalidated
}
size = newSize;
}
//end#fragment LinkedBinaryTree5
/** Swap the elements at two nodes */
public void swapElements(Position<E> v, Position<E> w)
throws InvalidPositionException {
BTPosition<E> vv = checkPosition(v);
BTPosition<E> ww = checkPosition(w);
E temp = w.element();
ww.setElement(v.element());
vv.setElement(temp);
}
/** Expand an external node into an internal node with two external
node children */
public void expandExternal(Position<E> v, E l, E r)
throws InvalidPositionException {
if (!isExternal(v))
throw new InvalidPositionException("Node is not external");
insertLeft(v, l);
insertRight(v, r);
}
/** Remove an external node v and replace its parent with v's
sibling */
public void removeAboveExternal(Position<E> v)
throws InvalidPositionException {
if (!isExternal(v))
throw new InvalidPositionException("Node is not external");
if (isRoot(v))
remove(v);
else {
Position<E> u = parent(v);
remove(v);
remove(u);
}
}
// Auxiliary methods
//begin#fragment LinkedBinaryTree5
/** If v is a good binary tree node, cast to BTPosition, else throw exception */
protected BTPosition<E> checkPosition(Position<E> v)
throws InvalidPositionException {
if (v == null || !(v instanceof BTPosition))
throw new InvalidPositionException("The position is invalid");
return (BTPosition<E>) v;
}
/** Creates a new binary tree node */
protected BTPosition<E> createNode(E element, BTPosition<E> parent,
BTPosition<E> left, BTPosition<E> right) {
return new BTNode<E>(element,parent,left,right); }
/** Creates a list storing the the nodes in the subtree of a node,
* ordered according to the preorder traversal of the subtree. */
protected void preorderPositions(Position<E> v, PositionList<Position<E>> pos)
throws InvalidPositionException {
pos.addLast(v);
if (hasLeft(v))
preorderPositions(left(v), pos); // recurse on left child
if (hasRight(v))
preorderPositions(right(v), pos); // recurse on right child
}
//end#fragment LinkedBinaryTree5
/** Creates a list storing the the nodes in the subtree of a node,
* ordered according to the inorder traversal of the subtree. */
protected void inorderPositions(Position<E> v, PositionList<Position<E>> pos)
throws InvalidPositionException {
if (hasLeft(v))
inorderPositions(left(v), pos); // recurse on left child
pos.addLast(v);
if (hasRight(v))
inorderPositions(right(v), pos); // recurse on right child
}
}

View File

@@ -0,0 +1,138 @@
package net.datastructures;
import java.util.Iterator;
import net.datastructures.*;
//begin#fragment Tree
/**
* A linked class for a tree where nodes have an arbitrary number of children.
//end#fragment Tree
* @author Luca Vismara, Roberto Tamassia, Michael Goodrich, Eric Zamore
//begin#fragment Tree
*/
public class LinkedTree<E> implements Tree<E> {
protected TreePosition<E> root; // reference to the root
protected int size; // number of nodes
/** Creates an empty tree. */
public LinkedTree() {
root = null; // start with an empty tree
size = 0;
}
/** Returns the number of nodes in the tree. */
public int size() {
return size;
}
//end#fragment LinkedTree
/** Returns whether the tree is empty. */
public boolean isEmpty() {
return (size == 0);
}
//begin#fragment LinkedTree
/** Returns whether a node is internal. */
public boolean isInternal(Position<E> v) throws InvalidPositionException {
return !isExternal(v);
}
//end#fragment LinkedTree
/** Returns whether a node is external. */
public boolean isExternal(Position<E> v) throws InvalidPositionException {
TreePosition<E> vv = checkPosition(v); // auxiliary method
return (vv.getChildren() == null) || vv.getChildren().isEmpty();
}
//begin#fragment LinkedTree
/** Returns whether a node is the root. */
public boolean isRoot(Position<E> v) throws InvalidPositionException {
checkPosition(v);
return (v == root());
}
//begin#fragment LinkedTree
/** Returns the root of the tree. */
public Position<E> root() throws EmptyTreeException {
if (root == null)
throw new EmptyTreeException("The tree is empty");
return root;
}
//end#fragment LinkedTree
//begin#fragment LinkedTree2
/** Returns the parent of a node. */
public Position<E> parent(Position<E> v)
throws InvalidPositionException, BoundaryViolationException {
TreePosition<E> vv = checkPosition(v);
Position<E> parentPos = vv.getParent();
if (parentPos == null)
throw new BoundaryViolationException("No parent");
return parentPos;
}
/** Returns an iterable collection of the children of a node. */
public Iterable<Position<E>> children(Position<E> v)
throws InvalidPositionException {
TreePosition<E> vv = checkPosition(v);
if (isExternal(v))
throw new InvalidPositionException("External nodes have no children");
return vv.getChildren();
}
/** Returns an iterable collection of the tree nodes. */
public Iterable<Position<E>> positions() {
PositionList<Position<E>> positions = new NodePositionList<Position<E>>();
if(size != 0)
preorderPositions(root(), positions); // assign positions in preorder
return positions;
}
/** Returns an iterator of the elements stored at the nodes */
public Iterator<E> iterator() {
Iterable<Position<E>> positions = positions();
PositionList<E> elements = new NodePositionList<E>();
for (Position<E> pos: positions)
elements.addLast(pos.element());
return elements.iterator(); // An iterator of elements
}
/** Replaces the element at a node. */
public E replace(Position<E> v, E o)
throws InvalidPositionException {
TreePosition<E> vv = checkPosition(v);
E temp = v.element();
vv.setElement(o);
return temp;
}
//end#fragment LinkedTree2
//begin#fragment LinkedTree3
// Additional update methods
/** Adds a root node to an empty tree */
public Position<E> addRoot(E e) throws NonEmptyTreeException {
if(!isEmpty())
throw new NonEmptyTreeException("Tree already has a root");
size = 1;
root = createNode(e,null,null);
return root;
}
/** Swap the elements at two nodes */
public void swapElements(Position<E> v, Position<E> w)
throws InvalidPositionException {
TreePosition<E> vv = checkPosition(v);
TreePosition<E> ww = checkPosition(w);
E temp = w.element();
ww.setElement(v.element());
vv.setElement(temp);
}
// Auxiliary methods
//begin#fragment LinkedTree5
/** If v is a good tree node, cast to TreePosition, else throw exception */
protected TreePosition<E> checkPosition(Position<E> v)
throws InvalidPositionException {
if (v == null || !(v instanceof TreePosition))
throw new InvalidPositionException("The position is invalid");
return (TreePosition<E>) v;
}
/** Creates a new tree node */
protected TreePosition<E> createNode(E element, TreePosition<E> parent,
PositionList<Position<E>> children) {
return new TreeNode<E>(element,parent,children);
}
/** Creates a list storing the the nodes in the subtree of a node,
* ordered according to the preorder traversal of the subtree. */
protected void preorderPositions(Position<E> v, PositionList<Position<E>> pos)
throws InvalidPositionException {
pos.addLast(v);
for (Position<E> w : children(v))
preorderPositions(w, pos); // recurse on each child
}
}
//end#fragment LinkedTree5

View File

@@ -0,0 +1,36 @@
package net.datastructures;
/**
* An interface for a map which binds a key uniquely to a value.
* @author Michael Goodrich
*/
//begin#fragment Map
// A simple Map interface
public interface Map<K,V> {
/** Returns the number of items in the map. */
public int size();
/** Returns whether the map is empty. */
public boolean isEmpty();
/**
* If there is an entry with the specified key, replaces the value of
* this entry with the specified value and returns the old value. Else,
* adds a new entry with the specified key and value and returns null.
*/
public V put(K key, V value) throws InvalidKeyException;
/**
* Returns the value of the entry containing the given key. Returns
* null if no such entry exists.
*/
public V get(K key) throws InvalidKeyException;
/**
* If there is an entry with the specified key, removes this entry and
* returns its value. Else, returns null.
*/
public V remove(K key) throws InvalidKeyException;
/** Returns an iterable object containing all the keys in the map. */
public Iterable<K> keySet();
/** Returns an iterable object containing all the values in the map. */
public Iterable<V> values();
/** Returns an iterable object containing all the entries in the map. */
public Iterable<Entry<K,V>> entrySet();
}
//end#fragment Map

View File

@@ -0,0 +1,39 @@
package net.datastructures;
/**
* Node of a singly linked list, which stores references to its
* element and to the next node in the list.
*
* @author Natasha Gelfand
* @author Roberto Tamassia
* @author Michael Goodrich
*/
//begin#fragment Node
public class Node<E> {
// Instance variables:
private E element;
private Node<E> next;
/** Creates a node with null references to its element and next node. */
public Node() {
this(null, null);
}
/** Creates a node with the given element and next node. */
public Node(E e, Node<E> n) {
element = e;
next = n;
}
// Accessor methods:
public E getElement() {
return element;
}
public Node<E> getNext() {
return next;
}
// Modifier methods:
public void setElement(E newElem) {
element = newElem;
}
public void setNext(Node<E> newNext) {
next = newNext;
}
}
//end#fragment Node

View File

@@ -0,0 +1,113 @@
package net.datastructures;
/**
* Implementation of the Deque interface by means of a doubly linked
* list. This class uses class DLNode, which implements a node of
* the list.
*
* @author Natasha Gelfand
* @author Roberto Tamassia
*/
//begin#fragment NodeDeque
public class NodeDeque<E> implements Deque<E> {
protected DLNode<E> header, trailer; // sentinels
protected int size; // number of elements
//end#fragment NodeDeque
/** Creates an empty deque. */
//begin#fragment NodeDeque
public NodeDeque() { // initialize an empty deque
header = new DLNode<E>();
trailer = new DLNode<E>();
header.setNext(trailer); // make header point to trailer
trailer.setPrev(header); // make trailer point to header
size = 0;
}
//end#fragment NodeDeque
/**
* Return the size of the deque, that is the number of elements it has.
* @return Number of elements in the deque
*/
//begin#fragment size
public int size() {
return size;
}
//end#fragment size
/**
* This function returns true if and only if the deque is empty
* @return true if the deque is empty, false otherwise
*/
//begin#fragment isEmpty
public boolean isEmpty() {
if (size == 0)
return true;
return false;
}
//end#fragment isEmpty
/**
* Inspect the first element without modifying the deque.
* @return The first element in the sequence
*/
//begin#fragment first
public E getFirst() throws EmptyDequeException {
if (isEmpty())
throw new EmptyDequeException("Deque is empty.");
return header.getNext().getElement();
}
//end#fragment first
public E getLast() throws EmptyDequeException {
if (isEmpty())
throw new EmptyDequeException("Deque is empty.");
return trailer.getPrev().getElement();
}
//begin#fragment addFirst
public void addFirst(E o) {
DLNode<E> second = header.getNext();
DLNode<E> first = new DLNode<E>(o, header, second);
second.setPrev(first);
header.setNext(first);
size++;
}
//end#fragment addFirst
public void addLast(E o) {
DLNode<E> secondtolast = trailer.getPrev();
DLNode<E> last = new DLNode<E>(o, secondtolast, trailer);
secondtolast.setNext(last);
trailer.setPrev(last);
size++;
}
public E removeFirst() throws EmptyDequeException {
if (isEmpty())
throw new EmptyDequeException("Deque is empty.");
DLNode<E> first = header.getNext();
E o = first.getElement();
DLNode<E> second = first.getNext();
header.setNext(second);
second.setPrev(header);
size--;
return o;
}
//begin#fragment removeLast
public E removeLast() throws EmptyDequeException {
if (isEmpty())
throw new EmptyDequeException("Deque is empty.");
DLNode<E> last = trailer.getPrev();
E o = last.getElement();
DLNode<E> secondtolast = last.getPrev();
trailer.setPrev(secondtolast);
secondtolast.setNext(trailer);
size--;
return o;
}
//end#fragment removeLast
//begin#fragment tail
}
//end#fragment tail

View File

@@ -0,0 +1,232 @@
package net.datastructures;
import java.util.Iterator;
/**
* Realization of a PositionList using a doubly-linked list of nodes.
*
* @author Michael Goodrich, Natasha Gelfand, Roberto Tamassia, Eric Zamore
*/
//begin#fragment Header
public class NodePositionList<E> implements PositionList<E> {
//end#fragment Header
//begin#fragment Listvars
protected int numElts; // Number of elements in the list
protected DNode<E> header, trailer; // Special sentinels
//end#fragment Listvars
//begin#fragment checkPosition
/** Constructor that creates an empty list; O(1) time */
public NodePositionList() {
numElts = 0;
header = new DNode<E>(null, null, null); // create header
trailer = new DNode<E>(header, null, null); // create trailer
header.setNext(trailer); // make header and trailer point to each other
}
/** Checks if position is valid for this list and converts it to
* DNode if it is valid; O(1) time */
protected DNode<E> checkPosition(Position<E> p)
throws InvalidPositionException {
if (p == null)
throw new InvalidPositionException
("Null position passed to NodeList");
if (p == header)
throw new InvalidPositionException
("The header node is not a valid position");
if (p == trailer)
throw new InvalidPositionException
("The trailer node is not a valid position");
try {
DNode<E> temp = (DNode<E>) p;
if ((temp.getPrev() == null) || (temp.getNext() == null))
throw new InvalidPositionException
("Position does not belong to a valid NodeList");
return temp;
} catch (ClassCastException e) {
throw new InvalidPositionException
("Position is of wrong type for this list");
}
}
//end#fragment checkPosition
//begin#fragment first
/** Returns the number of elements in the list; O(1) time */
public int size() { return numElts; }
/** Returns whether the list is empty; O(1) time */
public boolean isEmpty() { return (numElts == 0); }
/** Returns the first position in the list; O(1) time */
public Position<E> first()
throws EmptyListException {
if (isEmpty())
throw new EmptyListException("List is empty");
return header.getNext();
}
//end#fragment first
/** Returns the last position in the list; O(1) time */
public Position<E> last()
throws EmptyListException {
if (isEmpty())
throw new EmptyListException("List is empty");
return trailer.getPrev();
}
//begin#fragment first
/** Returns the position before the given one; O(1) time */
public Position<E> prev(Position<E> p)
throws InvalidPositionException, BoundaryViolationException {
DNode<E> v = checkPosition(p);
DNode<E> prev = v.getPrev();
if (prev == header)
throw new BoundaryViolationException
("Cannot advance past the beginning of the list");
return prev;
}
//end#fragment first
/** Returns the position after the given one; O(1) time */
public Position<E> next(Position<E> p)
throws InvalidPositionException, BoundaryViolationException {
DNode<E> v = checkPosition(p);
DNode<E> next = v.getNext();
if (next == trailer)
throw new BoundaryViolationException
("Cannot advance past the end of the list");
return next;
}
//begin#fragment first
/** Insert the given element before the given position;
* O(1) time */
public void addBefore(Position<E> p, E element)
throws InvalidPositionException {
DNode<E> v = checkPosition(p);
numElts++;
DNode<E> newNode = new DNode<E>(v.getPrev(), v, element);
v.getPrev().setNext(newNode);
v.setPrev(newNode);
}
//end#fragment first
/** Insert the given element after the given position;
* O(1) time */
public void addAfter(Position<E> p, E element)
throws InvalidPositionException {
DNode<E> v = checkPosition(p);
numElts++;
DNode<E> newNode = new DNode<E>(v, v.getNext(), element);
v.getNext().setPrev(newNode);
v.setNext(newNode);
}
//begin#fragment remove
/** Insert the given element at the beginning of the list, returning
* the new position; O(1) time */
public void addFirst(E element) {
numElts++;
DNode<E> newNode = new DNode<E>(header, header.getNext(), element);
header.getNext().setPrev(newNode);
header.setNext(newNode);
}
//end#fragment remove
/** Insert the given element at the end of the list, returning
* the new position; O(1) time */
public void addLast(E element) {
numElts++;
DNode<E> oldLast = trailer.getPrev();
DNode<E> newNode = new DNode<E>(oldLast, trailer, element);
oldLast.setNext(newNode);
trailer.setPrev(newNode);
}
//begin#fragment remove
/**Remove the given position from the list; O(1) time */
public E remove(Position<E> p)
throws InvalidPositionException {
DNode<E> v = checkPosition(p);
numElts--;
DNode<E> vPrev = v.getPrev();
DNode<E> vNext = v.getNext();
vPrev.setNext(vNext);
vNext.setPrev(vPrev);
E vElem = v.element();
// unlink the position from the list and make it invalid
v.setNext(null);
v.setPrev(null);
return vElem;
}
/** Replace the element at the given position with the new element
* and return the old element; O(1) time */
public E set(Position<E> p, E element)
throws InvalidPositionException {
DNode<E> v = checkPosition(p);
E oldElt = v.element();
v.setElement(element);
return oldElt;
}
//end#fragment remove
//begin#fragment Iterator
/** Returns an iterator of all the elements in the list. */
public Iterator<E> iterator() { return new ElementIterator<E>(this); }
//end#fragment Iterator
//begin#fragment PIterator
/** Returns an iterable collection of all the nodes in the list. */
public Iterable<Position<E>> positions() { // create a list of posiitons
PositionList<Position<E>> P = new NodePositionList<Position<E>>();
if (!isEmpty()) {
Position<E> p = first();
while (true) {
P.addLast(p); // add position p as the last element of list P
if (p == last())
break;
p = next(p);
}
}
return P; // return P as our Iterable object
}
//end#fragment PIterator
// Convenience methods
/** Returns whether a position is the first one; O(1) time */
public boolean isFirst(Position<E> p)
throws InvalidPositionException {
DNode<E> v = checkPosition(p);
return v.getPrev() == header;
}
/** Returns whether a position is the last one; O(1) time */
public boolean isLast(Position<E> p)
throws InvalidPositionException {
DNode<E> v = checkPosition(p);
return v.getNext() == trailer;
}
/** Swap the elements of two give positions; O(1) time */
public void swapElements(Position<E> a, Position<E> b)
throws InvalidPositionException {
DNode<E> pA = checkPosition(a);
DNode<E> pB = checkPosition(b);
E temp = pA.element();
pA.setElement(pB.element());
pB.setElement(temp);
}
/** Returns a textual representation of a given node list using for-each */
public static <E> String forEachToString(PositionList<E> L) {
String s = "[";
int i = L.size();
for (E elem: L) {
s += elem; // implicit cast of the element to String
i--;
if (i > 0)
s += ", "; // separate elements with a comma
}
s += "]";
return s;
}
//begin#fragment toString
/** Returns a textual representation of a given node list */
public static <E> String toString(PositionList<E> l) {
Iterator<E> it = l.iterator();
String s = "[";
while (it.hasNext()) {
s += it.next(); // implicit cast of the next element to String
if (it.hasNext())
s += ", ";
}
s += "]";
return s;
}
//end#fragment toString
/** Returns a textual representation of the list */
public String toString() {
return toString(this);
}
}

View File

@@ -0,0 +1,128 @@
package net.datastructures;
/**
* Realization of a queue by means of a singly-linked list of nodes.
* All operations are performed in constant time.
*
* @author Roberto Tamassia
*/
public class NodeQueue<E> implements Queue<E> {
protected Node<E> head, tail; // the head and tail nodes
protected int size; // Keeps track of number of elements in queue
/** Creates an empty queue. */
public NodeQueue() {
head = null;
tail = null;
size = 0;
}
public int size() { //# Return the current queue size
return size;
}
public boolean isEmpty() { //# Returns true iff queue is empty
if ( (head==null) && (tail==null) )
return true;
return false;
}
//begin#fragment enqueue
public void enqueue(E elem) {
Node<E> node = new Node<E>();
node.setElement(elem);
node.setNext(null); // node will be new tail node
if (size == 0)
head = node; // special case of a previously empty queue
else
tail.setNext(node); // add node at the tail of the list
tail = node; // update the reference to the tail node
size++;
}
//end#fragment enqueue
public E front() //# Return the first queue element
throws EmptyQueueException {
if (size == 0)
throw new EmptyQueueException("Queue is empty.");
return head.getElement();
}
//begin#fragment dequeue
public E dequeue() throws EmptyQueueException {
if (size == 0)
throw new EmptyQueueException("Queue is empty.");
E tmp = head.getElement();
head = head.getNext();
size--;
if (size == 0)
tail = null; // the queue is now empty
return tmp;
}
//end#fragment dequeue
public String toString() {
String s = "";
s += "(";
if (!isEmpty()) {
Node p = head;
do {
s += p.getElement() ;
if (p != tail)
s += ", ";
p = p.getNext();
} while (p != null);
}
s += ")";
return s;
}
/**
* Prints information about an operation and the queue.
* @param op operation performed
* @param element element returned by the operation
* @return information about the operation performed, the element
* returned by the operation and the content of the stack after
* the operation.
*/
public static void status(Queue Q, String op, Object element) {
System.out.println("---------------------------------");
System.out.println(op);
System.out.println("Returned: " + element);
String emptyStatus;
if (Q.isEmpty())
emptyStatus = "empty";
else
emptyStatus = "not empty";
System.out.println("size = " + Q.size() + ", " + emptyStatus);
System.out.println("Queue: " + Q);
}
/**
* Test program that performs a series of operations on on a queue and
* prints the operation performed, the returned element and the
* content of the stack after each operation.
*/
public static void main(String[] args) {
Object o;
Queue<Integer> A = new NodeQueue<Integer>();
status (A, "New empty queue", null);
A.enqueue(5);
status (A, "enqueue(5)", null);
A.enqueue(3);
status (A, "enqueue(3)", null);
A.enqueue(7);
status (A, "enqueue(7)", null);
o = A.dequeue();
status (A, "dequeue()", o);
A.enqueue(9);
status (A, "enqueue(9)", null);
o = A.dequeue();
status (A, "dequeue()", o);
o = o = A.front();
status (A, "front()", o);
}
}

View File

@@ -0,0 +1,116 @@
package net.datastructures;
/**
* Implementation of the stack ADT by means of a singly linked list.
*
* @author Natasha Gelfand
* @author Roberto Tamassia
* @see Node
*/
//begin#fragment NodeStack
public class NodeStack<E> implements Stack<E> {
protected Node<E> top; // reference to the head node
protected int size; // number of elements in the stack
//end#fragment NodeStack
/** Creates an empty stack. */
//begin#fragment NodeStack
public NodeStack() { // constructs an empty stack
top = null;
size = 0;
}
public int size() { return size; }
public boolean isEmpty() {
if (top == null) return true;
return false;
}
public void push(E elem) {
Node<E> v = new Node<E>(elem, top); // create and link-in a new node
top = v;
size++;
}
public E top() throws EmptyStackException {
if (isEmpty()) throw new EmptyStackException("Stack is empty.");
return top.getElement();
}
public E pop() throws EmptyStackException {
if (isEmpty()) throw new EmptyStackException("Stack is empty.");
E temp = top.getElement();
top = top.getNext(); // link-out the former top node
size--;
return temp;
}
//end#fragment NodeStack
/**
* Returns a string representation of the stack as a list of elements,
* with the top element at the end: [ ... , prev, top ].
* This method runs in O(n) time, where n is the size of the stack.
* @return textual representation of the stack.
*/
public String toString() {
String s;
Node<E> cur = null;
s = "[";
int n = size();
if (n > 0) {
cur = top;
s += cur.getElement();
}
if (n > 1)
for (int i = 1; i <= n-1; i++) {
cur = cur.getNext();
s += ", " + cur.getElement();
}
s += "]";
return s;
}
/**
* Prints information about an operation and the stack.
* @param op operation performed
* @param element element returned by the operation
* @return information about the operation performed, the element
* returned by the operation and the content of the stack after
* the operation.
*/
public static void status(Stack S, String op, Object element) {
System.out.println("---------------------------------");
System.out.println(op);
System.out.println("Returned: " + element);
String emptyStatus;
if (S.isEmpty())
emptyStatus = "empty";
else
emptyStatus = "not empty";
System.out.println("size = " + S.size() + ", " + emptyStatus);
System.out.println("Stack: " + S);
}
/**
* Test program that performs a series of operations on on a stack and
* prints the operation performed, the returned element and the
* content of the stack after each operation.
*/
public static void main(String[] args) {
Object o;
Stack<Integer> A = new NodeStack<Integer>();
status (A, "New empty stack", null);
A.push(5);
status (A, "push(5)", null);
A.push(3);
status (A, "push(3)", null);
A.push(7);
status (A, "push(7)", null);
o = A.pop();
status (A, "pop()", o);
A.push(9);
status (A, "push(9)", null);
o = A.pop();
status (A, "pop()", o);
o = o = A.top();
status (A, "top()", o);
}
//begin#fragment NodeStack
}
//end#fragment NodeStack

View File

@@ -0,0 +1,11 @@
package net.datastructures;
/**
* Runtime exception thrown when one tries to create the root of a
* tree that is not empty.
*/
public class NonEmptyTreeException extends RuntimeException {
public NonEmptyTreeException(String err) {
super(err);
}
}

View File

@@ -0,0 +1,12 @@
package net.datastructures;
/**
* An interface for a position, which is a holder object storing a
* single element.
* @author Roberto Tamassia, Michael Goodrich
*/
//begin#fragment All
public interface Position<E> {
/** Return the element stored at this position. */
E element();
}
//end#fragment All

View File

@@ -0,0 +1,50 @@
package net.datastructures;
import java.util.Iterator;
/**
* An interface for positional lists.
* @author Roberto Tamassia, Michael Goodrich
*/
//begin#fragment Header
public interface PositionList<E> extends Iterable<E> {
//end#fragment Header
//begin#fragment List
/** Returns the number of elements in this list. */
public int size();
/** Returns whether the list is empty. */
public boolean isEmpty();
/** Returns the first node in the list. */
public Position<E> first();
/** Returns the last node in the list. */
public Position<E> last();
/** Returns the node after a given node in the list. */
public Position<E> next(Position<E> p)
throws InvalidPositionException, BoundaryViolationException;
/** Returns the node before a given node in the list. */
public Position<E> prev(Position<E> p)
throws InvalidPositionException, BoundaryViolationException;
/** Inserts an element at the front of the list, returning new position. */
public void addFirst(E e);
/** Inserts and element at the back of the list, returning new position. */
public void addLast(E e);
/** Inserts an element after the given node in the list. */
public void addAfter(Position<E> p, E e)
throws InvalidPositionException;
/** Inserts an element before the given node in the list. */
public void addBefore(Position<E> p, E e)
throws InvalidPositionException;
/** Removes a node from the list, returning the element stored there. */
public E remove(Position<E> p) throws InvalidPositionException;
/** Replaces the element stored at the given node, returning old element. */
public E set(Position<E> p, E e) throws InvalidPositionException;
//end#fragment List
//begin#fragment Positions
/** Returns an iterable collection of all the nodes in the list. */
public Iterable<Position<E>> positions();
//end#fragment Positions
//begin#fragment Iterator
/** Returns an iterator of all the elements in the list. */
public Iterator<E> iterator();
//end#fragment Iterator
//begin#fragment Tail
}
//end#fragment Tail

View File

@@ -0,0 +1,17 @@
package net.datastructures;
//begin#fragment PriorityQueue
/** Interface for the priority queue ADT */
public interface PriorityQueue<K,V> {
/** Returns the number of items in the priority queue. */
public int size();
/** Returns whether the priority queue is empty. */
public boolean isEmpty();
/** Returns but does not remove an entry with minimum key. */
public Entry<K,V> min() throws EmptyPriorityQueueException;
/** Inserts a key-value pair and return the entry created. */
public Entry<K,V> insert(K key, V value) throws InvalidKeyException;
/** Removes and returns an entry with minimum key. */
public Entry<K,V> removeMin() throws EmptyPriorityQueueException;
}
//end#fragment PriorityQueue

View File

@@ -0,0 +1,43 @@
package net.datastructures;
/**
* Interface for a queue: a collection of elements that are inserted
* and removed according to the first-in first-out principle.
*
* @author Michael T. Goodrich
* @author Natasha Gelfand
* @author Mark Handy
* @author Roberto Tamassia
* @see EmptyQueueException
*/
//begin#fragment Queue
public interface Queue<E> {
/**
* Returns the number of elements in the queue.
* @return number of elements in the queue.
*/
public int size();
/**
* Returns whether the queue is empty.
* @return true if the queue is empty, false otherwise.
*/
public boolean isEmpty();
/**
* Inspects the element at the front of the queue.
* @return element at the front of the queue.
* @exception EmptyQueueException if the queue is empty.
*/
public E front() throws EmptyQueueException;
/**
* Inserts an element at the rear of the queue.
* @param element new element to be inserted.
*/
public void enqueue (E element);
/**
* Removes the element at the front of the queue.
* @return element removed.
* @exception EmptyQueueException if the queue is empty.
*/
public E dequeue() throws EmptyQueueException;
}
//end#fragment Queue

View File

@@ -0,0 +1,219 @@
package net.datastructures;
import java.util.Comparator;
/**
* Realization of a red-black Tree by extending a binary search tree.
*
* @author Michael Goodrich, Roberto Tamassia, Eric Zamore
*/
//begin#fragment RBTree
/** Realization of a dictionary by means of a red-black tree. */
public class RBTree<K,V>
extends BinarySearchTree<K,V> implements Dictionary<K,V> {
public RBTree() { super(); }
public RBTree(Comparator<K> C) { super(C); }
/** Nested class for the nodes of a red-black tree */
protected static class RBNode<K,V> extends BTNode<Entry<K,V>> {
protected boolean isRed; // we add a color field to a BTNode
RBNode() {/* default constructor */}
/** Preferred constructor */
RBNode(Entry<K,V> element, BTPosition<Entry<K,V>> parent,
BTPosition<Entry<K,V>> left, BTPosition<Entry<K,V>> right) {
super(element, parent, left, right);
isRed = false;
}
public boolean isRed() {return isRed;}
public void makeRed() {isRed = true;}
public void makeBlack() {isRed = false;}
public void setColor(boolean color) {isRed = color;}
}
//end#fragment RBTree
//begin#fragment insertItem
/** Creates a new tree node. */
protected BTPosition<Entry<K,V>> createNode(Entry<K,V> element,
BTPosition<Entry<K,V>> parent, BTPosition<Entry<K,V>> left,
BTPosition<Entry<K,V>> right) {
return new RBNode<K,V>(element,parent,left,right); // a red-black node
}
//end#fragment insertItem
/** Inserts an item into the dictionary and returns the newly
* created entry. */
//begin#fragment insertItem
public Entry<K,V> insert(K k, V x) throws InvalidKeyException {
Entry<K,V> toReturn = super.insert(k, x);
Position<Entry<K,V>> posZ = actionPos; // start at the insertion position
setRed(posZ);
if (isRoot(posZ))
setBlack(posZ);
else
remedyDoubleRed(posZ); // fix a double-red color violation
return toReturn;
}
//end#fragment insertItem
/** Remedies a double red violation at a given node caused by insertion. */
//begin#fragment insertItem
protected void remedyDoubleRed(Position<Entry<K,V>> posZ) {
Position<Entry<K,V>> posV = parent(posZ);
if (isRoot(posV))
return;
if (!isPosRed(posV))
return;
// we have a double red: posZ and posV
if (!isPosRed(sibling(posV))) { // Case 1: trinode restructuring
posV = restructure(posZ);
setBlack(posV);
setRed(left(posV));
setRed(right(posV));
}
else { // Case 2: recoloring
setBlack(posV);
setBlack(sibling(posV));
Position<Entry<K,V>> posU = parent(posV);
if (isRoot(posU))
return;
setRed(posU);
remedyDoubleRed(posU);
}
}
//end#fragment insertItem
/** Removes and returns the given entry from the dictionary. */
//begin#fragment remedyDoubleBlack
public Entry<K,V> remove(Entry<K,V> ent) throws InvalidEntryException {
Entry<K,V> toReturn = super.remove(ent);
Position<Entry<K,V>> posR = actionPos;
if (toReturn != null) {
if (wasParentRed(posR) || isRoot(posR) || isPosRed(posR))
setBlack(posR);
else
remedyDoubleBlack(posR);
}
return toReturn;
}
//end#fragment remedyDoubleBlack
/** Remedies a double black violation at a given node caused by removal. */
//begin#fragment remedyDoubleBlack
protected void remedyDoubleBlack(Position<Entry<K,V>> posR) {
Position<Entry<K,V>> posX, posY, posZ;
boolean oldColor;
posX = parent(posR);
posY = sibling(posR);
if (!isPosRed(posY)) {
posZ = redChild(posY);
if (hasRedChild(posY)) { // Case 1: trinode restructuring
oldColor = isPosRed(posX);
posZ = restructure(posZ);
setColor(posZ, oldColor);
setBlack(posR);
setBlack(left(posZ));
setBlack(right(posZ));
return;
}
setBlack(posR);
setRed(posY);
if (!isPosRed(posX)) { // Case 2: recoloring
if (!isRoot(posX))
remedyDoubleBlack(posX);
return;
}
setBlack(posX);
return;
} // Case 3: adjustment
if (posY == right(posX)) posZ = right(posY);
else posZ = left(posY);
restructure(posZ);
setBlack(posY);
setRed(posX);
remedyDoubleBlack(posR);
}
//end#fragment remedyDoubleBlack
/** Returns whether a node is red. */
protected boolean isPosRed(Position<Entry<K,V>> position) {
return ((RBNode) position).isRed();
}
/** Returns whether the former parent of a node was red. */
private boolean wasParentRed(Position<Entry<K,V>> position){
if (!isRoot(position)) {
if(!isPosRed(position) && !isPosRed(parent(position))) {
if (isExternal(sibling(position)) ||
(hasTwoExternalChildren(sibling(position)) &&
isPosRed(sibling(position))))
return true; //then position's old parent was red
}
}
return false;
}
/** Returns whether an internal node has two external children. */
private boolean hasTwoExternalChildren(Position<Entry<K,V>> position){
if (isExternal(left(position))
&& isExternal(right(position)))
return true;
else
return false;
}
/** Colors a node red. */
protected void setRed(Position<Entry<K,V>> position) {
((RBNode) position).makeRed();
}
/** Colors a node black. */
protected void setBlack(Position<Entry<K,V>> position) {
((RBNode) position).makeBlack();
}
/** Sets the color of a node.
* @param color <tt>true</tt> to color the node red, <tt>false</tt>
* to color the node black*/
protected void setColor(Position<Entry<K,V>> position, boolean color) {
((RBNode) position).setColor(color);
}
/** Returns a red child of a node. */
protected Position<Entry<K,V>> redChild(Position<Entry<K,V>> position) {
Position<Entry<K,V>> child = left(position);
if (isPosRed(child))
return child;
child = right(position);
if (isPosRed(child))
return child;
return null;
}
/** Returns whether a node has a red child. */
protected boolean hasRedChild(Position<Entry<K,V>> position){
if (isPosRed(left(position)) || isPosRed(right(position)))
return true;
else
return false;
}
/**
* Swaps the colors of <tt>a</tt> and <tt>b</tt> if they are
* different and returns whether <tt>a</tt> was red.
*/
protected boolean swapColor(Position<Entry<K,V>> a, Position<Entry<K,V>> b){
boolean wasRed = false;
if (isPosRed(a) && !isPosRed(b)){
wasRed = true;
setBlack(a);
setRed(b);
}
else if (!isPosRed(a) && isPosRed(b)){
setBlack(b);
setRed(a);
}
return wasRed;
}
/** Swaps the colors and elements at the two nodes. */
protected void swap(Position<Entry<K,V>> swapPos, Position<Entry<K,V>> remPos){
swapColor(remPos, swapPos);
swapElements(swapPos, remPos);
}
}

View File

@@ -0,0 +1,225 @@
package net.datastructures;
import java.util.Comparator;
/**
* Realization of a red-black tree by extending a binary search tree.
*
* @author Michael Goodrich, Roberto Tamassia, Eric Zamore
*/
//begin#fragment RBTree
/** Realization of a map by means of a red-black tree. */
public class RBTreeMap<K,V>
extends BinarySearchTreeMap<K,V> implements Map<K,V> {
public RBTreeMap() { super(); }
public RBTreeMap(Comparator<K> C) { super(C); }
/** Nested class for the nodes of a red-black tree */
protected static class RBNode<K,V> extends BTNode<Entry<K,V>> {
protected boolean isRed; // we add a color field to a BTNode
RBNode() {/* default constructor */}
/** Preferred constructor */
RBNode(Entry<K,V> element, BTPosition<Entry<K,V>> parent,
BTPosition<Entry<K,V>> left, BTPosition<Entry<K,V>> right) {
super(element, parent, left, right);
isRed = false;
}
public boolean isRed() {return isRed;}
public void makeRed() {isRed = true;}
public void makeBlack() {isRed = false;}
public void setColor(boolean color) {isRed = color;}
}
//end#fragment RBTree
//begin#fragment insertItem
/** Creates a new tree node. */
protected BTPosition<Entry<K,V>> createNode(Entry<K,V> element,
BTPosition<Entry<K,V>> parent, BTPosition<Entry<K,V>> left,
BTPosition<Entry<K,V>> right) {
return new RBNode<K,V>(element,parent,left,right); // a red-black node
}
//end#fragment insertItem
/**
* If there is an entry with the specified key, replaces the value of
* this entry with the specified value and returns the old value. Else,
* adds a new entry with the specified key and value and returns null.
*/
//begin#fragment insertItem
public V put(K k, V x) throws InvalidKeyException {
V toReturn = super.put(k, x);
Position<Entry<K,V>> posZ = actionPos;
if (toReturn == null) { // a new entry has been added
setRed(posZ);
if (isRoot(posZ))
setBlack(posZ);
else
remedyDoubleRed(posZ); // fix a double-red color violation
}
return toReturn;
}
//end#fragment insertItem
/** Remedies a double red violation at a given node caused by insertion. */
//begin#fragment insertItem
protected void remedyDoubleRed(Position<Entry<K,V>> posZ) {
Position<Entry<K,V>> posV = parent(posZ);
if (isRoot(posV))
return;
if (!isPosRed(posV))
return;
// we have a double red: posZ and posV
if (!isPosRed(sibling(posV))) { // Case 1: trinode restructuring
posV = restructure(posZ);
setBlack(posV);
setRed(left(posV));
setRed(right(posV));
}
else { // Case 2: recoloring
setBlack(posV);
setBlack(sibling(posV));
Position<Entry<K,V>> posU = parent(posV);
if (isRoot(posU))
return;
setRed(posU);
remedyDoubleRed(posU);
}
}
//end#fragment insertItem
/**
* If there is an entry with the specified key, removes this entry and
* returns its value. Else, returns null.
*/
//begin#fragment remedyDoubleBlack
public V remove(K k) throws InvalidKeyException {
V toReturn = super.remove(k);
Position<Entry<K,V>> posR = actionPos;
if (toReturn != null) {
if (wasParentRed(posR) || isRoot(posR) || isPosRed(posR))
setBlack(posR);
else
remedyDoubleBlack(posR);
}
return toReturn;
}
//end#fragment remedyDoubleBlack
/** Remedies a double black violation at a given node caused by removal. */
//begin#fragment remedyDoubleBlack
protected void remedyDoubleBlack(Position<Entry<K,V>> posR) {
Position<Entry<K,V>> posX, posY, posZ;
boolean oldColor;
posX = parent(posR);
posY = sibling(posR);
if (!isPosRed(posY)) {
posZ = redChild(posY);
if (hasRedChild(posY)) { // Case 1: trinode restructuring
oldColor = isPosRed(posX);
posZ = restructure(posZ);
setColor(posZ, oldColor);
setBlack(posR);
setBlack(left(posZ));
setBlack(right(posZ));
return;
}
setBlack(posR);
setRed(posY);
if (!isPosRed(posX)) { // Case 2: recoloring
if (!isRoot(posX))
remedyDoubleBlack(posX);
return;
}
setBlack(posX);
return;
} // Case 3: adjustment
if (posY == right(posX)) posZ = right(posY);
else posZ = left(posY);
restructure(posZ);
setBlack(posY);
setRed(posX);
remedyDoubleBlack(posR);
}
//end#fragment remedyDoubleBlack
/** Returns whether a node is red. */
protected boolean isPosRed(Position<Entry<K,V>> position) {
return ((RBNode) position).isRed();
}
/** Returns whether the former parent of a node was red. */
private boolean wasParentRed(Position<Entry<K,V>> position){
if (!isRoot(position)) {
if(!isPosRed(position) && !isPosRed(parent(position))) {
if (isExternal(sibling(position)) ||
(hasTwoExternalChildren(sibling(position)) &&
isPosRed(sibling(position))))
return true; //then position's old parent was red
}
}
return false;
}
/** Returns whether an internal node has two external children. */
private boolean hasTwoExternalChildren(Position<Entry<K,V>> position){
if (isExternal(left(position))
&& isExternal(right(position)))
return true;
else
return false;
}
/** Colors a node red. */
protected void setRed(Position<Entry<K,V>> position) {
((RBNode) position).makeRed();
}
/** Colors a node black. */
protected void setBlack(Position<Entry<K,V>> position) {
((RBNode) position).makeBlack();
}
/** Sets the color of a node.
* @param color <tt>true</tt> to color the node red, <tt>false</tt>
* to color the node black*/
protected void setColor(Position<Entry<K,V>> position, boolean color) {
((RBNode) position).setColor(color);
}
/** Returns a red child of a node. */
protected Position<Entry<K,V>> redChild(Position<Entry<K,V>> position) {
Position<Entry<K,V>> child = left(position);
if (isPosRed(child))
return child;
child = right(position);
if (isPosRed(child))
return child;
return null;
}
/** Returns whether a node has a red child. */
protected boolean hasRedChild(Position<Entry<K,V>> position){
if (isPosRed(left(position)) || isPosRed(right(position)))
return true;
else
return false;
}
/**
* Swaps the colors of <tt>a</tt> and <tt>b</tt> if they are
* different and returns whether <tt>a</tt> was red.
*/
protected boolean swapColor(Position<Entry<K,V>> a, Position<Entry<K,V>> b){
boolean wasRed = false;
if (isPosRed(a) && !isPosRed(b)){
wasRed = true;
setBlack(a);
setRed(b);
}
else if (!isPosRed(a) && isPosRed(b)){
setBlack(b);
setRed(a);
}
return wasRed;
}
/** Swaps the colors and elements at the two nodes. */
protected void swap(Position<Entry<K,V>> swapPos, Position<Entry<K,V>> remPos){
swapColor(remPos, swapPos);
swapElements(swapPos, remPos);
}
}

View File

@@ -0,0 +1,17 @@
package net.datastructures;
//begin#fragment Sequence
/**
* An interface for a sequence, a data structure supporting all
* operations of a deque, indexed list and position list.
//end#fragment Sequence
* @author Roberto Tamassia, Michael Goodrich
//begin#fragment Sequence
*/
public interface Sequence<E>
extends Deque<E>, IndexList<E>, PositionList<E> {
/** Returns the position containing the element at the given index. */
public Position<E> atIndex(int r) throws BoundaryViolationException;
/** Returns the index of the element stored at the given position. */
public int indexOf(Position<E> p) throws InvalidPositionException;
}
//end#fragment Sequence

View File

@@ -0,0 +1,254 @@
package net.datastructures;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.IOException;
import java.util.Comparator;
import java.util.Random;
import java.util.Arrays;
/**
* Class containing various sorting algorithms.
*
* @author Michael Goodrich, Roberto Tamassia, Eric Zamore
*/
public class Sort {
//begin#fragment mergeSort
/**
* Sorts the elements of list in in nondecreasing order according
* to comparator c, using the merge-sort algorithm.
**/
public static <E> void mergeSort (PositionList<E> in, Comparator<E> c) {
int n = in.size();
if (n < 2)
return; // the in list is already sorted in this case
// divide
PositionList<E> in1 = new NodePositionList<E>();
PositionList<E> in2 = new NodePositionList<E>();
int i = 0;
while (i < n/2) {
in1.addLast(in.remove(in.first())); // move the first n/2 elements to in1
i++;
}
while (!in.isEmpty())
in2.addLast(in.remove(in.first())); // move the rest to in2
// recur
mergeSort(in1,c);
mergeSort(in2,c);
//conquer
merge(in1,in2,c,in);
}
//end#fragment mergeSort
//begin#fragment merge
/**
* Merges two sorted lists, in1 and in2, into a sorted list in.
**/
public static <E> void merge(PositionList<E> in1, PositionList<E> in2,
Comparator<E> c, PositionList<E> in) {
while (!in1.isEmpty() && !in2.isEmpty())
if (c.compare(in1.first().element(), in2.first().element()) <= 0)
in.addLast(in1.remove(in1.first()));
else
in.addLast(in2.remove(in2.first()));
while(!in1.isEmpty()) // move the remaining elements of in1
in.addLast(in1.remove(in1.first()));
while(!in2.isEmpty()) // move the remaining elements of in2
in.addLast(in2.remove(in2.first()));
}
//end#fragment merge
//begin#fragment mergeSort2
/** Sorts an array with a comparator using nonrecursive merge sort. */
public static <E> void mergeSort(E[] orig, Comparator<E> c) {
E[] in = (E[]) new Object[orig.length]; // make a new temporary array
System.arraycopy(orig,0,in,0,in.length); // copy the input
E[] out = (E[]) new Object[in.length]; // output array
E[] temp; // temp array reference used for swapping
int n = in.length;
for (int i=1; i < n; i*=2) { // each iteration sorts all length-2*i runs
for (int j=0; j < n; j+=2*i) // each iteration merges two length-i pairs
merge(in,out,c,j,i); // merge from in to out two length-i runs at j
temp = in; in = out; out = temp; // swap arrays for next iteration
}
// the "in" array contains the sorted array, so re-copy it
System.arraycopy(in,0,orig,0,in.length);
}
/** Merges two subarrays, specified by a start and increment. */
protected static <E> void merge(E[] in, E[] out, Comparator<E> c, int start,
int inc) { // merge in[start..start+inc-1] and in[start+inc..start+2*inc-1]
int x = start; // index into run #1
int end1 = Math.min(start+inc, in.length); // boundary for run #1
int end2 = Math.min(start+2*inc, in.length); // boundary for run #2
int y = start+inc; // index into run #2 (could be beyond array boundary)
int z = start; // index into the out array
while ((x < end1) && (y < end2))
if (c.compare(in[x],in[y]) <= 0) out[z++] = in[x++];
else out[z++] = in[y++];
if (x < end1) // first run didn't finish
System.arraycopy(in, x, out, z, end1 - x);
else if (y < end2) // second run didn't finish
System.arraycopy(in, y, out, z, end2 - y);
}
//end#fragment mergeSort2
/**
* Sorts the elements of list in in nondecreasing order according to
* comparator c, using a list-based implementation of the deterministic
* quicksort algorithm.
**/
public static <E> void quickSort(PositionList<E> in, Comparator<E> c) {
if (in.size() <= 1)
return;
E pivot = in.remove(in.last());
PositionList<E> lesser = new NodePositionList<E>();
PositionList<E> equal = new NodePositionList<E>();
PositionList<E> greater = new NodePositionList<E>();
E cur;
while (!in.isEmpty()) {
cur = in.remove(in.first());
if (c.compare(cur,pivot) < 0)
lesser.addFirst(cur);
else if(c.compare(cur,pivot) == 0)
equal.addFirst(cur);
else
greater.addFirst(cur);
}
quickSort(lesser,c); // recur on lesser list
quickSort(greater,c); // recur on greater list
while(!lesser.isEmpty())
in.addLast(lesser.remove(lesser.first()));
while(!equal.isEmpty())
in.addLast(equal.remove(equal.first()));
in.addLast(pivot);
while(!greater.isEmpty())
in.addLast(greater.remove(greater.first()));
}
/**
* Sorts the elements of array s in nondecreasing order according
* to comparator c, using the quick-sort algorithm. Most of the work
* is done by the auxiliary recursive method quickSortStep.
**/
//begin#fragment quickSort
public static <E> void quickSort (E[] s, Comparator<E> c) {
if (s.length < 2) return; // the array is already sorted in this case
quickSortStep(s, c, 0, s.length-1); // recursive sort method
}
//end#fragment quickSort
/**
* Sorts in nondecreasing order the elements of sequence s between
* ranks leftBound and rightBound, using a recursive, in-place,
* implementation of the quick-sort algorithm.
**/
//begin#fragment quickSortStep
private static <E> void quickSortStep (E[] s, Comparator<E> c,
int leftBound, int rightBound ) {
if (leftBound >= rightBound) return; // the indices have crossed
E temp; // temp object used for swapping
E pivot = s[rightBound];
int leftInd = leftBound; // will scan rightward
int rightInd = rightBound-1; // will scan leftward
while (leftInd <= rightInd) { // scan right until larger than the pivot
while ( (leftInd <= rightInd) && (c.compare(s[leftInd], pivot)<=0) )
leftInd++;
while ( (rightInd >= leftInd) && (c.compare(s[rightInd], pivot)>=0))
rightInd--;
if (leftInd < rightInd) { // both elements were found, so swap
temp = s[rightInd]; s[rightInd] = s[leftInd]; s[leftInd] = temp;
}
} // the loop continues until the indices cross
temp = s[rightBound]; // swap pivot with element at leftInd
s[rightBound] = s[leftInd];
s[leftInd] = temp; // the pivot is now at leftInd
quickSortStep(s, c, leftBound, leftInd-1); // left recursive call
quickSortStep(s, c, leftInd+1, rightBound); // right recursive call
}
//end#fragment quickSortStep
public static void main (String[] argv) throws IOException {
out("Start your engines...");
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
Random r = new Random();
Comparator<Integer> c = new DefaultComparator<Integer>();
out("Enter number of elements:");
String num = in.readLine();
int n = (new Integer(num)).intValue();
String cont;
Integer[] A = new Integer[n];
Integer[] B = new Integer[n];
float msin=0f,qsin=0f,msout=0f,qsout=0f;
long t;
do {
PositionList<Integer> C = new NodePositionList<Integer>();
PositionList<Integer> D = new NodePositionList<Integer>();
for (int i = 0; i < n; i++) {
int x = r.nextInt(100);
A[i] = new Integer(x);
B[i] = new Integer(x);
C.addLast(new Integer(x));
D.addLast(new Integer(x));
}
out("Array-Based Sorting");
out("Before: " + Arrays.asList(A));
//array-based mergesort
t = System.currentTimeMillis();
mergeSort(A, c);
msin = (System.currentTimeMillis()-t)/1000f;
out("MSort: " + Arrays.asList(A));
String correct = Arrays.asList(A).toString();
//array-based quicksort
t = System.currentTimeMillis();
quickSort(B, c);
qsin = (System.currentTimeMillis()-t)/1000f;
out("QSort: " + Arrays.asList(B));
if(!correct.equals(Arrays.asList(B).toString())) {
System.out.println("sorts produced different results!");
System.exit(1);
}
out("List-Based Sorting");
//list-based mergesort
t = System.currentTimeMillis();
mergeSort(C, c);
out("MSort: " + C);
msout = (System.currentTimeMillis()-t)/1000f;
if(!correct.equals(C.toString())) {
System.out.println("sorts produced different results!");
System.exit(1);
}
//list-based quicksort
t = System.currentTimeMillis();
quickSort(D, c);
out("QSort: " + D);
qsout = (System.currentTimeMillis()-t)/1000f;
if(!correct.equals(D.toString())) {
System.out.println("sorts produced different results!");
System.exit(1);
}
out("Times (in seconds)");
out("Array-Based");
out("MSort: "+msin);
out("QSort: "+qsin);
out("List-Based");
out("MSort: "+msout);
out("QSort: "+qsout);
out("Type 'e' to end ...");
cont = in.readLine();
} while (cont.equals(""));
}
private static void out (String s) {
System.out.println(s);
}
}

View File

@@ -0,0 +1,117 @@
package net.datastructures;
import java.util.Comparator;
/**
* Realization of a priority queue by means of a sorted node list in
* nondecreasing order.
* @author Roberto Tamassia, Michael Goodrich, Eric Zamore
*/
//begin#fragment SortedListPriorityQueue1
public class SortedListPriorityQueue<K,V> implements PriorityQueue<K,V> {
protected PositionList<Entry<K,V>> entries;
protected Comparator<K> c;
protected Position<Entry<K,V>> actionPos; // variable used by subclasses
/** Inner class for entries */
protected static class MyEntry<K,V> implements Entry<K,V> {
protected K k; // key
protected V v; // value
public MyEntry(K key, V value) {
k = key;
v = value;
}
// methods of the Entry interface
public K getKey() { return k; }
public V getValue() { return v; }
//end#fragment SortedListPriorityQueue1
// overrides toString, useful for debugging
public String toString() { return "(" + k + "," + v + ")"; }
//begin#fragment SortedListPriorityQueue1
}
/** Creates the priority queue with the default comparator. */
public SortedListPriorityQueue () {
entries = new NodePositionList<Entry<K,V>>();
c = new DefaultComparator<K>();
}
/** Creates the priority queue with the given comparator. */
public SortedListPriorityQueue (Comparator<K> comp) {
entries = new NodePositionList<Entry<K,V>>();
c = comp;
}
//end#fragment SortedListPriorityQueue1
/** Creates the priority queue with the given comparator and list.
* The list is assumed to be sorted in nondecreasing order.*/
public SortedListPriorityQueue (PositionList<Entry<K,V>> list, Comparator<K> comp) {
entries = list;
c = comp;
}
/** Sets the comparator for this priority queue.
* @throws IllegalStateException if priority queue is not empty */
public void setComparator(Comparator<K> comp) throws IllegalStateException {
if(!isEmpty()) // this is only allowed if the priority queue is empty
throw new IllegalStateException("Priority queue is not empty");
c = comp;
}
/** Returns the number of elements in the priority queue. */
public int size () {return entries.size(); }
/** Returns whether the priority queue is empty. */
public boolean isEmpty () { return entries.isEmpty(); }
//begin#fragment SortedListPriorityQueue2
/** Returns but does not remove an entry with minimum key. */
public Entry<K,V> min () throws EmptyPriorityQueueException {
if (entries.isEmpty())
throw new EmptyPriorityQueueException("priority queue is empty");
else
return entries.first().element();
}
/** Inserts a key-value pair and return the entry created. */
public Entry<K,V> insert (K k, V v) throws InvalidKeyException {
checkKey(k); // auxiliary key-checking method (could throw exception)
Entry<K,V> entry = new MyEntry<K,V>(k, v);
insertEntry(entry); // auxiliary insertion method
return entry;
}
/** Auxiliary method used for insertion. */
protected void insertEntry(Entry<K,V> e) {
if (entries.isEmpty()) {
entries.addFirst(e); // insert into empty list
actionPos = entries.first(); // insertion position
}
else if (c.compare(e.getKey(), entries.last().element().getKey()) > 0) {
entries.addLast(e); // insert at the end of the list
actionPos = entries.last(); // insertion position
}
else {
Position<Entry<K,V>> curr = entries.first();
while (c.compare(e.getKey(), curr.element().getKey())> 0) {
curr = entries.next(curr); // advance toward insertion position
}
entries.addBefore(curr, e);
actionPos = entries.prev(curr); // insertion position
}
}
/** Removes and returns an entry with minimum key. */
public Entry<K,V> removeMin() throws EmptyPriorityQueueException {
if (entries.isEmpty())
throw new EmptyPriorityQueueException("priority queue is empty");
else
return entries.remove(entries.first());
}
//end#fragment SortedListPriorityQueue2
//begin#fragment SortedListPriorityQueue3
/** Determines whether a key is valid. */
protected boolean checkKey(K key) throws InvalidKeyException {
boolean result;
try { // check if the key can be compared to itself
result = (c.compare(key,key)==0);
} catch (ClassCastException e)
{ throw new InvalidKeyException("key cannot be compared"); }
return result;
}
// overrides toString, useful for debugging
public String toString() {
return entries.toString();
}
//end#fragment SortedListPriorityQueue3
//begin#fragment tail
}
//end#fragment tail

View File

@@ -0,0 +1,44 @@
package net.datastructures;
//begin#fragment Stack
/**
* Interface for a stack: a collection of objects that are inserted
* and removed according to the last-in first-out principle. This
* interface includes the main methods of java.util.Stack.
*
* @author Roberto Tamassia
* @author Michael Goodrich
* @see EmptyStackException
*/
public interface Stack<E> {
/**
* Return the number of elements in the stack.
* @return number of elements in the stack.
*/
public int size();
/**
* Return whether the stack is empty.
* @return true if the stack is empty, false otherwise.
*/
public boolean isEmpty();
/**
* Inspect the element at the top of the stack.
* @return top element in the stack.
* @exception EmptyStackException if the stack is empty.
*/
public E top()
throws EmptyStackException;
/**
* Insert an element at the top of the stack.
* @param element to be inserted.
*/
public void push (E element);
/**
* Remove the top element from the stack.
* @return element removed.
* @exception EmptyStackException if the stack is empty.
*/
public E pop()
throws EmptyStackException;
}
//end#fragment Stack

View File

@@ -0,0 +1,41 @@
package net.datastructures;
import java.util.Iterator;
//begin#fragment Tree
/**
* An interface for a tree where nodes can have an arbitrary number of children.
//end#fragment Tree
* @author Michael Goodrich
//begin#fragment Tree
*/
public interface Tree<E> {
/** Returns the number of nodes in the tree. */
public int size();
/** Returns whether the tree is empty. */
public boolean isEmpty();
/** Returns an iterator of the elements stored in the tree. */
public Iterator<E> iterator();
/** Returns an iterable collection of the the nodes. */
public Iterable<Position<E>> positions();
/** Replaces the element stored at a given node. */
public E replace(Position<E> v, E e)
throws InvalidPositionException;
/** Returns the root of the tree. */
public Position<E> root() throws EmptyTreeException;
/** Returns the parent of a given node. */
public Position<E> parent(Position<E> v)
throws InvalidPositionException, BoundaryViolationException;
/** Returns an iterable collection of the children of a given node. */
public Iterable<Position<E>> children(Position<E> v)
throws InvalidPositionException;
/** Returns whether a given node is internal. */
public boolean isInternal(Position<E> v)
throws InvalidPositionException;
/** Returns whether a given node is external. */
public boolean isExternal(Position<E> v)
throws InvalidPositionException;
/** Returns whether a given node is the root of the tree. */
public boolean isRoot(Position<E> v)
throws InvalidPositionException;
}
//end#fragment Tree

View File

@@ -0,0 +1,39 @@
package net.datastructures;
//begin#fragment TNode
/**
* Class implementing a node of a binary tree by storing references to
* an element, a parent node, a left node, and a right node.
//end#fragment TNode
*
* @author Luca Vismara, Roberto Tamassia, Michael Goodrich
//begin#fragment TNode
*/
public class TreeNode<E> implements TreePosition<E> {
private E element; // element stored at this node
private TreePosition<E> parent; // adjacent node
private PositionList<Position<E>> children; // children nodes
//end#fragment TNode
/** Default constructor */
public TreeNode() { }
//begin#fragment TNode
/** Main constructor */
public TreeNode(E element, TreePosition<E> parent,
PositionList<Position<E>> children) {
setElement(element);
setParent(parent);
setChildren(children);
}
/** Returns the element stored at this position */
public E element() { return element; }
/** Sets the element stored at this position */
public void setElement(E o) { element=o; }
/** Returns the children of this position */
public PositionList<Position<E>> getChildren() { return children; }
/** Sets the right child of this position */
public void setChildren(PositionList<Position<E>> c) { children=c; }
/** Returns the parent of this position */
public TreePosition<E> getParent() { return parent; }
/** Sets the parent of this position */
public void setParent(TreePosition<E> v) { parent=v; }
}
//end#fragment TNode

View File

@@ -0,0 +1,18 @@
package net.datastructures;
//begin#fragment TPos
/**
* Interface for a node of a binary tree. It maintains an element, a
* parent node, a left node, and a right node.
//end#fragment TPos
*
* @author Michael Goodrich
//begin#fragment TPos
*/
public interface TreePosition<E> extends Position<E> { // inherits element()
public void setElement(E o);
public PositionList<Position<E>> getChildren();
public void setChildren(PositionList<Position<E>> c);
public TreePosition<E> getParent();
public void setParent(TreePosition<E> v);
}
//end#fragment TPos

View File

@@ -0,0 +1,6 @@
package net.datastructures;
/**
* An interface for a vertex of a graph.
* @author Roberto Tamassia
*/
public interface Vertex<E> extends DecorablePosition<E> { }