/* SListNode.java */ package list; /** * An SListNode is a mutable node in an SList (singly-linked list). **/ public class SListNode extends ListNode { /** * (inherited) item references the item stored in the current node. * (inherited) myList references the List that contains this node. * next references the next node in the SList. * * DO NOT CHANGE THE FOLLOWING FIELD DECLARATIONS. **/ protected SListNode next; /** * SListNode() constructor. * @param i the item to store in the node. * @param l the list this node is in. * @param n the node following this node. */ SListNode(Object i, SList l, SListNode n) { item = i; myList = l; next = n; } /** * next() returns the node following this node. If this node is invalid, * throws an exception. * * @return the node following this node. * @exception InvalidNodeException if this node is not valid. * * Performance: runs in O(1) time. */ public ListNode next() throws InvalidNodeException { if (!isValidNode()) { throw new InvalidNodeException("next() called on invalid node"); } if (next == null) { // Create an invalid node. SListNode node = ((SList) myList).newNode(null, null); node.myList = null; return node; } else { return next; } } /** * prev() returns the node preceding this node. If this node is invalid, * throws an exception. * * @param node the node whose predecessor is sought. * @return the node preceding this node. * @exception InvalidNodeException if this node is not valid. * * Performance: runs in O(this.size) time. */ public ListNode prev() throws InvalidNodeException { if (!isValidNode()) { throw new InvalidNodeException("prev() called on invalid node"); } SListNode prev = ((SList) myList).head; if (prev == this) { // Create an invalid node. prev = ((SList) myList).newNode(null, null); prev.myList = null; } else { while (prev.next != this) { prev = prev.next; } } return prev; } /** * insertAfter() inserts an item immediately following this node. If this * node is invalid, throws an exception. * * @param item the item to be inserted. * @exception InvalidNodeException if this node is not valid. * * Performance: runs in O(1) time. */ public void insertAfter(Object item) throws InvalidNodeException { if (!isValidNode()) { throw new InvalidNodeException("insertAfter() called on invalid node"); } SListNode newNode = ((SList) myList).newNode(item, next); if (next == null) { ((SList) myList).tail = newNode; } next = newNode; myList.size++; } /** * insertBefore() inserts an item immediately preceding this node. If this * node is invalid, throws an exception. * * @param item the item to be inserted. * @exception InvalidNodeException if this node is not valid. * * Performance: runs in O(this.size) time. */ public void insertBefore(Object item) throws InvalidNodeException { if (!isValidNode()) { throw new InvalidNodeException("insertBefore() called on invalid node"); } SListNode newNode = ((SList) myList).newNode(item, this); if (this == ((SList) myList).head) { ((SList) myList).head = newNode; } else { SListNode prev = (SListNode) prev(); prev.next = newNode; } myList.size++; } /** * remove() removes this node from its SList. If this node is invalid, * throws an exception. * * @exception InvalidNodeException if this node is not valid. * * Performance: runs in O(this.size) time. */ public void remove() throws InvalidNodeException { if (!isValidNode()) { throw new InvalidNodeException("remove() called on invalid node"); } if (this == ((SList) myList).head) { ((SList) myList).head = next; if (next == null) { ((SList) myList).tail = null; } } else { SListNode prev = (SListNode) prev(); prev.next = next; if (next == null) { ((SList) myList).tail = prev; } } myList.size--; // Make this node an invalid node, so it cannot be used to corrupt myList. myList = null; // Set other reference to null to improve garbage collection. next = null; } }