680 likes | 702 Views
Elementary Data Structures. CS 105. Elementary Data Structures. Stack container of elements that are inserted and removed last-in first-out (LIFO) Queue container of elements that are inserted and removed first-in first-out (FIFO) Deque (double-ended queue)
E N D
Elementary Data Structures CS 105
Elementary Data Structures • Stack • container of elements that are inserted and removed last-in first-out (LIFO) • Queue • container of elements that are inserted and removed first-in first-out (FIFO) • Deque (double-ended queue) • container of elements that allows insertion and removal from either end
Stack • Last-in, First-out (LIFO) structure • Operations • push: add element into the stack • pop: remove & return topmost element • top: return topmost element • isEmpty: check if the stack has no elements • size: return number of elements in the stack • Sample uses • “Back” button of a browser, “Undo” operation, function/method calls
Stack Interface public interface Stack { public int size(); public boolean isEmpty(); public void push( Object o ); public Object top() throws EmptyStackException; public Object pop() throws EmptyStackException; } public class EmptyStackException extends RuntimeException { }
Array Implementation public class ArrayStack implements Stack { private int top = -1; private Object S[]; ... } top 3 S ... x z y w
Array Implementation Details • An array of objects stores the elements • An integer field points to the topmost element • Value of top is –1 when the stack is empty • A constant indicates the size/capacity of the array • Throw a StackFullException when a push is attempted on a full array
ArrayStack class public class ArrayStack implements Stack { public static final int CAPACITY = 1000; private Object S[]; private int top; public ArrayStack() { S = new Object[CAPACITY]; top = -1; } public boolean isEmpty() { return (top < 0); } … }
ArrayStack class continued public class ArrayStack implements Stack { … public int size() { return (top + 1); } public void push(Object obj) throws FullStackException { if (size() == CAPACITY) throw new FullStackException(); S[++top] = obj; } … } public class FullStackException extends RuntimeException { }
ArrayStack class continued public class ArrayStack implements Stack { … public Object top() throws EmptyStackException { if (isEmpty()) throw new EmptyStackException(); return S[top]; } public Object pop() throws EmptyStackException { if (isEmpty()) throw new EmptyStackException(); return S[top--]; } … }
Garbage collection • After a pop() operation, array still contains reference to popped element • Succeeding push() operations will override such references but it is not certain whether pushes will occur after the pops • Better to set the reference to null so that the object is garbage-collected when no longer in use
Improved pop() method public class ArrayStack implements Stack { … public Object pop() throws EmptyStackException { Object elem; if (isEmpty()) throw new EmptyStackException(); elem = S[top]; S[top--] = null; // dereference S[top] for garbage collection. return elem; } … }
Using the Stack Stack s1 = new ArrayStack(); String temp; s1.push( "easy" ); s1.push( "this" ); temp = (String) s1.pop(); System.out.print( temp ); s1.push( "is" ); s1.push( "class" ); while ( !s1.isEmpty() ) { temp = (String) s1.pop(); System.out.print( " "+ temp ); } System.out.println(); OK because Strings are Objects Cast object to String
Stack of ints Stack s2 = new ArrayStack(); s2.push( 5 ); s2.push( 2 ); s2.push( 3 ); int num = (Integer) s2.pop(); System.out.println( num ); Allowed in Java 1.5 because primitive type values are“auto-boxed” Cast object to Integer type (not int) Note: In previous Java versions, s2.push( new Integer( 2 ) ); num = ( (Integer) s2.pop() ).intValue();
Time Complexity Analysis • push() : O(1) • pop() : O(1) • isEmpty() : O(1) • size() : O(1) • top(): O(1)
Array Implementation Alternative • Make top variable point to next available array position instead of actual topmost element • top = 0 when empty • top represents size top 4 S ... x z y w
Problems with ArrayStack • CAPACITY needs to be specified • Consequences • stack may fill up (when size() == MAX ) • memory is wasted if actual stack consumption is way below maximum • Need a more “dynamic” implementation
Linked List Implementation top null y w z A stack as a sequence of nodes
The Node class public class Node { private Object element; private Node next; public Node( Object e, Node n ) { element = e; next = n; } public Object getElement() … public Node getNext() … public void setElement( Object newElem ) … public void setNext( Node newNext ) … } y
Linked List Implementation • Stack is represented by a Node reference (called top) • This reference is null when stack is empty • Top refers to the top element only but links in each node keep the elements together • An integer field represents the number of elements in the stack
NodeStack class public class NodeStack implements Stack { private Node top; private int size; public NodeStack() { top = null; size = 0; } public boolean isEmpty() { return (top == null); } … }
NodeStack class continued public class NodeStack implements Stack { … public int size() { return size; } public void push( Object obj ) { Node v = new Node( obj, top ); top = v; size++; } … }
Push operation top size 3 null y w z
Push operation top size 3 null x y w z Create node
Push operation top size 4 null x y w z Update top and size
NodeStack class continued public class NodeStack implements Stack { … public Object top() throws EmptyStackException { if ( isEmpty() ) throw new EmptyStackException(); return top.getElement(); } public Object pop() throws EmptyStackException { if ( isEmpty() ) throw new EmptyStackException(); Object temp = top.getElement(); top = top.getNext(); size--; return temp; } … }
Pop operation top size 4 null x y w z
Pop operation top size 4 null x y w z temp Get top element
Pop operation top size 3 null x y w z temp Update top and size
Pop operation top size 3 null x y w z temp Node automatically disposed
Pop operation top size 3 null x y w z Return element
Using the NodeStack Stack s2 = new NodeStack(); s2.push( 5 ); s2.push( 2 ); s2.push( 3 ); int num = (Integer) s2.pop(); System.out.println( num ); Only this line changed
Time Complexity Analysis • push() : O(1) • pop() : O(1) • isEmpty() : O(1) • size() : O(1) • top(): O(1)
ArrayStack versus NodeStack • NodeStack uses only the memory that it needs at any given time • NodeStack has no size limit(just the system’s memory) – FullStackException not thrown • ArrayStack’s implementation is simpler • Which implementation is more efficient?
Managing Multiple Implementations • Note that we now have two implementations of a Stack: public class ArrayStack implements Stack { … } public class NodeStack implements Stack { … } • Consider what code needs to be changed if we shift between implementations • It would be preferable if the code that uses the stack does not need to be updated
A StackFactory Class • Use a separate class that produces Stack objects public class StackFactory { public static Stack createStack() { return new ArrayStack(); // or return new NodeStack(); } } • Advantage: • if you want to change your implementation, you just need to change StackFactory • you don’t need to change all calls to new ArrayStack in all your code!
Using a StackFactory Stack s2 = StackFactory.createStack(); s2.push( 5 ); s2.push( 2 ); s2.push( 3 ); int num = (Integer) s2.pop(); System.out.println( num ); this line need not be changed even if the stack implementation changes
Queue • First-in, First-out (FIFO) structure • Operations • enqueue: insert element at rear • dequeue: remove & return front element • front: return front element • isEmpty: check if the queue has no elements • size: return number of elements in the queue • Sample use • handling requests and reservations
The Queue Interface public interface Queue { public int size(); public boolean isEmpty(); public void enqueue( Object o ); public Object front() throws EmptyQueueException; public Object dequeue() throws EmptyQueueException; } public class EmptyQueueException extends RuntimeException { }
Array Implementation Possibilities • On enqueue, place element in the next available slot; on dequeue, remove element at position 0 and move all other elements to the left • Dequeue takes O(n) time • Have integer pointers to front and rear, increment rear on enqueue, increment front on dequeue, so that both operations are O(1)
Array Implementation of a Queue • An Object array and two integers • front: index of first element in queue • rear: index of first FREE element in queue rear front 4 0 ...
ArrayQueue public class ArrayQueue implements Queue { public static final int CAPACITY = 1000; private Object s[]; private int front, rear; public ArrayQueue() { s = new Object[CAPACITY]; front = rear = 0; } ... }
isEmpty and Enqueue public class ArrayQueue implements Queue { ... public boolean isEmpty() { return ( front == rear ); } public void enqueue( Object o ) throws FullQueueException { if ( rear == CAPACITY ) throw new FullQueueException(); s[rear++] = o; } ... } public class FullQueueException extends RuntimeException { }
Enqueue operation front rear 0 3 ...
Enqueue operation front rear 0 4 ... Enqueued object
Dequeue public class ArrayQueue implements Queue { ... public Object dequeue() throws EmptyQueueException { if ( isEmpty() ) throw new EmptyQueueException(); return s[front++]; } … }
Dequeue operation front rear 0 4 ...
Dequeue operation front rear 1 4 ... Return this object
Dequeue operation Remember to set reference in array to null front rear 1 4 ... null
Dequeue with Garbage Collection public class ArrayQueue implements Queue { ... public Object dequeue() throws EmptyQueueException { if ( isEmpty() ) throw new EmptyQueueException(); Object data = s[front]; s[front] = null; front++; return data; } }
Circular Array • Suppose many enqueue operations followed by many dequeue operations • Result: rear approaches CAPACITY but the queue is not really full • Solution: Circular Array • allow rear (and front) to “wrap around” the array (if rear = CAPACITY-1, incrementing rear means resetting it to 0)