這次作業沒有測試代碼,一畝地上有測試資料連結:http://pan.baidu.com/s/1dD5ql4P
DList中的insertFront, insetBack等方法多為視訊前幾節講的Doubly-Linkedlist.
在測試TestLockDList的時候總是出現ClassCastException, 然而我LockDList中的代碼都沒寫錯,也override newNode。後來發現在DList中我雖然建立了newNode方法,但是在insertFront等方法中用的還是
DListNode new_node = new DListNode(item, head.prev, head);
是以後來在LockDList中雖然override newNode,但實際上這個方法根本沒有用到,是以DListNode才無法轉化成LockDListNode。
DList:
/* DList.java */
package com.homework4;
/**
* A DList is a mutable doubly-linked list ADT. Its implementation is
* circularly-linked and employs a sentinel (dummy) node at the head
* of the list.
*
* DO NOT CHANGE ANY METHOD PROTOTYPES IN THIS FILE.
*/
public class DList {
/**
* head references the sentinel node.
* size is the number of items in the list. (The sentinel node does not
* store an item.)
*
* DO NOT CHANGE THE FOLLOWING FIELD DECLARATIONS.
*/
protected DListNode head;
protected int size;
/* DList invariants:
* 1) head != null.
* 2) For any DListNode x in a DList, x.next != null.
* 3) For any DListNode x in a DList, x.prev != null.
* 4) For any DListNode x in a DList, if x.next == y, then y.prev == x.
* 5) For any DListNode x in a DList, if x.prev == y, then y.next == x.
* 6) size is the number of DListNodes, NOT COUNTING the sentinel,
* that can be accessed from the sentinel (head) by a sequence of
* "next" references.
*/
/**
* newNode() calls the DListNode constructor. Use this class to allocate
* new DListNodes rather than calling the DListNode constructor directly.
* That way, only this method needs to be overridden if a subclass of DList
* wants to use a different kind of node.
* @param item the item to store in the node.
* @param prev the node previous to this node.
* @param next the node following this node.
*/
protected DListNode newNode(Object item, DListNode prev, DListNode next) {
return new DListNode(item, prev, next);
}
/**
* DList() constructor for an empty DList.
*/
public DList() {
// Your solution here.
head = newNode(null,head,head);
head.prev = head;
head.next = head;
size = 0;
}
/**
* isEmpty() returns true if this DList is empty, false otherwise.
* @return true if this DList is empty, false otherwise.
* Performance: runs in O(1) time.
*/
public boolean isEmpty() {
return size == 0;
}
/**
* length() returns the length of this DList.
* @return the length of this DList.
* Performance: runs in O(1) time.
*/
public int length() {
return size;
}
/**
* insertFront() inserts an item at the front of this DList.
* @param item is the item to be inserted.
* Performance: runs in O(1) time.
*/
public void insertFront(Object item) {
// Your solution here.
DListNode new_node = newNode(item, head, head.next);
head.next.prev = new_node;
head.next = new_node;
size++;
}
/**
* insertBack() inserts an item at the back of this DList.
* @param item is the item to be inserted.
* Performance: runs in O(1) time.
*/
public void insertBack(Object item) {
// Your solution here.
DListNode new_node = newNode(item, head.prev, head);
head.prev.next = new_node;
head.prev = new_node;
size++;
}
/**
* front() returns the node at the front of this DList. If the DList is
* empty, return null.
*
* Do NOT return the sentinel under any circumstances!
*
* @return the node at the front of this DList.
* Performance: runs in O(1) time.
*/
public DListNode front() {
// Your solution here.
if (head.next != null){
return head.next;
}
return null;
}
/**
* back() returns the node at the back of this DList. If the DList is
* empty, return null.
*
* Do NOT return the sentinel under any circumstances!
*
* @return the node at the back of this DList.
* Performance: runs in O(1) time.
*/
public DListNode back() {
// Your solution here.
if (head.next != null){
return head.prev;
}
return null;
}
/**
* next() returns the node following "node" in this DList. If "node" is
* null, or "node" is the last node in this DList, return null.
*
* Do NOT return the sentinel under any circumstances!
*
* @param node the node whose successor is sought.
* @return the node following "node".
* Performance: runs in O(1) time.
*/
public DListNode next(DListNode node) {
// Your solution here.
if (node != null || node.next != head){
return node.next;
}
return null;
}
/**
* prev() returns the node prior to "node" in this DList. If "node" is
* null, or "node" is the first node in this DList, return null.
*
* Do NOT return the sentinel under any circumstances!
*
* @param node the node whose predecessor is sought.
* @return the node prior to "node".
* Performance: runs in O(1) time.
*/
public DListNode prev(DListNode node) {
// Your solution here.
if (node != null || node.prev != head ){
return node.prev;
}
return null;
}
/**
* insertAfter() inserts an item in this DList immediately following "node".
* If "node" is null, do nothing.
* @param item the item to be inserted.
* @param node the node to insert the item after.
* Performance: runs in O(1) time.
*/
public void insertAfter(Object item, DListNode node) {
// Your solution here.
if (node != null){
DListNode new_node = newNode(item,node,node.next);
node.next.prev = new_node;
node.next = new_node;
size++;
}
}
/**
* insertBefore() inserts an item in this DList immediately before "node".
* If "node" is null, do nothing.
* @param item the item to be inserted.
* @param node the node to insert the item before.
* Performance: runs in O(1) time.
*/
public void insertBefore(Object item, DListNode node) {
// Your solution here.
if (node != null){
DListNode new_node = newNode(item,node.prev,node);
node.prev.next = new_node;
node.prev = new_node;
size++;
}
}
/**
* remove() removes "node" from this DList. If "node" is null, do nothing.
* Performance: runs in O(1) time.
*/
public void remove(DListNode node) {
// Your solution here.
if (node != null && node != head){
node.prev.next = node.next;
node.next.prev = node.prev;
node.prev = null;
node.next = null;
size--;
}
}
/**
* toString() returns a String representation of this DList.
*
* DO NOT CHANGE THIS METHOD.
*
* @return a String representation of this DList.
* Performance: runs in O(n) time, where n is the length of the list.
*/
public String toString() {
String result = "[ ";
DListNode current = head.next;
while (current != head) {
result = result + current.item + " ";
current = current.next;
}
return result + "]";
}
public void checkInvariants() {
System.out.println("\nVerifying invariants.");
boolean tightShip = true;
// 1) head != null.
if (head == null) {
System.out.println("ERROR: Invariant 1 failed.");
System.out.println("head == null!");
tightShip = false;
}
DListNode x = head;
int cur = 0;
do
{
// 2) For any DListNode x in a DList, x.next != null.
if (x.next == null) {
System.out.println("ERROR: Invariant 2 failed.");
System.out.println("x.next == null for element " + cur);
tightShip = false;
cur--;
break;
}
// 3) For any DListNode x in a DList, x.prev != null.
if (x.prev == null) {
System.out.println("ERROR: Invariant 3 failed.");
System.out.println("x.prev == null for element " + cur);
tightShip = false;
}
// 4) For any DListNode x in a DList, if x.next == y, then y.prev == x.
DListNode y = x.next;
if (y.prev != x) {
System.out.println("ERROR: Invariant 4 failed.");
System.out.println("x.next == y but y.prev != x for element " + cur);
tightShip = false;
}
// 5) For any DListNode x in a DList, if x.prev == y, then y.next == x.
y = x.prev;
if (y.next != x) {
System.out.println("ERROR: Invariant 5 failed.");
System.out.println("x.prev == y but y.next != x for element " + cur);
tightShip = false;
}
y = null;
x = x.next;
cur++;
} while (x != head);
// 6) size is the number of DListNodes, NOT COUNTING the sentinel,
// that can be accessed from the sentinel (head) by a sequence of
// "next" references.
if (size != --cur) {
System.out.println("ERROR: Invariant 6 failed.");
System.out.println("size == " + size);
System.out.println("Should be " + cur + ".");
tightShip = false;
}
System.out.print("You ");
if (!tightShip) {
System.out.print("do not ");
}
System.out.println("run a tight ship!\n");
}
/**
* main() contains test code for making new DList objects, inserting and
* removing nodes, and detemining the size of DList objects.
*/
public static void main(String[] args) {
System.out.println("Constructing a new DList.");
DList l1 = new DList();
System.out.println(l1);
System.out.println("Current size: " + l1.length());
System.out.println("\nAttempting to remove the head node.");
l1.remove(l1.head);
System.out.println(l1);
System.out.println("Current size: " + l1.length());
System.out.println("\nAttempting to remove the node after head.");
l1.remove(l1.head.next);
System.out.println(l1);
System.out.println("Current size: " + l1.length());
System.out.println("\nAttempting to insert a new front node containing 3.");
l1.insertFront(new Integer(3));
System.out.println(l1);
System.out.println("Current size: " + l1.length());
System.out.println("\nAttempting to insert a new front node containing 2.");
l1.insertFront(new Integer(2));
System.out.println(l1);
System.out.println("Current size: " + l1.length());
System.out.println("\nAttempting to insert a new front node containing 99.");
l1.insertFront(new Integer(99));
System.out.println(l1);
System.out.println("Current size: " + l1.length());
System.out.println("\nAttempting to remove the node after head.");
l1.remove(l1.head.next);
System.out.println(l1);
System.out.println("Current size: " + l1.length());
l1.checkInvariants();
System.out.println("Attempting to insert a new back node containing 9");
l1.insertBack(new Integer(9));
System.out.println(l1);
System.out.println("Current size: " + l1.length());
System.out.print("\nAttempting to insert a new back node containing ");
System.out.println("\"deleteMe\".");
l1.insertBack(new String("deleteMe"));
System.out.println(l1);
System.out.println("Current size: " + l1.length());
System.out.print("\nAttempting to insert a new node containing 4 after the ");
System.out.println("second node.");
l1.insertAfter(4, l1.next(l1.head).next);
System.out.println(l1);
System.out.println("Current size: " + l1.length());
System.out.println("\nAttempting to remove the back node.");
l1.remove(l1.prev(l1.head));
System.out.println(l1);
System.out.println("Current size: " + l1.length());
System.out.print("\nAttempting to insert a new node containing 8 after ");
System.out.println("the second to last node.");
l1.insertAfter(8, l1.prev(l1.back()));
System.out.println(l1);
System.out.println("Current size: " + l1.length());
l1.checkInvariants();
System.out.println("Constructing a new DList.");
DList l2 = new DList();
System.out.println(l2);
System.out.print("\nAttempting to set the head node of the new DList ");
System.out.println("to the first node of the old DList.");
System.out.print("Good luck with that! (I bet it will screw up the ");
System.out.println("invariants.)\n");
l2.head = l1.head.next;
System.out.println("First DList:");
l1.checkInvariants();
System.out.println("Second DList:");
l2.checkInvariants();
}
}
LockDList:
package com.homework4;
public class LockDList extends DList {
@Override
protected LockDListNode newNode(Object item, DListNode prev, DListNode next) {
return new LockDListNode(item,prev,next);
}
public void lockNode(DListNode node){
((LockDListNode) node).locked = true;
}
@Override
public void remove(DListNode node) {
if(((LockDListNode) node).locked){
return;
}
super.remove(node);
}
}
DListNode:
package com.homework4;
/**
* A DListNode is a node in a DList (doubly-linked list).
*/
public class DListNode {
/**
* item references the item stored in the current node.
* prev references the previous node in the DList.
* next references the next node in the DList.
*
* DO NOT CHANGE THE FOLLOWING FIELD DECLARATIONS.
*/
public Object item;
protected DListNode prev;
protected DListNode next;
/**
* DListNode() constructor.
* @param i the item to store in the node.
* @param p the node previous to this node.
* @param n the node following this node.
*/
DListNode(Object i, DListNode p, DListNode n) {
item = i;
prev = p;
next = n;
}
}
LockDListNode:
package com.homework4;
public class LockDListNode extends DListNode {
boolean locked;
LockDListNode(Object i, DListNode p, DListNode n) {
super(i, p, n);
locked = false;
}
}