// -*- Mode: Java -*- // BitList.java --- data structure to store a sequence of bits (ints) // Author : Marcel Turcotte // Created On : Fri Apr 9 09:00:27 2004 // Last Modified By: Marcel Turcotte // Last Modified On: Tue Apr 4 10:06:56 2006 // Unlike the list of the current assignment, this one 1) does not // detect concurrent modifications and 2) does not start with a dummmy // node. import java.util.NoSuchElementException; // Stores the bits in reverse order! public class BitList { // useful constants public static final int ZERO = 0; public static final int ONE = 1; // instance variables private Node first; // constructors public BitList() { first = null; } public BitList( String s ) { // pre-condition if ( s == null ) { throw new IllegalArgumentException( "null" ); } for ( int i=0; i < s.length() ; i++ ) { int bit = s.charAt(i) - '0'; if ( ( bit != ZERO ) && ( bit != ONE ) ) { throw new IllegalArgumentException( s ); } addFirst( bit ); // reverses the order! } } public void addFirst( int bit ) { if ( ( bit != ZERO ) && ( bit != ONE ) ) { throw new IllegalArgumentException( Integer.toString( bit ) ); } first = new Node( bit, first ); } public int removeFirst() { if ( first == null ) { throw new NoSuchElementException(); } int saved = first.bit; first = first.next; return saved; } public void complement() { if ( first == null ) { addFirst( ONE ); } else { complement( first ); } } private static void complement( Node p ) { // base case if ( p == null ) { return; } // pre-processing (could be post as well) if ( p.bit == ONE ) { p.bit = ZERO; } else { p.bit = ONE; } // recursion complement( p.next ); } // private void complement( Node p ) { // // if ( p.bit == ONE ) { // p.bit = ZERO; // } else { // p.bit = ONE; // } // if ( p.next != null ) { // complement( p.next ); // } // } public BitList or( BitList other ) { if ( first == null ) { throw new IllegalArgumentException( "this list is empty" ); } if ( other.first == null ) { throw new IllegalArgumentException( "other is empty" ); } BitList result; result = new BitList(); or( result, first, other.first ); return result; } private static void or( BitList result, Node p, Node q ) { // pre-conditions if ( p == null && q != null ) { throw new IllegalArgumentException( "this list is shorter" ); } if ( p != null && q == null ) { throw new IllegalArgumentException( "this list is longer" ); } // base case if ( p == null && q == null ) { return; } // recursion or( result, p.next, q.next ); // post-processing if ( p.bit == ONE || q.bit == ONE ) { result.addFirst( ONE ); } else { result.addFirst( ZERO ); } } // alternative implementation public BitList or2( BitList other ) { if ( first == null ) { throw new IllegalArgumentException( "this list is empty" ); } if ( other.first == null ) { throw new IllegalArgumentException( "other is empty" ); } BitList result; result = new BitList(); result.first = or2( first, other.first ); return result; } private static Node or2( Node p, Node q ) { // pre-conditions if ( p == null && q != null ) { throw new IllegalArgumentException( "this list is shorter" ); } if ( p != null && q == null ) { throw new IllegalArgumentException( "this list is longer" ); } // base case if ( p == null && q == null ) { return null; } // recursion Node res = or2( p.next, q.next ); // post-processing int bit; if ( p.bit == ONE || q.bit == ONE ) { bit = ONE; } else { bit = ZERO; } return new Node( bit, res ); } public boolean equals( Object other ) { if ( ! ( other instanceof BitList ) ) { return false; } return equals( first, ( (BitList) other ).first ); } private static boolean equals( Node p, Node q ) { // Base cases (stopping recursion) // Same length? if ( p == null && q != null ) { return false; } if ( p != null && q == null ) { return false; } // Reached the end of both lists? if ( p == null && q == null ) { return true; } // Found a mismatch? if ( p.bit != q.bit ) { return false; } // General case return equals( p.next, q.next ); } public Iterator iterator() { return new BitListIterator(); } public String toString() { String str = ""; if ( first == null ) { str += ZERO; } else { Node p = first; while (p!=null) { str = p.bit + str; // reverses the order p = p.next; } } return str; } // The implementation of the nodes (static nested class) private static class Node { private int bit; // <- NEW private Node next; private Node( int bit, Node next ) { // <- ACCORDINGLY ... this.bit = bit; this.next = next; } } // The implementation of the iterators (inner class) private class BitListIterator implements Iterator { private Node current = null; private BitListIterator() { current = null; } public boolean hasNext() { return ( ( current == null && first != null ) || ( current != null && current.next != null ) ); } public int next() { if ( current == null ) { current = first ; } else { current = current.next ; // move the cursor forward } if ( current == null ) { throw new NoSuchElementException() ; } return current.bit ; } public void add( int bit ) { if ( ( bit != ZERO ) && ( bit != ONE ) ) { throw new IllegalArgumentException( Integer.toString( bit ) ); } Node newNode; if ( current == null ) { first = new Node( bit, first ); current = first; } else { current.next = new Node( bit, current.next ); current = current.next; } } } }