这次作业没有测试代码,一亩地上有测试数据链接: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; } }