Question: For this project, you will be creating three custom data structures that need to meet certain runtime performance requirements. Youll create two distinct list structures

For this project, you will be creating three custom data structures that need to meet certain

runtime performance requirements. Youll create two distinct list structures (lists that prohibit

duplicates) - one that provides random access and one that provides sequential access. Youll

also create a red-black tree based map structure that has an insertion-order iterator and

methods that provide sorted-order indexed based key access. Your structures must conform to

the java.util.List and java.util.Map interfaces, respectively.

Runtime Performance Requirements

The methods in your distinct random access list implementation must meet the following runtime

performance requirements.

Method Runtime

add (int, E) linear

get constant

contains constant

indexOf linear

set constant

remove (Object) linear

remove (int) linear

The methods in your distinct sequential access list implementation must meet the following

runtime performance requirements.

Method Runtime

add (int, E) linear

get linear

contains constant

indexOf linear

set linear

remove (Object) linear

remove (int) linear

The methods in your red-black tree implementation must meet the following runtime

performance requirements.

Method Runtime

put logarithmic

get logarithmic

indexOf logarithmic

keyAt logarithmic

containsKey logarithmic

Guidance and Supplemental Requirements

The first thing you should do is create the barebones classes that are sufficient for

executing the provided test harnesses.

Your distinct random-access list must implement java.util.RandomAccess.

a TreeMap class that provides a

basic red-black tree implementation. To create this class, the instructor basically copied

the source code of java.util.TreeMap and then removed all functionality thats not

essential for conforming to the java.util.Map interface. This means that the provide

TreeMap class does not implement java.util.NavigableMap or java.util.SortedMap, and

thats okay for this project.

Copy that provided map class and use that as a starting point for your map class.

Thus, you wont have to implement the red-black mechanics yourself for this

project.

Your map must implement the provided IndexedMap and LinkedMap interfaces.

There are a multitude of ways of approaching solutions. Before you start implementing,

try to slow down and consider various approaches. Try to keep your solutions as simple

as possible and re-use existing classes (especially in java.util) where possible; that will

reduce the amount of coding youll have to do.

***Tree Map Class***

public class TreeMap, V>

extends AbstractMap implements Map {

/**

* The RED marker.

*/

private static final boolean RED = false;

/**

* The BLACK marker.

*/

private static final boolean BLACK = true;

/**

* Comparators are not used.

*/

private final Comparator comparator = null;

/**

* The tree root.

*/

private Entry root;

/**

* The set of Entry objects.

*/

private EntrySet entrySet;

/**

* The number of entries in the tree.

*/

private int size = 0;

/**

* The number of structural modifications to the tree.

*/

private int modCount = 0;

/**

* Sole constructor.

*/

public TreeMap() {

super();

}

/* (non-Javadoc)

* @see java.util.AbstractMap#entrySet()

*/

@Override

public Set> entrySet() {

if (entrySet == null)

entrySet = new EntrySet();

return entrySet;

}

/* (non-Javadoc)

* @see java.util.AbstractMap#put(java.lang.Object, java.lang.Object)

*/

@Override

public V put(final K key, final V value) {

Entry t = root;

if (t == null) {

compare(key, key); // type (and possibly null) check

root = new Entry<>(key, value, null);

size = 1;

modCount++;

return null;

}

int cmp;

Entry parent;

if (key == null)

throw new NullPointerException();

Comparable k = (Comparable) key;

do {

parent = t;

cmp = k.compareTo(t.key);

if (cmp < 0)

t = t.left;

else if (cmp > 0)

t = t.right;

else

return t.setValue(value);

} while (t != null);

Entry e = new Entry<>(key, value, parent);

if (cmp < 0)

parent.left = e;

else

parent.right = e;

fixAfterInsertion(e);

size++;

modCount++;

return null;

}

/* (non-Javadoc)

* @see java.util.AbstractMap#size()

*/

@Override

public int size() {

return size;

}

/**

* Removes all of the mappings from this map.

* The map will be empty after this call returns.

*/

public void clear() {

modCount++;

size = 0;

root = null;

}

/**

* Re-balances the tree after an insertion event.

* Algorithm taken from CLR.

* @param entry Rebalancing beging at this node.

*/

private void fixAfterInsertion(final Entry entry) {

Entry x = entry;

x.color = RED;

while (x != null && x != root && x.parent.color == RED) {

if (parentOf(x) == leftOf(parentOf(parentOf(x)))) {

Entry y = rightOf(parentOf(parentOf(x)));

if (colorOf(y) == RED) {

setColor(parentOf(x), BLACK);

setColor(y, BLACK);

setColor(parentOf(parentOf(x)), RED);

x = parentOf(parentOf(x));

} else {

if (x == rightOf(parentOf(x))) {

x = parentOf(x);

rotateLeft(x);

}

setColor(parentOf(x), BLACK);

setColor(parentOf(parentOf(x)), RED);

rotateRight(parentOf(parentOf(x)));

}

} else {

Entry y = leftOf(parentOf(parentOf(x)));

if (colorOf(y) == RED) {

setColor(parentOf(x), BLACK);

setColor(y, BLACK);

setColor(parentOf(parentOf(x)), RED);

x = parentOf(parentOf(x));

} else {

if (x == leftOf(parentOf(x))) {

x = parentOf(x);

rotateRight(x);

}

setColor(parentOf(x), BLACK);

setColor(parentOf(parentOf(x)), RED);

rotateLeft(parentOf(parentOf(x)));

}

}

}

root.color = BLACK;

}

/**

* From CLR.

* @param p The root of the subtree being rotated.

*/

private void rotateLeft(final Entry p) {

if (p != null) {

Entry r = p.right;

p.right = r.left;

if (r.left != null)

r.left.parent = p;

r.parent = p.parent;

if (p.parent == null)

root = r;

else if (p.parent.left == p)

p.parent.left = r;

else

p.parent.right = r;

r.left = p;

p.parent = r;

}

}

/**

* From CLR.

* @param p The root of the subtree being rotated.

*/

private void rotateRight(final Entry p) {

if (p != null) {

Entry l = p.left;

p.left = l.right;

if (l.right != null) l.right.parent = p;

l.parent = p.parent;

if (p.parent == null)

root = l;

else if (p.parent.right == p)

p.parent.right = l;

else p.parent.left = l;

l.right = p;

p.parent = l;

}

}

/**

* Delete node d, and then rebalance the tree.

* @param d The node to delete.

*/

private void deleteEntry(final Entry d) {

Entry p = d;

modCount++;

size--;

// If strictly internal, copy successor's element to p and then make p

// point to successor.

if (p.left != null && p.right != null) {

Entry s = successor(p);

p.key = s.key;

p.value = s.value;

p = s;

} // p has 2 children

// Start fixup at replacement node, if it exists.

Entry replacement = (p.left != null ? p.left : p.right);

if (replacement != null) {

// Link replacement to parent

replacement.parent = p.parent;

if (p.parent == null)

root = replacement;

else if (p == p.parent.left)

p.parent.left = replacement;

else

p.parent.right = replacement;

// Null out links so they are OK to use by fixAfterDeletion.

p.left = null;

p.right = null;

p.parent = null;

// Fix replacement

if (p.color == BLACK)

fixAfterDeletion(replacement);

} else if (p.parent == null) { // return if we are the only node.

root = null;

} else { // No children. Use self as phantom replacement and unlink.

if (p.color == BLACK)

fixAfterDeletion(p);

if (p.parent != null) {

if (p == p.parent.left)

p.parent.left = null;

else if (p == p.parent.right)

p.parent.right = null;

p.parent = null;

}

}

}

/**

* Re-balances after a deletion event. From CLR.

* @param node The node from which to start re-balancing.

*/

private void fixAfterDeletion(final Entry node) {

Entry x = node;

while (x != root && colorOf(x) == BLACK) {

if (x == leftOf(parentOf(x))) {

Entry sib = rightOf(parentOf(x));

if (colorOf(sib) == RED) {

setColor(sib, BLACK);

setColor(parentOf(x), RED);

rotateLeft(parentOf(x));

sib = rightOf(parentOf(x));

}

if (colorOf(leftOf(sib)) == BLACK

&& colorOf(rightOf(sib)) == BLACK) {

setColor(sib, RED);

x = parentOf(x);

} else {

if (colorOf(rightOf(sib)) == BLACK) {

setColor(leftOf(sib), BLACK);

setColor(sib, RED);

rotateRight(sib);

sib = rightOf(parentOf(x));

}

setColor(sib, colorOf(parentOf(x)));

setColor(parentOf(x), BLACK);

setColor(rightOf(sib), BLACK);

rotateLeft(parentOf(x));

x = root;

}

} else { // symmetric

Entry sib = leftOf(parentOf(x));

if (colorOf(sib) == RED) {

setColor(sib, BLACK);

setColor(parentOf(x), RED);

rotateRight(parentOf(x));

sib = leftOf(parentOf(x));

}

if (colorOf(rightOf(sib)) == BLACK

&& colorOf(leftOf(sib)) == BLACK) {

setColor(sib, RED);

x = parentOf(x);

} else {

if (colorOf(leftOf(sib)) == BLACK) {

setColor(rightOf(sib), BLACK);

setColor(sib, RED);

rotateLeft(sib);

sib = leftOf(parentOf(x));

}

setColor(sib, colorOf(parentOf(x)));

setColor(parentOf(x), BLACK);

setColor(leftOf(sib), BLACK);

rotateRight(parentOf(x));

x = root;

}

}

}

setColor(x, BLACK);

}

/**

* Compares two keys using the correct comparison method for this TreeMap.

* @param k1 first key

* @param k2 second key

* @return {@link Comparable#compareTo(Object)}.

*/

@SuppressWarnings("unchecked")

final int compare(final Object k1, final Object k2) {

return comparator == null ? ((Comparable) k1).compareTo((K) k2)

: comparator.compare((K) k1, (K) k2);

}

/**

* Returns the first Entry in the TreeMap (according to the TreeMap's

* key-sort function). Returns null if the TreeMap is empty.

* @return the first Entry in the TreeMap (according to the TreeMap's

* key-sort function), or null if the TreeMap is empty.

*/

final Entry getFirstEntry() {

Entry p = root;

if (p != null)

while (p.left != null)

p = p.left;

return p;

}

/**

* Returns this map's entry for the given key, or {@code null} if the map

* does not contain an entry for the key.

*

* @param key The key of the entry to return.

* @return this map's entry for the given key, or {@code null} if the map

* does not contain an entry for the key

* @throws ClassCastException if the specified key cannot be compared

* with the keys currently in the map

* @throws NullPointerException if the specified key is null

* and this map uses natural ordering, or its comparator

* does not permit null keys

*/

final Entry getEntry(final Object key) {

if (key == null)

throw new NullPointerException();

@SuppressWarnings("unchecked")

Comparable k = (Comparable) key;

Entry p = root;

while (p != null) {

int cmp = k.compareTo(p.key);

if (cmp < 0)

p = p.left;

else if (cmp > 0)

p = p.right;

else

return p;

}

return null;

}

/**

* Returns the color of p.

* @param p The node whose color gets returned.

* @param key type

* @param value type

* @return the color of p

*/

private static boolean colorOf(final Entry p) {

return (p == null ? BLACK : p.color);

}

/**

* Returns the parent of p.

* @param p The node to query.

* @param key type

* @param value type

* @return the color of p

*/

private static Entry parentOf(final Entry p) {

return (p == null ? null : p.parent);

}

/**

* Sets the color of p.

* @param p The node to set.

* @param c either {@link TreeMap#RED} or {@link TreeMap#BLACK}.

* @param key type

* @param value type

*/

private static void setColor(final Entry p, final boolean c) {

if (p != null)

p.color = c;

}

/**

* Returns the left child of p.

* @param p The node to query.

* @param key type

* @param value type

* @return the left child of p.

*/

private static Entry leftOf(final Entry p) {

return (p == null) ? null : p.left;

}

/**

* Returns the right child of p.

* @param p The node to query.

* @param key type

* @param value type

* @return the right child of p.

*/

private static Entry rightOf(final Entry p) {

return (p == null) ? null : p.right;

}

/**

* Test two values for equality. Differs from o1.equals(o2) only in

* that it copes with {@code null} o1 properly.

* @param o1 first object

* @param o2 second object

* @return whether o1 and o2 are equal.

*/

static final boolean valEquals(final Object o1, final Object o2) {

return (o1 == null ? o2 == null : o1.equals(o2));

}

/**

* Returns the successor of the specified Entry, or null if no such.

* @param t The node to query.

* @param key type

* @param value type

* @return the successor of the specified Entry, or null if no such.

*/

static Entry successor(final Entry t) {

if (t == null)

return null;

else if (t.right != null) {

Entry p = t.right;

while (p.left != null)

p = p.left;

return p;

} else {

Entry p = t.parent;

Entry ch = t;

while (p != null && ch == p.right) {

ch = p;

p = p.parent;

}

return p;

}

}

/**

* Returns the predecessor of the specified Entry, or null if no such.

* @param t The node to query.

* @param key type

* @param value type

* @return the predecessor of the specified Entry, or null if no such.

*/

static Entry predecessor(final Entry t) {

if (t == null)

return null;

else if (t.left != null) {

Entry p = t.left;

while (p.right != null)

p = p.right;

return p;

} else {

Entry p = t.parent;

Entry ch = t;

while (p != null && ch == p.left) {

ch = p;

p = p.parent;

}

return p;

}

}

/**

* Models a red-black tree Entry / Node.

* @author Anwar Reddick copied the Java source.

*

* @param key type

* @param value type

*/

static final class Entry implements Map.Entry {

/**

* key.

*/

K key;

/**

* value.

*/

V value;

/**

* left child.

*/

Entry left;

/**

* right child.

*/

Entry right;

/**

* parent node.

*/

Entry parent;

/**

* default is black.

*/

boolean color = BLACK;

/**

* Make a new cell with given key, value, and parent, and with

* {@code null} child links, and BLACK color.

* @param key key

* @param value value

* @param parent parent

*/

Entry(final K key, final V value, final Entry parent) {

this.key = key;

this.value = value;

this.parent = parent;

}

/**

* Returns the key.

*

* @return the key

*/

public K getKey() {

return key;

}

/**

* Returns the value associated with the key.

*

* @return the value associated with the key

*/

public V getValue() {

return value;

}

/**

* Replaces the value currently associated with the key with the given

* value.

*

* @param value the new value.

* @return the value associated with the key before this method was

* called

*/

public V setValue(final V value) {

V oldValue = this.value;

this.value = value;

return oldValue;

}

/* (non-Javadoc)

* @see java.lang.Object#equals(java.lang.Object)

*/

@Override

public boolean equals(final Object o) {

if (!(o instanceof Map.Entry))

return false;

Map.Entry e = (Map.Entry) o;

return valEquals(key, e.getKey()) && valEquals(value, e.getValue());

}

/* (non-Javadoc)

* @see java.lang.Object#hashCode()

*/

@Override

public int hashCode() {

int keyHash = (key == null ? 0 : key.hashCode());

int valueHash = (value == null ? 0 : value.hashCode());

return keyHash ^ valueHash;

}

/* (non-Javadoc)

* @see java.lang.Object#toString()

*/

@Override

public String toString() {

return key + "=" + value;

}

}

/**

* A set of {@link Entry} objects from the map.

*

* @author Anwar Reddick

*

*/

class EntrySet extends AbstractSet> {

/* (non-Javadoc)

* @see java.util.AbstractCollection#iterator()

*/

@Override

public Iterator> iterator() {

return new EntryIterator(getFirstEntry());

}

/* (non-Javadoc)

* @see java.util.AbstractCollection#contains(java.lang.Object)

*/

@Override

public boolean contains(final Object o) {

if (!(o instanceof Map.Entry))

return false;

Map.Entry entry = (Map.Entry) o;

Object value = entry.getValue();

Entry p = getEntry(entry.getKey());

return p != null && valEquals(p.getValue(), value);

}

/* (non-Javadoc)

* @see java.util.AbstractCollection#remove(java.lang.Object)

*/

@Override

public boolean remove(final Object o) {

if (!(o instanceof Map.Entry))

return false;

Map.Entry entry = (Map.Entry) o;

Object value = entry.getValue();

Entry p = getEntry(entry.getKey());

if (p != null && valEquals(p.getValue(), value)) {

deleteEntry(p);

return true;

}

return false;

}

/* (non-Javadoc)

* @see java.util.AbstractCollection#size()

*/

@Override

public int size() {

return TreeMap.this.size();

}

/* (non-Javadoc)

* @see java.util.AbstractCollection#clear()

*/

@Override

public void clear() {

TreeMap.this.clear();

}

}

/**

* Base class for TreeMap Iterators.

* @param the type handled by this iterator.

*/

abstract class PrivateEntryIterator implements Iterator {

/**

* next entry.

*/

Entry next;

/**

* The entry that was most recently returned by nextEntry or prevEntry.

*/

Entry lastReturned;

/**

* Expected # of modifications to the underlying map caused by calls to

* methods on this class.

*/

int expectedModCount;

/**

* Initializes fields.

* @param first the beginning entry.

*/

PrivateEntryIterator(final Entry first) {

expectedModCount = modCount;

lastReturned = null;

next = first;

}

/* (non-Javadoc)

* @see java.util.Iterator#hasNext()

*/

@Override

public final boolean hasNext() {

return next != null;

}

/**

* Returns the next entry object and moves the cursor forward.

* @return the next entry object.

*/

final Entry nextEntry() {

Entry e = next;

if (e == null)

throw new NoSuchElementException();

if (modCount != expectedModCount)

throw new ConcurrentModificationException();

next = successor(e);

lastReturned = e;

return e;

}

/**

* Returns the previous entry object and moves the cursor backward.

* Repeatedly calling this and nextEntry will repeatedly result in the

* same object being returned.

* @return the previous entry object.

*/

final Entry prevEntry() {

Entry e = next;

if (e == null)

throw new NoSuchElementException();

if (modCount != expectedModCount)

throw new ConcurrentModificationException();

next = predecessor(e);

lastReturned = e;

return e;

}

/* (non-Javadoc)

* @see java.util.Iterator#remove()

*/

@Override

public void remove() {

if (lastReturned == null)

throw new IllegalStateException();

if (modCount != expectedModCount)

throw new ConcurrentModificationException();

// deleted entries are replaced by their successors

if (lastReturned.left != null && lastReturned.right != null)

next = lastReturned;

deleteEntry(lastReturned);

expectedModCount = modCount;

lastReturned = null;

}

}

/**

* The primary iterator. No other iterators from {@link java.util.TreeMap}

* were copied into this class.

*

* @author Anwar Reddick

*

*/

final class EntryIterator extends PrivateEntryIterator> {

/**

* Initializes - first will be the first object processed in the first

* call to next.

* @param first the first object to be processed in the first

* call to next.

*/

EntryIterator(final Entry first) {

super(first);

}

/* (non-Javadoc)

* @see java.util.Iterator#next()

*/

@Override

public Map.Entry next() {

return nextEntry();

}

}

}

Step by Step Solution

There are 3 Steps involved in it

1 Expert Approved Answer
Step: 1 Unlock blur-text-image
Question Has Been Solved by an Expert!

Get step-by-step solutions from verified subject matter experts

Step: 2 Unlock
Step: 3 Unlock

Students Have Also Explored These Related Databases Questions!