Finished Deque.
This commit is contained in:
@@ -4,15 +4,141 @@ import tester.Tester;
|
|||||||
|
|
||||||
class Examples {
|
class Examples {
|
||||||
|
|
||||||
|
Deque<Integer> mtDeque;
|
||||||
|
|
||||||
|
Deque<String> exampleDeque;
|
||||||
Sentinel<String> exampleSentinel;
|
Sentinel<String> exampleSentinel;
|
||||||
|
|
||||||
|
Deque<Integer> oneTwo;
|
||||||
|
Node<Integer> one;
|
||||||
|
Node<Integer> two;
|
||||||
|
|
||||||
void init() {
|
void init() {
|
||||||
|
mtDeque = new Deque<Integer>();
|
||||||
|
|
||||||
exampleSentinel = new Sentinel<String>();
|
exampleSentinel = new Sentinel<String>();
|
||||||
|
exampleDeque = new Deque<String>(exampleSentinel);
|
||||||
|
|
||||||
|
Node<String> n1 = new Node<String>("abc");
|
||||||
|
Node<String> n2 = new Node<String>("bcd");
|
||||||
|
Node<String> n3 = new Node<String>("def");
|
||||||
|
|
||||||
|
exampleSentinel.assign(n3, n1);
|
||||||
|
n1.assign(exampleSentinel, n2);
|
||||||
|
n2.assign(n1, n3);
|
||||||
|
n3.assign(n2, exampleSentinel);
|
||||||
|
|
||||||
|
one = new Node<Integer>(1);
|
||||||
|
two = new Node<Integer>(2);
|
||||||
|
|
||||||
|
oneTwo = new Deque<Integer>();
|
||||||
|
|
||||||
|
oneTwo.header.assign(two, one);
|
||||||
|
one.assign(oneTwo.header, two);
|
||||||
|
two.assign(one, oneTwo.header);
|
||||||
}
|
}
|
||||||
|
|
||||||
void testSentinel(Tester t) {
|
void testDequeSize(Tester t) {
|
||||||
init();
|
init();
|
||||||
t.checkExpect(exampleSentinel.nxt, exampleSentinel);
|
t.checkExpect(mtDeque.size(), 0);
|
||||||
|
t.checkExpect(exampleDeque.size(), 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
void testDequeAddAtHead(Tester t) {
|
||||||
|
init();
|
||||||
|
|
||||||
|
t.checkExpect(mtDeque.addAtHead(2).addAtHead(1), oneTwo);
|
||||||
|
}
|
||||||
|
|
||||||
|
void testDequeAddAtTail(Tester t) {
|
||||||
|
init();
|
||||||
|
|
||||||
|
t.checkExpect(mtDeque.addAtTail(1).addAtTail(2), oneTwo);
|
||||||
|
}
|
||||||
|
|
||||||
|
void testDequeRemoveFromHead(Tester t) {
|
||||||
|
init();
|
||||||
|
|
||||||
|
Deque<Integer> justTwo = new Deque<Integer>().addAtHead(2);
|
||||||
|
t.checkExpect(oneTwo.removeFromHead(), justTwo);
|
||||||
|
t.checkException(
|
||||||
|
new UnsupportedOperationException(
|
||||||
|
"Can't remove a `Sentinel` node."
|
||||||
|
),
|
||||||
|
mtDeque,
|
||||||
|
"removeFromHead"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
void testDequeRemoveFromTail(Tester t) {
|
||||||
|
init();
|
||||||
|
|
||||||
|
Deque<Integer> justOne = new Deque<Integer>().addAtHead(1);
|
||||||
|
t.checkExpect(oneTwo.removeFromTail(), justOne);
|
||||||
|
t.checkException(
|
||||||
|
new UnsupportedOperationException(
|
||||||
|
"Can't remove a `Sentinel` node."
|
||||||
|
),
|
||||||
|
mtDeque,
|
||||||
|
"removeFromTail"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
void testDequeFind(Tester t) {
|
||||||
|
init();
|
||||||
|
|
||||||
|
t.checkExpect(oneTwo.find(new isTwo()), two);
|
||||||
|
t.checkExpect(
|
||||||
|
oneTwo.find(new isTwoThousandOneHundredFortyFive()),
|
||||||
|
oneTwo.header
|
||||||
|
);
|
||||||
|
t.checkExpect(mtDeque.find(new isTwo()), mtDeque.header);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Deque<T> {
|
||||||
|
|
||||||
|
ANode<T> header;
|
||||||
|
|
||||||
|
Deque() {
|
||||||
|
this.header = new Sentinel<T>();
|
||||||
|
}
|
||||||
|
|
||||||
|
Deque(Sentinel<T> sentinel) {
|
||||||
|
this.header = sentinel;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get number of `Node`s in the list (not counting `Sentinel`s).
|
||||||
|
int size() {
|
||||||
|
return this.header.sz();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add an element to the 'head' of the list.
|
||||||
|
Deque<T> addAtHead(T thing) {
|
||||||
|
this.header.addAtHead(thing);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add an element to the 'head' of the list.
|
||||||
|
Deque<T> addAtTail(T thing) {
|
||||||
|
this.header.addAtTail(thing);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove the first element in the list.
|
||||||
|
Deque<T> removeFromHead() {
|
||||||
|
this.header.removeFromHead();
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove the last element in the list.
|
||||||
|
Deque<T> removeFromTail() {
|
||||||
|
this.header.removeFromTail();
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
ANode<T> find(IPred<T> question) {
|
||||||
|
return this.header.find(question);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -27,23 +153,75 @@ abstract class ANode<T> {
|
|||||||
this.pre = pre;
|
this.pre = pre;
|
||||||
}
|
}
|
||||||
|
|
||||||
void assignNode(ANode<T> nxt, ANode<T> pre) {
|
void setNxt(ANode<T> nxt) {
|
||||||
|
this.nxt = nxt;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setPre(ANode<T> pre) {
|
||||||
|
this.pre = pre;
|
||||||
|
}
|
||||||
|
|
||||||
|
void assign(ANode<T> pre, ANode<T> nxt) {
|
||||||
|
this.setPre(pre);
|
||||||
|
this.setNxt(nxt);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the size of a list, not including the `Sentinel`.
|
||||||
|
int sz() {
|
||||||
throw new UnsupportedOperationException(
|
throw new UnsupportedOperationException(
|
||||||
"Can't call assignNode() on non-Node."
|
"Can't call `sz()` on non-`Sentinel` node."
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int szHelper() {
|
||||||
|
return 1 + this.nxt.szHelper();
|
||||||
}
|
}
|
||||||
|
|
||||||
class Deque<A> {
|
void addAtHead(T thing) {
|
||||||
|
throw new UnsupportedOperationException(
|
||||||
|
"Can't call `addAtHead()` on non-`Sentinel` node."
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
Sentinel<A> sentinel;
|
void addAtTail(T thing) {
|
||||||
|
throw new UnsupportedOperationException(
|
||||||
|
"Can't call `addAtTail()` on non-`Sentinel` node."
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
Deque(Sentinel<A> sentinel) {
|
void removeFromHead() {
|
||||||
this.sentinel = sentinel;
|
throw new UnsupportedOperationException(
|
||||||
|
"Can't call `removeHead()` on non-`Sentinel` node."
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
void removeFromTail() {
|
||||||
|
throw new UnsupportedOperationException(
|
||||||
|
"Can't call `removeTail()` on non-`Sentinel` node."
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set surrounding nodes to pass over this one.
|
||||||
|
void remove() {
|
||||||
|
this.nxt.setPre(this.pre);
|
||||||
|
this.pre.setNxt(this.nxt);
|
||||||
|
this.nxt = null;
|
||||||
|
this.pre = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
ANode<T> find(IPred<T> question) {
|
||||||
|
throw new UnsupportedOperationException(
|
||||||
|
"Can't call `find()` on non-`Sentinel` node."
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
ANode<T> findHelper(IPred<T> question) {
|
||||||
|
return this;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class Sentinel<T> extends ANode<ANode<T>> {
|
// The sentinel of the list, linking its head and tail.
|
||||||
|
class Sentinel<T> extends ANode<T> {
|
||||||
|
|
||||||
Sentinel() {
|
Sentinel() {
|
||||||
// To create an empty list, this Sentinel points to itself.
|
// To create an empty list, this Sentinel points to itself.
|
||||||
@@ -51,9 +229,44 @@ class Sentinel<T> extends ANode<ANode<T>> {
|
|||||||
this.nxt = this;
|
this.nxt = this;
|
||||||
this.pre = this;
|
this.pre = this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int sz() {
|
||||||
|
return this.nxt.szHelper();
|
||||||
}
|
}
|
||||||
|
|
||||||
class Node<T> extends ANode<Node<T>> {
|
int szHelper() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void addAtHead(T thing) {
|
||||||
|
new Node<T>(thing, this, this.nxt);
|
||||||
|
}
|
||||||
|
|
||||||
|
void addAtTail(T thing) {
|
||||||
|
new Node<T>(thing, this.pre, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
void removeFromHead() {
|
||||||
|
this.nxt.remove();
|
||||||
|
}
|
||||||
|
|
||||||
|
void removeFromTail() {
|
||||||
|
this.pre.remove();
|
||||||
|
}
|
||||||
|
|
||||||
|
void remove() {
|
||||||
|
throw new UnsupportedOperationException(
|
||||||
|
"Can't remove a `Sentinel` node."
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
ANode<T> find(IPred<T> question) {
|
||||||
|
return this.nxt.findHelper(question);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// A node in the list.
|
||||||
|
class Node<T> extends ANode<T> {
|
||||||
|
|
||||||
T val;
|
T val;
|
||||||
|
|
||||||
@@ -62,14 +275,39 @@ class Node<T> extends ANode<Node<T>> {
|
|||||||
this.val = val;
|
this.val = val;
|
||||||
}
|
}
|
||||||
|
|
||||||
Node(T val, ANode<T> nxt, ANode<T> pre) {
|
Node(T val, ANode<T> pre, ANode<T> nxt) {
|
||||||
this(val);
|
this(val);
|
||||||
this.assignNode(nxt, pre);
|
if (nxt == null || pre == null) throw new IllegalArgumentException(
|
||||||
|
"Can't construct node with defunct fields."
|
||||||
|
);
|
||||||
|
|
||||||
|
this.nxt = nxt;
|
||||||
|
this.pre = pre;
|
||||||
|
|
||||||
|
nxt.setPre(this);
|
||||||
|
pre.setNxt(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
void assignNode(ANode<T> nxt, ANode<T> pre) {
|
ANode<T> findHelper(IPred<T> question) {
|
||||||
throw new UnsupportedOperationException(
|
return question.ask(this.val) ? this : this.nxt.findHelper(question);
|
||||||
"Can't call assignNode() on non-Node."
|
}
|
||||||
);
|
}
|
||||||
|
|
||||||
|
// A predicate.
|
||||||
|
interface IPred<T> {
|
||||||
|
boolean ask(T thing);
|
||||||
|
}
|
||||||
|
|
||||||
|
class isTwo implements IPred<Integer> {
|
||||||
|
|
||||||
|
public boolean ask(Integer n) {
|
||||||
|
return n == 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class isTwoThousandOneHundredFortyFive implements IPred<Integer> {
|
||||||
|
|
||||||
|
public boolean ask(Integer n) {
|
||||||
|
return n == 2145;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -6,7 +6,7 @@
|
|||||||
</attributes>
|
</attributes>
|
||||||
</classpathentry>
|
</classpathentry>
|
||||||
<classpathentry kind="src" path="src"/>
|
<classpathentry kind="src" path="src"/>
|
||||||
<classpathentry kind="lib" path="/home/jacob/School/CS3/libs/javalib.jar"/>
|
<classpathentry kind="lib" path="/home/jacob/Projects/CS3/libs/javalib.jar"/>
|
||||||
<classpathentry kind="lib" path="/home/jacob/School/CS3/libs/tester.jar"/>
|
<classpathentry kind="lib" path="/home/jacob/Projects/CS3/libs/tester.jar"/>
|
||||||
<classpathentry kind="output" path="bin"/>
|
<classpathentry kind="output" path="bin"/>
|
||||||
</classpath>
|
</classpath>
|
||||||
|
Reference in New Issue
Block a user