Binary search tree
BinarySearchTree.java
package comp2402a5;
import java.util.Collection;
import java.util.Comparator;
import java.util.Iterator;
public class BinarySearchTree<Node extends BSTNode<Node,T>, T> extends
BinaryTree<Node> implements SSet<T> {
public Comparator<T> c;
/**
* The number of nodes (elements) currently in the tree
*/
public int n;
public Node newNode(T x) {
Node u = super.newNode();
u.x = x;
return u;
}
public BinarySearchTree(Node is, Comparator<T> c) {
super(is);
this.c = c;
}
public BinarySearchTree(Node is) {
this(is, new DefaultComparator<T>());
}
/**
* Create a new instance of this class
* @warning child must set sampleNode before anything that
* might make calls to newNode()
*/
public BinarySearchTree() {
this(null, new DefaultComparator<T>());
}
/**
* Search for a value in the tree
* @return the last node on the search path for x
*/
public Node findLast(T x) {
Node w = r, prev = nil;
while (w != nil) {
prev = w;
int comp = c.compare(x, w.x);
if (comp < 0) {
w = w.left;
} else if (comp > 0) {
w = w.right;
} else {
return w;
}
}
return prev;
}
/**
* Search for a value in the tree
* @return the last node on the search path for x
*/
public Node findGENode(T x) {
Node w = r, z = nil;
while (w != nil) {
int comp = c.compare(x, w.x);
if (comp < 0) {
z = w;
w = w.left;
} else if (comp > 0) {
w = w.right;
} else {
return w;
}
}
return z;
}
public T findEQ(T x) {
Node u = r;
while (u != nil) {
int comp = c.compare(x, u.x);
if (comp < 0)
u = u.left;
else if (comp > 0)
u = u.right;
else
return u.x;
}
return null;
}
public T find(T x) {
Node w = r, z = nil;
while (w != nil) {
int comp = c.compare(x, w.x);
if (comp < 0) {
z = w;
w = w.left;
} else if (comp > 0) {
w = w.right;
} else {
return w.x;
}
}
return z == nil ? null : z.x;
}
public T findGE(T u) {
if (u == null) { // find the minimum value
Node w = r;
if (w == nil) return null;
while (w.left != nil)
w = w.left;
return w.x;
}
Node w = findGENode(u);
return w == nil ? null : w.x;
}
/**
* Search for a value in the tree
* @return the last node on the search path for x
*/
public Node findLTNode(T x) {
Node u = r, z = nil;
while (u != nil) {
int comp = c.compare(x, u.x);
if (comp < 0) {
u = u.left;
} else if (comp > 0) {
z = u;
u = u.right;
} else {
return u;
}
}
return z;
}
public T findLT(T x) {
if (x == null) { // find the maximum value
Node w = r;
if (w == nil) return null;
while (w.right != nil)
w = w.right;
return w.x;
}
Node w = findLTNode(x);
return w == nil ? null : w.x;
}
/**
* Add the node u as a child of node p — ASSUMES p has no child
* where u should be added
* @param p
* @param u
* @return true if the child was added, false otherwise
*/
public boolean addChild(Node p, Node u) {
if (p == nil) {
r = u; // inserting into empty tree
} else {
int comp = c.compare(u.x, p.x);
if (comp < 0) {
p.left = u;
} else if (comp > 0) {
p.right = u;
} else {
return false; // u.x is already in the tree
}
u.parent = p;
}
n++;
return true;
}
/**
* Add a new value
* @param x
* @return
*/
public boolean add(T x) {
Node p = findLast(x);
return addChild(p, newNode(x));
}
/**
* Add a new value
* @param x
* @return
*/
public boolean add(Node u) {
Node p = findLast(u.x);
return addChild(p, u);
}
/**
* Remove the node u — ASSUMING u has at most one child
* @param u
*/
public void splice(Node u) {
Node s, p;
if (u.left != nil) {
s = u.left;
} else {
s = u.right;
}
if (u == r) {
r = s;
p = nil;
} else {
p = u.parent;
if (p.left == u) {
p.left = s;
} else {
p.right = s;
}
}
if (s != nil) {
s.parent = p;
}
n–;
}
/**
* Remove the node u from the binary search tree
* @param u
*/
public void remove(Node u) {
if (u.left == nil || u.right == nil) {
splice(u);
} else {
Node w = u.right;
while (w.left != nil)
w = w.left;
u.x = w.x;
splice(w);
}
}
/**
* Do a left rotation at u
* @param u
*/
public void rotateLeft(Node u) {
Node w = u.right;
w.parent = u.parent;
if (w.parent != nil) {
if (w.parent.left == u) {
w.parent.left = w;
} else {
w.parent.right = w;
}
}
u.right = w.left;
if (u.right != nil) {
u.right.parent = u;
}
u.parent = w;
w.left = u;
if (u == r) { r = w; r.parent = nil; }
}
/**
* Do a right rotation at u
* @param u
*/
public void rotateRight(Node u) {
Node w = u.left;
w.parent = u.parent;
if (w.parent != nil) {
if (w.parent.left == u) {
w.parent.left = w;
} else {
w.parent.right = w;
}
}
u.left = w.right;
if (u.left != nil) {
u.left.parent = u;
}
u.parent = w;
w.right = u;
if (u == r) { r = w; r.parent = nil; }
}
/**
* Remove a node
* @param x
* @return
*/
public boolean remove(T x) {
Node u = findLast(x);
if (u != nil && c.compare(x,u.x) == 0) {
remove(u);
return true;
}
return false;
}
public String toString() {
String s = “[“;
Iterator<T> it = iterator();
while (it.hasNext()) {
s += it.next().toString() + (it.hasNext() ? “,” : “”);
}
s += “]”;
return s;
}
@SuppressWarnings({“unchecked”})
public boolean contains(Object x) {
Node u = findLast((T)x);
return u != nil && c.compare(u.x, (T)x) == 0;
}
public boolean containsAll(Collection<?> c) {
for (Object x : c)
if (!contains(x))
return false;
return true;
}
public Iterator<T> iterator(Node u) {
class BTI implements Iterator<T> {
public Node w, prev;
public BTI(Node iw) {
w = iw;
}
public boolean hasNext() {
return w != nil;
}
public T next() {
T x = w.x;
prev = w;
w = nextNode(w);
return x;
}
public void remove() {
// FIXME: This is a bug. remove() methods have to be changed
BinarySearchTree.this.remove(prev);
}
}
return new BTI(u);
}
public Iterator<T> iterator() {
return iterator(firstNode());
}
public Iterator<T> iterator(T x) {
return iterator(findGENode(x));
}
public int size() {
return n;
}
public boolean isEmpty() {
return n == 0;
}
public void clear() {
super.clear();
n = 0;
}
public Comparator<? super T> comparator() {
return c;
}
}
BinaryTree.java
package comp2402a5;
import java.util.LinkedList;
import java.util.Queue;
import java.util.Random;
public class BinaryTree<Node extends BinaryTreeNode<Node>> {
/**
* Used to make a mini-factory
*/
public Node sampleNode;
/**
* The root of this tree
*/
public Node r;
/**
* This tree’s null node
*/
public Node nil;
/**
* Create a new instance of this class
* @param isampleNode
*/
public BinaryTree(Node nil) {
sampleNode = nil;
this.nil = null;
}
/**
* Create a new instance of this class
* @warning child must set sampleNode before anything that
* might make calls to newNode()
*/
public BinaryTree() { }
/**
* Allocate a new node for use in this tree
* @return
*/
@SuppressWarnings({“unchecked”})
public Node newNode() {
try {
Node u = (Node)sampleNode.getClass().newInstance();
u.parent = u.left = u.right = nil;
return u;
} catch (Exception e) {
return null;
}
}
public int depth(Node u) {
int d = 0;
while (u != r) {
u = u.parent;
d++;
}
return d;
}
/**
* Compute the size (number of nodes) of this tree
* @return the number of nodes in this tree
*/
public int size() {
return size(r);
}
/**
* @return the size of the subtree rooted at u
*/
public int size(Node u) {
if (u == nil)
return 0;
return 1 + size(u.left) + size(u.right);
}
public int height() {
return height(r);
}
/**
* @return the size of the subtree rooted at u
*/
public int height(Node u) {
if (u == nil)
return -1;
return 1 + Math.max(height(u.left), height(u.right));
}
/**
* @return
*/
public boolean isEmpty() {
return r == nil;
}
/**
* Make this tree into the empty tree
*/
public void clear() {
r = nil;
}
public void traverse(Node u) {
if (u == nil) return;
traverse(u.left);
traverse(u.right);
}
public void traverse2() {
Node u = r, prev = nil, next;
while (u != nil) {
if (prev == u.parent) {
if (u.left != nil) next = u.left;
else if (u.right != nil) next = u.right;
else next = u.parent;
} else if (prev == u.left) {
if (u.right != nil) next = u.right;
else next = u.parent;
} else {
next = u.parent;
}
prev = u;
u = next;
}
}
public int size2() {
Node u = r, prev = nil, next;
int n = 0;
while (u != nil) {
if (prev == u.parent) {
n++;
if (u.left != nil) next = u.left;
else if (u.right != nil) next = u.right;
else next = u.parent;
} else if (prev == u.left) {
if (u.right != nil) next = u.right;
else next = u.parent;
} else {
next = u.parent;
}
prev = u;
u = next;
}
return n;
}
public void bfTraverse() {
Queue<Node> q = new LinkedList<Node>();
q.add(r);
while (!q.isEmpty()) {
Node u = q.remove();
if (u.left != nil) q.add(u.left);
if (u.right != nil) q.add(u.right);
}
}
/**
* Find the first node in an in-order traversal
* @return
*/
public Node firstNode() {
Node w = r;
if (w == nil) return nil;
while (w.left != nil)
w = w.left;
return w;
}
/**
* Find the node that follows u in an in-order traversal
* @param w
* @return
*/
public Node nextNode(Node w) {
if (w.right != nil) {
w = w.right;
while (w.left != nil)
w = w.left;
} else {
while (w.parent != nil && w.parent.left != w)
w = w.parent;
w = w.parent;
}
return w;
}
public static <Node extends BinaryTreeNode<Node>> void completeBinaryTree(BinaryTree<Node> t, int n) {
Queue<Node> q = new LinkedList<Node>();
t.clear();
if (n == 0)
return;
t.r = t.newNode();
q.add(t.r);
while (–n > 0) {
Node u = q.remove();
u.left = t.newNode();
u.left.parent = u;
q.add(u.left);
if (–n > 0) {
u.right = t.newNode();
u.right.parent = u;
q.add(u.right);
}
}
}
/**
* Create a new full binary tree whose expected number of nodes is n
* @param <Node>
* @param t
* @param n
*/
public static <Node extends BinaryTreeNode<Node>> void galtonWatsonFullTree(BinaryTree<Node> t, int n) {
Random r = new Random();
Queue<Node> q = new LinkedList<Node>();
t.clear();
t.r = t.newNode();
q.add(t.r);
double p = ((double)0.5 – ((double)1)/(n+n));
while (!q.isEmpty()) {
Node u = q.remove();
if (r.nextDouble() < p) {
u.left = t.newNode();
u.left.parent = u;
q.add(u.left);
u.right = t.newNode();
u.right.parent = u;
q.add(u.right);
}
}
}
static <Node extends BinaryTreeNode<Node>> void galtonWatsonTree(BinaryTree<Node> t, int n) {
Random r = new Random();
Queue<Node> q = new LinkedList<Node>();
t.clear();
t.r = t.newNode();
q.add(t.r);
double p = ((double)0.5 – ((double)1)/(n+n));
while (!q.isEmpty()) {
Node u = q.remove();
if (r.nextDouble() < p) {
u.left = t.newNode();
u.left.parent = u;
q.add(u.left);
} if (r.nextDouble() < p) {
u.right = t.newNode();
u.right.parent = u;
q.add(u.right);
}
}
}
}
BinaryTreeNode.java
package comp2402a5;
/**
* This class represents a node in a binary tree. This class is abstract and
* should be subclassed by a concrete class. See, for example the class
* SimpleBinaryTreeNode.
*
* @author morin
*
* @param <Node>
* the class of the children of this node
*/
public class BinaryTreeNode<Node extends BinaryTreeNode<Node>> {
public Node left;
public Node right;
public Node parent;
}
BSTNode.java
package comp2402a5;
public class BSTNode<Node extends BSTNode<Node,T>,T>
extends BinaryTreeNode<Node> {
/**
* The key stored at this node
*/
T x;
}
CountdownTree.java
package comp2402a5;
import java.util.Random;
import java.util.SortedSet;
import java.util.TreeSet;
/**
* An unfinished implementation of an Countdown tree (for exercises)
*
* @param <T>
*/
public class CountdownTree<T> extends
BinarySearchTree<CountdownTree.Node<T>, T> implements SSet<T> {
// countdown delay factor
double d;
public static class Node<T> extends BSTNode<Node<T>,T> {
int timer; // the height of the node
}
public CountdownTree(double d) {
this.d = d;
sampleNode = new Node<T>();
c = new DefaultComparator<T>();
}
public boolean add(T x) {
Node<T> u = new Node<T>();
u.timer = (int)Math.ceil(d);
u.x = x;
if (super.add(u)) {
// add some code here
return true;
}
return false;
}
public void splice(Node<T> u) {
Node<T> w = u.parent;
super.splice(u);
// add some code here (we just removed u from the tree
}
protected void explode(Node<T> u) {
// Write this code to explode u
// Make sure to update u.parent and/or r (the tree root) as appropriate
}
// Here is some test code you can use
public static void main(String[] args) {
Testum.sortedSetSanityTests(new SortedSSet<Integer>(new CountdownTree<Integer>(1)), 1000);
Testum.sortedSetSanityTests(new SortedSSet<Integer>(new CountdownTree<Integer>(2.5)), 1000);
Testum.sortedSetSanityTests(new SortedSSet<Integer>(new CountdownTree<Integer>(0.5)), 1000);
java.util.List<SortedSet<Integer>> ell = new java.util.ArrayList<SortedSet<Integer>>();
ell.add(new java.util.TreeSet<Integer>());
ell.add(new SortedSSet<Integer>(new CountdownTree<Integer>(1)));
ell.add(new SortedSSet<Integer>(new CountdownTree<Integer>(2.5)));
ell.add(new SortedSSet<Integer>(new CountdownTree<Integer>(0.5)));
Testum.sortedSetSpeedTests(ell, 1000000);
}
}
DefaultComparator.java
package comp2402a5;
import java.util.Comparator;
class DefaultComparator<T> implements Comparator<T> {
@SuppressWarnings(“unchecked”)
public int compare(T a, T b) {
return ((Comparable<T>)a).compareTo(b);
}
}
RangeSSet.java
package comp2402a5;
import java.util.Comparator;
import java.util.Iterator;
import java.util.NoSuchElementException;
import java.util.SortedSet;
/**
* This represents a view of the part of a SortedSSet in the interval [a,b).
* This implementation adds only a constant additive overhead to methods except
* size(), which runs in linear time.
*
* @param <T>
*/
public class RangeSSet<T> extends SortedSSet<T> {
T a;
T b;
public RangeSSet(SSet<T> s, T a, T b) {
super(s);
this.a = a;
this.b = b;
}
public Iterator<T> iterator() {
class IT implements Iterator<T> {
protected Iterator<T> it;
T next, prev;
public IT(Iterator<T> it) {
this.it = it;
if (it.hasNext()) {
next = it.next();
}
}
public boolean hasNext() {
return next != null
&& (b == null || s.comparator().compare(next, b) < 0);
}
public T next() {
if (!hasNext())
throw new NoSuchElementException();
prev = next;
next = it.next();
return prev;
}
public void remove() {
s.remove(prev);
}
}
return new IT(s.iterator(a));
}
@SuppressWarnings(“unchecked”)
public boolean contains(Object o) {
T x = (T) o;
Comparator<? super T> c = s.comparator();
if (a != null && c.compare(x, a) < 0)
return false;
if (b != null && c.compare(x, b) >= 0)
return false;
return super.contains(x);
}
public T first() {
return s.findGE(a);
}
public int size() {
Iterator<T> it = iterator();
int n = 0;
while (it.hasNext()) {
it.next();
n++;
}
return n;
}
public T last() {
return s.findLT(b);
}
protected final T max(T x, T y) {
if (x == null)
return y;
if (y == null)
return x;
if (s.comparator().compare(x, y) > 0)
return x;
return y;
}
protected final T min(T x, T y) {
if (x == null)
return y;
if (y == null)
return x;
if (s.comparator().compare(x, y) < 0)
return x;
return y;
}
protected final void rangeCheck(T x) {
Comparator<? super T> c = s.comparator();
if ((a != null && c.compare(x, a) < 0)
|| (b != null && c.compare(x, b) >= 0))
throw new IllegalArgumentException();
}
public boolean add(T x) {
rangeCheck(x);
return super.add(x);
}
@SuppressWarnings(“unchecked”)
public boolean remove(Object x) {
rangeCheck((T) x);
return super.remove(x);
}
public SortedSet<T> subSet(T a, T b) {
return new RangeSSet<T>(s, max(a, this.a), min(b, this.b));
}
public SortedSet<T> headSet(T b) {
return subSet(a, b);
}
public SortedSet<T> tailSet(T a) {
return subSet(a, b);
}
}
SortedSSet.java
package comp2402a5;
import java.util.AbstractSet;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Comparator;
import java.util.Iterator;
import java.util.SortedSet;
/**
* This class is a wrapper that allows any class that implements SSet<T> to
* allow it to also implement SortedSet<T>.
* @param <T>
*/
public class SortedSSet<T> extends AbstractSet<T> implements SortedSet<T> {
protected SSet<T> s;
public SortedSSet(SSet<T> s) {
this.s = s;
}
public Comparator<? super T> comparator() {
return s.comparator();
}
public T first() {
return s.findGE(null);
}
public T last() {
return s.findLT(null);
}
public SortedSet<T> headSet(T b) {
return new RangeSSet<T>(s, null, b);
}
public SortedSet<T> subSet(T a, T b) {
return new RangeSSet<T>(s, a, b);
}
public SortedSet<T> tailSet(T a) {
return new RangeSSet<T>(s, a, null);
}
public boolean add(T x) {
return s.add(x);
}
public void clear() {
s.clear();
}
@SuppressWarnings(“unchecked”)
public boolean contains(Object o) {
T y = s.findGE((T) o);
return y != null && y.equals(o);
}
public Iterator<T> iterator() {
return s.iterator();
}
@SuppressWarnings(“unchecked”)
public boolean remove(Object x) {
return s.remove((T) x);
}
public int size() {
return s.size();
}
public boolean isEmpty() {
return !s.iterator().hasNext();
}
}
SSet.java
package comp2402a5;
import java.util.Comparator;
import java.util.Iterator;
/**
* The SSet<T> interface is a simple interface that allows a class to implement
* all the functionality of the (more complicated) SortedSet<T> interface. Any
* class that implements SSet<T> can be wrapped in a SortedSSet<T> to obtain an
* implementation of SortedSet<T>
*
* @author morin
*
* @param <T>
* @see SortedSSet<T>
*/
public interface SSet<T> extends Iterable<T> {
/**
* @return the comparator used by this SSet
*/
public Comparator<? super T> comparator();
/**
* @return the number of elements in this SSet
*/
public int size();
/**
* Find the smallest element in the SSet that is greater than or equal to x.
* If x is null, return the smallest element in the SSet
*
* @param x
* @return the smallest element in the SSet that is greater than or equal to
* x. If x is null then the smallest element in the SSet
*/
public T findGE(T x);
/**
* Find the largest element in the SSet that is greater than to x. If x is
* null, return the largest element in the SSet
*
* @param x
* @return the largest element in the SSet that is less than x. If x is null
* then the smallest element in the SSet
*/
public T findLT(T x);
/**
* Add the element x to the SSet
*
* @param x
* @return true if the element was added or false if x was already in the
* set
*/
public boolean add(T x);
/**
* Remove the element x from the SSet
*
* @param x
* @return true if x was removed and false if x was not removed (because x
* was not present)
*/
public boolean remove(T x);
/**
* Clear the SSet, removing all elements from the set
*/
public void clear();
/**
* Return an iterator that iterates over the elements in sorted order,
* starting at the first element that is greater than or equal to x.
*/
public Iterator<T> iterator(T x);
}
Testum.java
package comp2402a5;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Random;
import java.util.Set;
import java.util.SortedSet;
import java.util.TreeSet;
/**
* A utility class with some static methods for testing List implementations
* @author morin
*/
public class Testum {
protected static void myassert(boolean b) throws AssertionError {
if (!b) {
throw new AssertionError();
}
}
protected static String s(Object c) {
return c.getClass().getName();
}
public static void sortedSetSanityTests(SortedSet<Integer> ss, int n) {
SortedSet<Integer> ts = new TreeSet<Integer>();
ss.clear();
Random r = new Random();
for (int i = 0; i < n; i++) {
Integer x = r.nextInt(2*n);
if (ts.add(x) != ss.add(x))
throw new RuntimeException(“add(x) returned wrong value”);
if (!compareSortedSets(ts,ss))
throw new RuntimeException(“sorted sets differ!”);
}
for (int i = 0; i < n; i++) {
Integer x = r.nextInt(2*n);
if (ts.remove(x) != ss.remove(x))
throw new RuntimeException(“remove(x) returned wrong value”);
if (!compareSortedSets(ts,ss))
throw new RuntimeException(“sorted sets differ!”);
}
ss.clear();
ts.clear();
compareSortedSets(ts,ss);
}
public static void sortedSetSpeedTests(Collection<SortedSet<Integer>> css, int n) {
long start, stop;
for (SortedSet<Integer> ss : css) {
ss.clear();
myassert(ss.size() == 0);
}
for (SortedSet<Integer> ss : css) {
System.out.print(“random insertions (” + s(ss) + “)…”);
start = System.nanoTime();
Random r = new Random();
for (int i = 0; i < n; i++)
ss.add(r.nextInt(2*n));
stop = System.nanoTime();
System.out.println(” ” + (1e-9 * (stop – start)) + ” seconds”);
myassert(ss.size() >= n/2);
}
System.out.println();
for (SortedSet<Integer> ss : css) {
System.out.print(“random contains (” + s(ss) + “)…”);
start = System.nanoTime();
Random r = new Random();
for (int i = 0; i < 2*n; i++)
ss.contains(r.nextInt(2*n));
stop = System.nanoTime();
System.out.println(” ” + (1e-9 * (stop – start)) + ” seconds”);
}
System.out.println();
for (SortedSet<Integer> ss : css) {
System.out.print(“random removals (” + s(ss) + “)…”);
start = System.nanoTime();
Random r = new Random();
for (int i = 0; i < 2*n; i++)
ss.remove(r.nextInt(2*n));
stop = System.nanoTime();
System.out.println(” ” + (1e-9 * (stop – start)) + ” seconds”);
}
System.out.println();
for (SortedSet<Integer> ss : css) {
System.out.print(“random headSets (” + s(ss) + “)…”);
start = System.nanoTime();
Random r = new Random();
for (int i = 0; i < n; i++) {
ss.headSet(r.nextInt(2*n));
Iterator<Integer> it = ss.iterator();
if (it.hasNext()) it.next();
}
stop = System.nanoTime();
System.out.println(” ” + (1e-9 * (stop – start)) + ” seconds”);
}
System.out.println();
for (SortedSet<Integer> ss : css) {
System.out.print(“iteration (” + s(ss) + “)…”);
start = System.nanoTime();
for (Integer i : ss) { i = i + 1; }
stop = System.nanoTime();
System.out.println(” ” + (1e-9 * (stop – start)) + ” seconds”);
}
System.out.println();
for (SortedSet<Integer> ss : css) {
System.out.print(“clear (” + s(ss) + “)…”);
start = System.nanoTime();
ss.clear();
stop = System.nanoTime();
System.out.println(” ” + (1e-9 * (stop – start)) + ” seconds”);
}
System.out.println();
for (SortedSet<Integer> ss : css) {
System.out.print(“sequential insertions (” + s(ss) + “)…”);
start = System.nanoTime();
for (int i = 0; i < n; i++) {
myassert(ss.size() == i);
ss.add(i*2);
}
stop = System.nanoTime();
System.out.println(” ” + (1e-9 * (stop – start)) + ” seconds”);
myassert(ss.size() == n);
}
System.out.println();
for (SortedSet<Integer> ss : css) {
System.out.print(“sequential contains (” + s(ss) + “)…”);
start = System.nanoTime();
for (int i = 0; i < 2*n; i++)
ss.contains(i);
stop = System.nanoTime();
System.out.println(” ” + (1e-9 * (stop – start)) + ” seconds”);
}
System.out.println();
for (SortedSet<Integer> ss : css) {
System.out.print(“sequential headSets (” + s(ss) + “)…”);
start = System.nanoTime();
for (int i = 0; i < 2*n; i++)
ss.headSet(i);
stop = System.nanoTime();
System.out.println(” ” + (1e-9 * (stop – start)) + ” seconds”);
}
System.out.println();
for (SortedSet<Integer> ss : css) {
System.out.print(“iteration over subSets (” + s(ss) + “)…”);
start = System.nanoTime();
for (Integer i : ss.subSet(n/2, 3*n/4)) { i = i + 1; }
stop = System.nanoTime();
System.out.println(” ” + (1e-9 * (stop – start)) + ” seconds”);
}
System.out.println();
}
protected static <T> boolean compareSortedSets(Collection<T> a, Collection<T> b) {
if (a.size() != b.size())
return false;
for (T x : a) {
if (!b.contains(x)) return false;
}
for (T x : b) {
if (!a.contains(x)) return false;
}
Iterator<T> ita = a.iterator();
Iterator<T> itb = b.iterator();
while (ita.hasNext()) {
if (!ita.next().equals(itb.next()))
return false;
}
return true;
}
}
Solution
BinarySearchTree.java
package comp2402a5;
import java.util.Collection;
import java.util.Comparator;
import java.util.Iterator;
public class BinarySearchTree<Node extends BSTNode<Node,T>, T> extends
BinaryTree<Node> implements SSet<T> {
public Comparator<T> c;
/**
* The number of nodes (elements) currently in the tree
*/
public int n;
public Node newNode(T x) {
Node u = super.newNode();
u.x = x;
return u;
}
public BinarySearchTree(Node is, Comparator<T> c) {
super(is);
this.c = c;
}
public BinarySearchTree(Node is) {
this(is, new DefaultComparator<T>());
}
/**
* Create a new instance of this class
* @warning child must set sampleNode before anything that
* might make calls to newNode()
*/
public BinarySearchTree() {
this(null, new DefaultComparator<T>());
}
/**
* Search for a value in the tree
* @return the last node on the search path for x
*/
public Node findLast(T x) {
Node w = r, prev = nil;
while (w != nil) {
prev = w;
int comp = c.compare(x, w.x);
if (comp < 0) {
w = w.left;
} else if (comp > 0) {
w = w.right;
} else {
return w;
}
}
return prev;
}
/**
* Search for a value in the tree
* @return the last node on the search path for x
*/
public Node findGENode(T x) {
Node w = r, z = nil;
while (w != nil) {
int comp = c.compare(x, w.x);
if (comp < 0) {
z = w;
w = w.left;
} else if (comp > 0) {
w = w.right;
} else {
return w;
}
}
return z;
}
public T findEQ(T x) {
Node u = r;
while (u != nil) {
int comp = c.compare(x, u.x);
if (comp < 0)
u = u.left;
else if (comp > 0)
u = u.right;
else
return u.x;
}
return null;
}
public T find(T x) {
Node w = r, z = nil;
while (w != nil) {
int comp = c.compare(x, w.x);
if (comp < 0) {
z = w;
w = w.left;
} else if (comp > 0) {
w = w.right;
} else {
return w.x;
}
}
return z == nil ? null : z.x;
}
public T findGE(T u) {
if (u == null) { // find the minimum value
Node w = r;
if (w == nil) return null;
while (w.left != nil)
w = w.left;
return w.x;
}
Node w = findGENode(u);
return w == nil ? null : w.x;
}
/**
* Search for a value in the tree
* @return the last node on the search path for x
*/
public Node findLTNode(T x) {
Node u = r, z = nil;
while (u != nil) {
int comp = c.compare(x, u.x);
if (comp < 0) {
u = u.left;
} else if (comp > 0) {
z = u;
u = u.right;
} else {
return u;
}
}
return z;
}
public T findLT(T x) {
if (x == null) { // find the maximum value
Node w = r;
if (w == nil) return null;
while (w.right != nil)
w = w.right;
return w.x;
}
Node w = findLTNode(x);
return w == nil ? null : w.x;
}
/**
* Add the node u as a child of node p — ASSUMES p has no child
* where u should be added
* @param p
* @param u
* @return true if the child was added, false otherwise
*/
public boolean addChild(Node p, Node u) {
if (p == nil) {
r = u; // inserting into empty tree
} else {
int comp = c.compare(u.x, p.x);
if (comp < 0) {
p.left = u;
} else if (comp > 0) {
p.right = u;
} else {
return false; // u.x is already in the tree
}
u.parent = p;
}
n++;
return true;
}
/**
* Add a new value
* @param x
* @return
*/
public boolean add(T x) {
Node p = findLast(x);
return addChild(p, newNode(x));
}
/**
* Add a new value
* @param x
* @return
*/
public boolean add(Node u) {
Node p = findLast(u.x);
return addChild(p, u);
}
/**
* Remove the node u — ASSUMING u has at most one child
* @param u
*/
public void splice(Node u) {
Node s, p;
if (u.left != nil) {
s = u.left;
} else {
s = u.right;
}
if (u == r) {
r = s;
p = nil;
} else {
p = u.parent;
if (p.left == u) {
p.left = s;
} else {
p.right = s;
}
}
if (s != nil) {
s.parent = p;
}
n–;
}
/**
* Remove the node u from the binary search tree
* @param u
*/
public void remove(Node u) {
if (u.left == nil || u.right == nil) {
splice(u);
} else {
Node w = u.right;
while (w.left != nil)
w = w.left;
u.x = w.x;
splice(w);
}
}
/**
* Do a left rotation at u
* @param u
*/
public void rotateLeft(Node u) {
Node w = u.right;
w.parent = u.parent;
if (w.parent != nil) {
if (w.parent.left == u) {
w.parent.left = w;
} else {
w.parent.right = w;
}
}
u.right = w.left;
if (u.right != nil) {
u.right.parent = u;
}
u.parent = w;
w.left = u;
if (u == r) { r = w; r.parent = nil; }
}
/**
* Do a right rotation at u
* @param u
*/
public void rotateRight(Node u) {
Node w = u.left;
w.parent = u.parent;
if (w.parent != nil) {
if (w.parent.left == u) {
w.parent.left = w;
} else {
w.parent.right = w;
}
}
u.left = w.right;
if (u.left != nil) {
u.left.parent = u;
}
u.parent = w;
w.right = u;
if (u == r) { r = w; r.parent = nil; }
}
/**
* Remove a node
* @param x
* @return
*/
public boolean remove(T x) {
Node u = findLast(x);
if (u != nil && c.compare(x,u.x) == 0) {
remove(u);
return true;
}
return false;
}
public String toString() {
String s = “[“;
Iterator<T> it = iterator();
while (it.hasNext()) {
s += it.next().toString() + (it.hasNext() ? “,” : “”);
}
s += “]”;
return s;
}
@SuppressWarnings({“unchecked”})
public boolean contains(Object x) {
Node u = findLast((T)x);
return u != nil && c.compare(u.x, (T)x) == 0;
}
public boolean containsAll(Collection<?> c) {
for (Object x : c)
if (!contains(x))
return false;
return true;
}
public Iterator<T> iterator(Node u) {
class BTI implements Iterator<T> {
public Node w, prev;
public BTI(Node iw) {
w = iw;
}
public boolean hasNext() {
return w != nil;
}
public T next() {
T x = w.x;
prev = w;
w = nextNode(w);
return x;
}
public void remove() {
// FIXME: This is a bug. remove() methods have to be changed
BinarySearchTree.this.remove(prev);
}
}
return new BTI(u);
}
public Iterator<T> iterator() {
return iterator(firstNode());
}
public Iterator<T> iterator(T x) {
return iterator(findGENode(x));
}
public int size() {
return n;
}
public boolean isEmpty() {
return n == 0;
}
public void clear() {
super.clear();
n = 0;
}
public Comparator<? super T> comparator() {
return c;
}
}
BinaryTree.java
package comp2402a5;
import java.util.LinkedList;
import java.util.Queue;
import java.util.Random;
public class BinaryTree<Node extends BinaryTreeNode<Node>> {
/**
* Used to make a mini-factory
*/
public Node sampleNode;
/**
* The root of this tree
*/
public Node r;
/**
* This tree’s null node
*/
public Node nil;
/**
* Create a new instance of this class
* @param isampleNode
*/
public BinaryTree(Node nil) {
sampleNode = nil;
this.nil = null;
}
/**
* Create a new instance of this class
* @warning child must set sampleNode before anything that
* might make calls to newNode()
*/
public BinaryTree() { }
/**
* Allocate a new node for use in this tree
* @return
*/
@SuppressWarnings({“unchecked”})
public Node newNode() {
try {
Node u = (Node)sampleNode.getClass().newInstance();
u.parent = u.left = u.right = nil;
return u;
} catch (Exception e) {
return null;
}
}
public int depth(Node u) {
int d = 0;
while (u != r) {
u = u.parent;
d++;
}
return d;
}
/**
* Compute the size (number of nodes) of this tree
* @return the number of nodes in this tree
*/
public int size() {
return size(r);
}
/**
* @return the size of the subtree rooted at u
*/
public int size(Node u) {
if (u == nil)
return 0;
return 1 + size(u.left) + size(u.right);
}
public int height() {
return height(r);
}
/**
* @return the size of the subtree rooted at u
*/
public int height(Node u) {
if (u == nil)
return -1;
return 1 + Math.max(height(u.left), height(u.right));
}
/**
* @return
*/
public boolean isEmpty() {
return r == nil;
}
/**
* Make this tree into the empty tree
*/
public void clear() {
r = nil;
}
public void traverse(Node u) {
if (u == nil) return;
traverse(u.left);
traverse(u.right);
}
public void traverse2() {
Node u = r, prev = nil, next;
while (u != nil) {
if (prev == u.parent) {
if (u.left != nil) next = u.left;
else if (u.right != nil) next = u.right;
else next = u.parent;
} else if (prev == u.left) {
if (u.right != nil) next = u.right;
else next = u.parent;
} else {
next = u.parent;
}
prev = u;
u = next;
}
}
public int size2() {
Node u = r, prev = nil, next;
int n = 0;
while (u != nil) {
if (prev == u.parent) {
n++;
if (u.left != nil) next = u.left;
else if (u.right != nil) next = u.right;
else next = u.parent;
} else if (prev == u.left) {
if (u.right != nil) next = u.right;
else next = u.parent;
} else {
next = u.parent;
}
prev = u;
u = next;
}
return n;
}
public void bfTraverse() {
Queue<Node> q = new LinkedList<Node>();
q.add(r);
while (!q.isEmpty()) {
Node u = q.remove();
if (u.left != nil) q.add(u.left);
if (u.right != nil) q.add(u.right);
}
}
/**
* Find the first node in an in-order traversal
* @return
*/
public Node firstNode() {
Node w = r;
if (w == nil) return nil;
while (w.left != nil)
w = w.left;
return w;
}
/**
* Find the node that follows u in an in-order traversal
* @param w
* @return
*/
public Node nextNode(Node w) {
if (w.right != nil) {
w = w.right;
while (w.left != nil)
w = w.left;
} else {
while (w.parent != nil && w.parent.left != w)
w = w.parent;
w = w.parent;
}
return w;
}
public static <Node extends BinaryTreeNode<Node>> void completeBinaryTree(BinaryTree<Node> t, int n) {
Queue<Node> q = new LinkedList<Node>();
t.clear();
if (n == 0)
return;
t.r = t.newNode();
q.add(t.r);
while (–n > 0) {
Node u = q.remove();
u.left = t.newNode();
u.left.parent = u;
q.add(u.left);
if (–n > 0) {
u.right = t.newNode();
u.right.parent = u;
q.add(u.right);
}
}
}
/**
* Create a new full binary tree whose expected number of nodes is n
* @param <Node>
* @param t
* @param n
*/
public static <Node extends BinaryTreeNode<Node>> void galtonWatsonFullTree(BinaryTree<Node> t, int n) {
Random r = new Random();
Queue<Node> q = new LinkedList<Node>();
t.clear();
t.r = t.newNode();
q.add(t.r);
double p = ((double)0.5 – ((double)1)/(n+n));
while (!q.isEmpty()) {
Node u = q.remove();
if (r.nextDouble() < p) {
u.left = t.newNode();
u.left.parent = u;
q.add(u.left);
u.right = t.newNode();
u.right.parent = u;
q.add(u.right);
}
}
}
static <Node extends BinaryTreeNode<Node>> void galtonWatsonTree(BinaryTree<Node> t, int n) {
Random r = new Random();
Queue<Node> q = new LinkedList<Node>();
t.clear();
t.r = t.newNode();
q.add(t.r);
double p = ((double)0.5 – ((double)1)/(n+n));
while (!q.isEmpty()) {
Node u = q.remove();
if (r.nextDouble() < p) {
u.left = t.newNode();
u.left.parent = u;
q.add(u.left);
} if (r.nextDouble() < p) {
u.right = t.newNode();
u.right.parent = u;
q.add(u.right);
}
}
}
}
BinaryTreeNode.java
package comp2402a5;
/**
* This class represents a node in a binary tree. This class is abstract and
* should be subclassed by a concrete class. See, for example the class
* SimpleBinaryTreeNode.
* @param <Node>
* the class of the children of this node
*/
public class BinaryTreeNode<Node extends BinaryTreeNode<Node>> {
public Node left;
public Node right;
public Node parent;
}
BSTNode.java
package comp2402a5;
public class BSTNode<Node extends BSTNode<Node,T>,T>
extends BinaryTreeNode<Node> {
/**
* The key stored at this node
*/
T x;
}
CountdownTree.java
package comp2402a5;
import java.lang.reflect.Array;
import java.util.Random;
import java.util.SortedSet;
import java.util.TreeSet;
/**
* An unfinished implementation of an Countdown tree (for exercises)
*
* @author morin
*
* @param <T>
*/
public class CountdownTree<T> extends BinarySearchTree<CountdownTree.Node<T>, T> implements SSet<T> {
// countdown delay factor
double d;
public static class Node<T> extends BSTNode<Node<T>, T> {
int timer; // the height of the node
}
public CountdownTree(double d) {
this.d = d;
sampleNode = new Node<T>();
c = new DefaultComparator<T>();
}
public boolean add(T x) {
Node<T> u = new Node<T>();
u.timer = (int) Math.ceil(d);
u.x = x;
if (super.add(u)) {
// add some code here
u = u.parent;
while (u != nil) {
u.timer–;
if (u.timer == 0) {
this.explode(u);
}
u = u.parent; // iterate
}
return true;
}
return false;
}
public void splice(Node<T> u) {
Node<T> w = u.parent;
super.splice(u);
// add some code here (we just removed u from the tree
while (w != nil) {
w.timer–;
if (w.timer == 0) {
this.explode(w);
}
w = w.parent; // iterate
}
}
protected void explode(Node<T> u) {
// Write this code to explode u
// Make sure to update u.parent and/or r (the tree root) as appropriate
int ns = size(u);
Node<T> p = u.parent;
@SuppressWarnings(“unchecked”)
Node<T>[] a = (Node<T>[]) Array.newInstance(Node.class, ns);
packIntoArray(u, a, 0);
if (p == nil) {
r = buildBalanced(a, 0, ns);
r.parent = nil;
} else if (p.right == u) {
p.right = buildBalanced(a, 0, ns);
p.right.parent = p;
} else {
p.left = buildBalanced(a, 0, ns);
p.left.parent = p;
}
}
int packIntoArray(Node<T> u, Node<T>[] a, int i) {
if (u == nil) {
return i;
}
i = packIntoArray(u.left, a, i);
a[i++] = u;
return packIntoArray(u.right, a, i);
}
Node<T> buildBalanced(Node<T>[] a, int i, int ns) {
if (ns == 0)
return nil;
int m = ns / 2;
a[i + m].left = buildBalanced(a, i, m);
if (a[i + m].left != nil)
a[i + m].left.parent = a[i + m];
a[i + m].right = buildBalanced(a, i + m + 1, ns – m – 1);
if (a[i + m].right != nil)
a[i + m].right.parent = a[i + m];
a[i + m].timer = (int) Math.ceil(d * size(a[i + m]));
return a[i + m];
}
// Here is some test code you can use
public static void main(String[] args) {
Testum.sortedSetSanityTests(new SortedSSet<Integer>(new CountdownTree<Integer>(1)), 1000);
Testum.sortedSetSanityTests(new SortedSSet<Integer>(new CountdownTree<Integer>(2.5)), 1000);
Testum.sortedSetSanityTests(new SortedSSet<Integer>(new CountdownTree<Integer>(0.5)), 1000);
java.util.List<SortedSet<Integer>> ell = new java.util.ArrayList<SortedSet<Integer>>();
ell.add(new java.util.TreeSet<Integer>());
ell.add(new SortedSSet<Integer>(new CountdownTree<Integer>(1)));
ell.add(new SortedSSet<Integer>(new CountdownTree<Integer>(2.5)));
ell.add(new SortedSSet<Integer>(new CountdownTree<Integer>(0.5)));
Testum.sortedSetSpeedTests(ell, 1000000);
}
}
DefaultComparator.java
package comp2402a5;
import java.util.Comparator;
class DefaultComparator<T> implements Comparator<T> {
@SuppressWarnings(“unchecked”)
public int compare(T a, T b) {
return ((Comparable<T>)a).compareTo(b);
}
}
RangeSSet.java
package comp2402a5;
import java.util.Comparator;
import java.util.Iterator;
import java.util.NoSuchElementException;
import java.util.SortedSet;
/**
* This represents a view of the part of a SortedSSet in the interval [a,b).
* This implementation adds only a constant additive overhead to methods except
* size(), which runs in linear time.
* @param <T>
*/
public class RangeSSet<T> extends SortedSSet<T> {
T a;
T b;
public RangeSSet(SSet<T> s, T a, T b) {
super(s);
this.a = a;
this.b = b;
}
public Iterator<T> iterator() {
class IT implements Iterator<T> {
protected Iterator<T> it;
T next, prev;
public IT(Iterator<T> it) {
this.it = it;
if (it.hasNext()) {
next = it.next();
}
}
public boolean hasNext() {
return next != null
&& (b == null || s.comparator().compare(next, b) < 0);
}
public T next() {
if (!hasNext())
throw new NoSuchElementException();
prev = next;
next = it.next();
return prev;
}
public void remove() {
s.remove(prev);
}
}
return new IT(s.iterator(a));
}
@SuppressWarnings(“unchecked”)
public boolean contains(Object o) {
T x = (T) o;
Comparator<? super T> c = s.comparator();
if (a != null && c.compare(x, a) < 0)
return false;
if (b != null && c.compare(x, b) >= 0)
return false;
return super.contains(x);
}
public T first() {
return s.findGE(a);
}
public int size() {
Iterator<T> it = iterator();
int n = 0;
while (it.hasNext()) {
it.next();
n++;
}
return n;
}
public T last() {
return s.findLT(b);
}
protected final T max(T x, T y) {
if (x == null)
return y;
if (y == null)
return x;
if (s.comparator().compare(x, y) > 0)
return x;
return y;
}
protected final T min(T x, T y) {
if (x == null)
return y;
if (y == null)
return x;
if (s.comparator().compare(x, y) < 0)
return x;
return y;
}
protected final void rangeCheck(T x) {
Comparator<? super T> c = s.comparator();
if ((a != null && c.compare(x, a) < 0)
|| (b != null && c.compare(x, b) >= 0))
throw new IllegalArgumentException();
}
public boolean add(T x) {
rangeCheck(x);
return super.add(x);
}
@SuppressWarnings(“unchecked”)
public boolean remove(Object x) {
rangeCheck((T) x);
return super.remove(x);
}
public SortedSet<T> subSet(T a, T b) {
return new RangeSSet<T>(s, max(a, this.a), min(b, this.b));
}
public SortedSet<T> headSet(T b) {
return subSet(a, b);
}
public SortedSet<T> tailSet(T a) {
return subSet(a, b);
}
}
SortedSSet.java
package comp2402a5;
import java.util.AbstractSet;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Comparator;
import java.util.Iterator;
import java.util.SortedSet;
/**
* This class is a wrapper that allows any class that implements SSet<T> to
* allow it to also implement SortedSet<T>.
* @param <T>
*/
public class SortedSSet<T> extends AbstractSet<T> implements SortedSet<T> {
protected SSet<T> s;
public SortedSSet(SSet<T> s) {
this.s = s;
}
public Comparator<? super T> comparator() {
return s.comparator();
}
public T first() {
return s.findGE(null);
}
public T last() {
return s.findLT(null);
}
public SortedSet<T> headSet(T b) {
return new RangeSSet<T>(s, null, b);
}
public SortedSet<T> subSet(T a, T b) {
return new RangeSSet<T>(s, a, b);
}
public SortedSet<T> tailSet(T a) {
return new RangeSSet<T>(s, a, null);
}
public boolean add(T x) {
return s.add(x);
}
public void clear() {
s.clear();
}
@SuppressWarnings(“unchecked”)
public boolean contains(Object o) {
T y = s.findGE((T) o);
return y != null && y.equals(o);
}
public Iterator<T> iterator() {
return s.iterator();
}
@SuppressWarnings(“unchecked”)
public boolean remove(Object x) {
return s.remove((T) x);
}
public int size() {
return s.size();
}
public boolean isEmpty() {
return !s.iterator().hasNext();
}
}
SSet.java
package comp2402a5;
import java.util.Comparator;
import java.util.Iterator;
/**
* The SSet<T> interface is a simple interface that allows a class to implement
* all the functionality of the (more complicated) SortedSet<T> interface. Any
* class that implements SSet<T> can be wrapped in a SortedSSet<T> to obtain an
* implementation of SortedSet<T>
*
* @author morin
*
* @param <T>
* @see SortedSSet<T>
*/
public interface SSet<T> extends Iterable<T> {
/**
* @return the comparator used by this SSet
*/
public Comparator<? super T> comparator();
/**
* @return the number of elements in this SSet
*/
public int size();
/**
* Find the smallest element in the SSet that is greater than or equal to x.
* If x is null, return the smallest element in the SSet
*
* @param x
* @return the smallest element in the SSet that is greater than or equal to
* x. If x is null then the smallest element in the SSet
*/
public T findGE(T x);
/**
* Find the largest element in the SSet that is greater than to x. If x is
* null, return the largest element in the SSet
*
* @param x
* @return the largest element in the SSet that is less than x. If x is null
* then the smallest element in the SSet
*/
public T findLT(T x);
/**
* Add the element x to the SSet
*
* @param x
* @return true if the element was added or false if x was already in the
* set
*/
public boolean add(T x);
/**
* Remove the element x from the SSet
*
* @param x
* @return true if x was removed and false if x was not removed (because x
* was not present)
*/
public boolean remove(T x);
/**
* Clear the SSet, removing all elements from the set
*/
public void clear();
/**
* Return an iterator that iterates over the elements in sorted order,
* starting at the first element that is greater than or equal to x.
*/
public Iterator<T> iterator(T x);
}
Testum.java
package comp2402a5;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Random;
import java.util.Set;
import java.util.SortedSet;
import java.util.TreeSet;
/**
* A utility class with some static methods for testing List implementations
*/
public class Testum {
protected static void myassert(boolean b) throws AssertionError {
if (!b) {
throw new AssertionError();
}
}
protected static String s(Object c) {
return c.getClass().getName();
}
public static void sortedSetSanityTests(SortedSet<Integer> ss, int n) {
SortedSet<Integer> ts = new TreeSet<Integer>();
ss.clear();
Random r = new Random();
for (int i = 0; i < n; i++) {
Integer x = r.nextInt(2*n);
if (ts.add(x) != ss.add(x))
throw new RuntimeException(“add(x) returned wrong value”);
if (!compareSortedSets(ts,ss))
throw new RuntimeException(“sorted sets differ!”);
}
for (int i = 0; i < n; i++) {
Integer x = r.nextInt(2*n);
if (ts.remove(x) != ss.remove(x))
throw new RuntimeException(“remove(x) returned wrong value”);
if (!compareSortedSets(ts,ss))
throw new RuntimeException(“sorted sets differ!”);
}
ss.clear();
ts.clear();
compareSortedSets(ts,ss);
}
public static void sortedSetSpeedTests(Collection<SortedSet<Integer>> css, int n) {
long start, stop;
for (SortedSet<Integer> ss : css) {
ss.clear();
myassert(ss.size() == 0);
}
for (SortedSet<Integer> ss : css) {
System.out.print(“random insertions (” + s(ss) + “)…”);
start = System.nanoTime();
Random r = new Random();
for (int i = 0; i < n; i++)
ss.add(r.nextInt(2*n));
stop = System.nanoTime();
System.out.println(” ” + (1e-9 * (stop – start)) + ” seconds”);
myassert(ss.size() >= n/2);
}
System.out.println();
for (SortedSet<Integer> ss : css) {
System.out.print(“random contains (” + s(ss) + “)…”);
start = System.nanoTime();
Random r = new Random();
for (int i = 0; i < 2*n; i++)
ss.contains(r.nextInt(2*n));
stop = System.nanoTime();
System.out.println(” ” + (1e-9 * (stop – start)) + ” seconds”);
}
System.out.println();
for (SortedSet<Integer> ss : css) {
System.out.print(“random removals (” + s(ss) + “)…”);
start = System.nanoTime();
Random r = new Random();
for (int i = 0; i < 2*n; i++)
ss.remove(r.nextInt(2*n));
stop = System.nanoTime();
System.out.println(” ” + (1e-9 * (stop – start)) + ” seconds”);
}
System.out.println();
for (SortedSet<Integer> ss : css) {
System.out.print(“random headSets (” + s(ss) + “)…”);
start = System.nanoTime();
Random r = new Random();
for (int i = 0; i < n; i++) {
ss.headSet(r.nextInt(2*n));
Iterator<Integer> it = ss.iterator();
if (it.hasNext()) it.next();
}
stop = System.nanoTime();
System.out.println(” ” + (1e-9 * (stop – start)) + ” seconds”);
}
System.out.println();
for (SortedSet<Integer> ss : css) {
System.out.print(“iteration (” + s(ss) + “)…”);
start = System.nanoTime();
for (Integer i : ss) { i = i + 1; }
stop = System.nanoTime();
System.out.println(” ” + (1e-9 * (stop – start)) + ” seconds”);
}
System.out.println();
for (SortedSet<Integer> ss : css) {
System.out.print(“clear (” + s(ss) + “)…”);
start = System.nanoTime();
ss.clear();
stop = System.nanoTime();
System.out.println(” ” + (1e-9 * (stop – start)) + ” seconds”);
}
System.out.println();
for (SortedSet<Integer> ss : css) {
System.out.print(“sequential insertions (” + s(ss) + “)…”);
start = System.nanoTime();
for (int i = 0; i < n; i++) {
myassert(ss.size() == i);
ss.add(i*2);
}
stop = System.nanoTime();
System.out.println(” ” + (1e-9 * (stop – start)) + ” seconds”);
myassert(ss.size() == n);
}
System.out.println();
for (SortedSet<Integer> ss : css) {
System.out.print(“sequential contains (” + s(ss) + “)…”);
start = System.nanoTime();
for (int i = 0; i < 2*n; i++)
ss.contains(i);
stop = System.nanoTime();
System.out.println(” ” + (1e-9 * (stop – start)) + ” seconds”);
}
System.out.println();
for (SortedSet<Integer> ss : css) {
System.out.print(“sequential headSets (” + s(ss) + “)…”);
start = System.nanoTime();
for (int i = 0; i < 2*n; i++)
ss.headSet(i);
stop = System.nanoTime();
System.out.println(” ” + (1e-9 * (stop – start)) + ” seconds”);
}
System.out.println();
for (SortedSet<Integer> ss : css) {
System.out.print(“iteration over subSets (” + s(ss) + “)…”);
start = System.nanoTime();
for (Integer i : ss.subSet(n/2, 3*n/4)) { i = i + 1; }
stop = System.nanoTime();
System.out.println(” ” + (1e-9 * (stop – start)) + ” seconds”);
}
System.out.println();
}
protected static <T> boolean compareSortedSets(Collection<T> a, Collection<T> b) {
if (a.size() != b.size())
return false;
for (T x : a) {
if (!b.contains(x)) return false;
}
for (T x : b) {
if (!a.contains(x)) return false;
}
Iterator<T> ita = a.iterator();
Iterator<T> itb = b.iterator();
while (ita.hasNext()) {
if (!ita.next().equals(itb.next()))
return false;
}
return true;
}
}