adts, stacks and queuescse.iitrpr.ac.in/ckn/courses/f2015/csl201/w3.pdf · abstract data types...
TRANSCRIPT
ADTs, Stacks and Queues
Readings - Chapter 6
1
Abstract Data Types
2 ADT
Abstract Data Types (ADTs) q An abstract data type (ADT) is a
mathematically specified entity that defines a set of its instances.
q An ADT specifies: n What data is stored n Interface - Operations on the data
w manipulation w access
n a set of axioms (preconditions and post conditions) that define what the operations do (not how)
3 ADT
Why Abstract Data Types (ADTs) q serve as specifications of requirements
for the building blocks of an algorithm q encapsulate the data structure and the
algorithms that works on the data structure
q separate issues of correctness and efficiency
4 ADT
ADT Example - Order Book of a Stock Trading System - Dynamic Set
q The data stored are n Stock n Shares n Price n Buy/Sell
q The operations supported are w New(): ADT w Add(B:ADT, e:Element): ADT w Remove(B:ADT, e:Element): ADT w isIn(B:ADT, e:Element): boolean
5 ADT
Element
ADT Example - Order Book of a Stock Trading System - Dynamic Set
q The data stored are n Stock n Shares n Price n Buy/Sell
q The operations supported are w New(): ADT w Add(B:ADT, e:Element): ADT w Remove(B:ADT, e:Element): ADT w isIn(B:ADT, e:Element): boolean
6 ADT
Element
Constructor
ADT Example - Order Book of a Stock Trading System - Dynamic Set
q The data stored are n Stock n Shares n Price n Buy/Sell
q The operations supported are w New(): ADT w Add(B:ADT, e:Element): ADT w Remove(B:ADT, e:Element): ADT w isIn(B:ADT, e:Element): boolean
7 ADT
Element
Constructor
Manipulation Operations
ADT Example - Order Book of a Stock Trading System - Dynamic Set
q The data stored are n Stock n Shares n Price n Buy/Sell
q The operations supported are w New(): ADT w Add(B:ADT, e:Element): ADT w Remove(B:ADT, e:Element): ADT w isIn(B:ADT, e:Element): boolean
8 ADT
Element
Constructor
Manipulation Operations
Access
ADT Example - Order Book of a Stock Trading System - Dynamic Set
q Axioms that define the methods n isIn(New(), e) - false n isIn(Add(B, e), e) - true n isIn(Add(B, f), e) - isIn(B, e) if e≠f n isIn(Remove(B, e), e) - false n isIn(Remove(B, f), e) = isIn(B, e), if e≠f
9 ADT
The Stack ADT q Container of abstract objects that are inserted and
removed according to the last-in-first-out (LIFO) principle
q Objects can be inserted at any time, but only the most-recently inserted object can be removed n Inserting an object - push n removing an object - pop
10 Stacks
The Stack ADT - Specification q Data Object q Operations
n new():ADT - creates a new stack n push(S:ADT, o:Object):ADT - Inserts
object o onto the top of stack S n pop(S:ADT):ADT - removes the top object
of stack S; if the stack is empty an error occurs
11 Stacks
The Stack ADT - Specification (contd) q Auxiliary operations
n top(S:ADT):Object - returns the top object of stack S without removing it; if the stack is empty, an error occurs
n size(S:ADT):integer returns the number of objects in stack S
n isEmpty(S:ADT):boolean - indicates if stack S is empty
q Axioms n pop(push(S, o)) = S n top(push(S, o)) = o
12 Stacks
Stack - Example
13 Stacks
Stack ADT specification in JAVA? Interfaces q Interface - collection of method
declarations with no data and no bodies n write down the method names and the
parameters (essentially the types) n when a class implements an interface, it
must implement all the methods declared in the interface.
n Separating interface and implementation is a useful programming technique.
14 Stacks
Stack Interface in Java q java.util has a built-in stack data structure
class - we will define our own interface and not use the built-in class
15 Stacks
public interface Stack<E> { !// accessor methods! public int size(); // returns the number of objects in the stack! public boolean isEmpty(); // returns true if the stack is empty, false otherwise! public E top(); throws StackEmptyException; // returns the top object of the stack!!// manipulation/update methods! public void push(E o); // inserts the object at the top of the stack! public E pop(); throws StackEmptyException; // removes and returns the object at the top of the stack!}
Stack ADT specification in JAVA? Exceptions q unexpected events that occur during the
execution of a program n useful for handling errors
q when an error (or an exceptional event is encountered, the Java code throws an exception
q Upon throwing an exception, the control flow exits from the current method and goes to the parent calling method n responsibility of handling the error can be
delegated to the parent method
16 Stacks
Exceptions - Example
Stacks 17
public void UpdateStudentScore(Student s) throws StudentNotFoundException { !... !if (s is not part of CSL201) !throw new StudentNotFoundException(s+"is not a student in CSL201"); !... !} !!public void UpdateClassScore() { !... !try { ! CSL201.UpdateStudentScore(s); !} !catch (StudentNotFoundException e) { !system.out.println(e); !} !... !}
More Exceptions - Try and Catch q try - guarded fragment of code that might
thrown an exception when executed. q catch - block of code to which control
jumps on catching an exception. The block contains code to analyze the exception and apply an appropriate solution.
q If an exception is never caught in a method, it will propagate upwards along the sequence of method calls until the user sees it.
q Exceptions are essentially Java Classes n Section 2.4
18 Stacks
Stack Interface in Java - Finally q java.util has a built-in stack data structure
class - we will define our own interface and not use the built-in class
19 Stacks
public interface Stack<E> { !// accessor methods! public int size(); // returns the number of objects in the stack! public boolean isEmpty(); // returns true if the stack is empty, false otherwise! public E top() throws StackEmptyException; // returns the top object of the stack!!// manipulation/update methods! public void push(E o); // inserts the object at the top of the stack! public E pop() throws StackEmptyException; // removes and returns the object at the top of the stack!}
Array-Based Stack Implementation in Java q Simple way to implement a stack
n specify the maximum size N of our stack q Add elements left to right q variable t keeps track of the top element
of the array stack S
q array indices start at 0, so we initialize t to -1
20 Stacks
S 0 1 2 t
…
Array-Based Stack Implementation in Java - 1 public class ArrayStack<E> implements Stack<E> { ! /** Default array capacity. */! public static final int CAPACITY=1000; // default array capacity!! /** Generic array used for storage of stack elements. */! private E[] data; // generic array used for storage!! /** Index of the top element of the stack in the array. */! private int t = -1; // index of the top element in stack!! /** Constructs an empty stack using the default array capacity. */! public ArrayStack() { this(CAPACITY); } // constructs stack with default capacity!! /** ! * Constructs and empty stack with the given array capacity. ! * @param capacity length of the underlying array ! */!public ArrayStack(int capacity) { // constructs stack with given capacity! data = (E[]) new Object[capacity]; ! }
21 Stacks
Array-Based Stack Implementation in Java - 2 /** ! * Returns the number of elements in the stack. ! * @return number of elements in the stack ! */!public int size() { return (t + 1); } !! /** ! * Tests whether the stack is empty. ! * @return true if the stack is empty, false otherwise ! */!public boolean isEmpty() { return (t == -1); } !! /** ! * Inserts an element at the top of the stack. ! * @param e the element to be inserted ! * @throws StackFullException if the array storing the elements is full ! */!public void push(E e) throws StackFullException { ! if (size() == data.length) throw new StackFullException("Stack is full"); ! data[++t] = e; // increment t before storing new item! }
22 Stacks
Array-Based Stack Implementation in Java - 3 /** ! * Returns, but does not remove, the element at the top of the stack. ! * @return top element in the stack (or null if empty) ! * @throws StackEmptyException if the array storing the stack is empty ! */! public E top() { ! if (isEmpty()) throw new StackEmptyException ("Stack is empty”); ! return data[t]; ! } !! /** ! * Removes and returns the top element from the stack. ! * @return element removed ! * @throws StackEmptyException if the array storing the stack is empty ! */! public E pop() { ! if (isEmpty()) throw new StackEmptyException ("Stack is empty”); ! E answer = data[t]; ! data[t] = null; // dereference to help garbage collection! t--; ! return answer; ! }
23 Stacks
Array-Based Stack Performance and Limitations q Performance
n implementation is simple and efficient w methods performed in O(1)
n Space complexity - O(N) q Limitations
n maximum capacity of the array has to be specified a priori w too large - wastage of space w too small - insufficient for a given application
n StackFullException is specific to this implementation
n StackEmptyException is required by the interface
24 Stacks
A Growable Array-Based Stack q On StackFullException, replace the array S
with a larger one and continue processing the push operations
q How large should the new array be? n tight strategy - add a constant f(N) = N+c n growth strategy - double up f(N) = 2N
25 Stacks
Algorithm push(o) if size()=N then A new array of length f(N) for i ç 0 to N-1
A[i] ç S[i] S ç A t ç t+1 S[t] ç o
Comparing Tight and Growth Strategies q cost model
n regular push - when array capacity is not exceeded; adds one element w costs 1 unit
n special push - when a new array is created and elements of the old array are copied before adding one element. w costs f(N)+N+1 units
26 Stacks
Tight Strategy (c=4) q start with an array size of 0
27 Stacks
a 4 + 1
a b 1
a b c 1
a b c d 1
a b c d e 8 + 4 + 1
a b c d e f 1
a b c d e f g 1
a b c d e f g h 1
a b c d e f g h i 1 2 + 8 + 1
a b c d e f g h i j 1
a b c d e f g h i j k 1
a b c d e f g h i j k l 1
cost of special push 2n+5 for a total of n pushes cost is O(n^2/c)
Growth Strategy (double the size) q start with an array size of 0
28 Stacks
a 1 + 0 + 1
a b 2 + 1 + 1
a b c 4 + 2 + 1
a b c d 1
a b c d e 8 + 4 + 1
a b c d e f 1
a b c d e f g 1
a b c d e f g h 1
a b c d e f g h i . 1 6 + 8 + 1
a b c d e f g h i j . 1
a b c d e f g h i j k . 1
a b c d e f g h i j k l . 1
cost of special push 3n+1 for a total of n pushes cost is O(n)
Linked List-Based Stack Implementation in Java - 1 public class LinkedStack<E> implements Stack<E> { !! /** The primary storage for elements of the stack */! private SinglyLinkedList<E> list = new SinglyLinkedList<>(); // an empty list!! /** Constructs an initially empty stack. */! public LinkedStack() { } // new stack relies on the initially empty list!! /** ! * Returns the number of elements in the stack. ! * @return number of elements in the stack ! */! public int size() { return list.size(); } !!
29 Stacks
Linked List-Based Stack Implementation in Java - 2 /** ! * Tests whether the stack is empty. ! * @return true if the stack is empty, false otherwise ! */! public boolean isEmpty() { return list.isEmpty(); } ! /** ! * Inserts an element at the top of the stack. ! * @param element the element to be inserted ! */! public void push(E element) { list.addFirst(element); } !! !
30 Stacks
Linked List-Based Stack Implementation in Java - 3 /** ! * Returns, but does not remove, the element at the top of the stack. ! * @return top element in the stack ! * @throws StackEmptyException if the list storing the stack is empty ! */! public E top() { ! if (isEmpty()) throw new StackEmptyException ("Stack is empty”); ! return list.first(); ! } ! ! /** ! * Removes and returns the top element from the stack. ! * @return element removed ! * @throws StackEmptyException if the list storing the stack is empty ! */! public E pop() { ! if (isEmpty()) throw new StackEmptyException ("Stack is empty”); ! return list.removeFirst(); ! }
31 Stacks
Applications of Stacks q Direct applications
n Page-visited history in a Web browser n Undo sequence in a text editor n Chain of method calls in the Java Virtual
Machine q Indirect applications
n Auxiliary data structure for algorithms n Component of other data structures
© 2014 Goodrich, Tamassia, Goldwasser 32 Stacks
Stacks 33
Stack Applications - Chain of Method Calls in JVM
q The Java Virtual Machine (JVM) keeps track of the chain of active methods with a stack
q When a method is called, the JVM pushes on the stack a frame containing n Local variables and return value n Program counter, keeping track of
the statement being executed q When a method ends, its frame
is popped from the stack and control is passed to the method on top of the stack
q Allows for recursion
main() { int i = 5; foo(i); }
foo(int j) { int k; k = j+1; bar(k); }
bar(int m) { … }
bar PC = 1 m = 6
foo PC = 3 j = 5 k = 6
main PC = 2 i = 5
© 2014 Goodrich, Tamassia, Goldwasser
Stack Applications- Evaluating Arithmetic Expressions
© 2014 Goodrich, Tamassia, Goldwasser Stacks 34
14 – 3 * 2 + 7 = (14 – (3 * 2) ) + 7
Operator precedence * has precedence over +/–
Associativity
operators of the same precedence group evaluated from left to right Example: (x – y) + z rather than x – (y + z)
Idea: push each operator on the stack, but first pop and perform higher and equal precedence operations.
Slide by Matt Stallmann included with permission.
Algorithm for Evaluating Expressions
© 2014 Goodrich, Tamassia, Goldwasser Stacks 35
Two stacks: q opStk holds operators q valStk holds values q Use $ as special “end of input”
token with lowest precedence Algorithm doOp()
x ← valStk.pop();y ← valStk.pop();op ← opStk.pop();valStk.push( y op x )
Algorithm repeatOps( refOp ):
while ( valStk.size() > 1 ∧ prec(refOp) ≤
prec(opStk.top()) doOp()
Algorithm EvalExp() Input: a stream of tokens representing
an arithmetic expression (with numbers)
Output: the value of the expression
while there’s another token z
if isNumber(z) then valStk.push(z)
else repeatOps(z); opStk.push(z)
repeatOps($); return valStk.top()
Slide by Matt Stallmann included with permission.
© 2014 Goodrich, Tamassia, Goldwasser Stacks 36
Algorithm on an Example Expression
14 ≤ 4 – 3 * 2 + 7 Operator ≤ has lower precedence than +/–
– ≤ 14
4
* 3 – ≤ 14
4
2 * 3 – ≤ 14
4
+
2 * 3 – ≤ 14
4
+
6 – ≤ 14
4 + ≤ 14
-2
$
7 + ≤ 14
-2
$
F $
≤ 14 5
Slide by Matt Stallmann included with permission.
Computing Spans (not in book) q Using a stack as an
auxiliary data structure in an algorithm
q Given an an array X, the span S[i] of X[i] is the maximum number of consecutive elements X[j] immediately preceding X[i] and such that X[j] ≤ X[i]
q Spans have applications to financial analysis n E.g., stock at 52-week high
© 2014 Goodrich, Tamassia, Goldwasser 37 Stacks
6 3 4 5 2 1 1 2 3 1
X S
01234567
0 1 2 3 4
Quadratic Algorithm Algorithm spans1(X, n)
Input array X of n integers Output array S of spans of X # S ← new array of n integers n for i ← 0 to n - 1 do n s ← 1 n while s ≤ i ∧ X[i - s] ≤ X[i] 1 + 2 + …+ (n - 1) s ← s + 1 1 + 2 + …+ (n - 1) S[i] ← s n return S 1
© 2014 Goodrich, Tamassia, Goldwasser 38 Stacks
Computing Spans with a Stack q We keep in a stack the
indices of the elements visible when “looking back”
q We scan the array from left to right n Let i be the current index n We pop indices from the
stack until we find index j such that X[i] < X[j]
n We set S[i] ← i - j n We push i onto the stack
© 2014 Goodrich, Tamassia, Goldwasser 39 Stacks
01234567
0 1 2 3 4 5 6 7
Stacks 40
Efficient Algorithm Algorithm spans2(X, n) #
S ← new array of n integers n A ← new empty stack 1 for i ← 0 to n - 1 do n while (¬A.isEmpty() ∧ X[A.top()] ≤ X[i] ) do n A.pop() n if A.isEmpty() then n S[i] ← i + 1 n else S[i] ← i - A.top() n A.push(i) n return S 1
q Each index of the array q Is pushed into the
stack exactly once q Is popped from
the stack at most once
q The statements in the while-loop are executed at most n times
q Algorithm spans2 runs in O(n) time
© 2014 Goodrich, Tamassia, Goldwasser
Stacks 41
Efficient Algorithm Algorithm spans2(X, n) #
S ← new array of n integers n A ← new empty stack 1 for i ← 0 to n - 1 do n while (¬A.isEmpty() ∧ X[A.top()] ≤ X[i] ) do n A.pop() n if A.isEmpty() then n S[i] ← i + 1 n else S[i] ← i - A.top() n A.push(i) n return S 1
© 2014 Goodrich, Tamassia, Goldwasser
6 3 4 5 2 1 1 2 3 1
X S
01234567
0 1 2 3 4
Java File I/O using Buffered and File Readers import java.io.*; !import java.util.Scanner; !!!public class FileScan{ ! public static void main(String[] args) throws IOException { ! Scanner s = null; ! try { ! s = new Scanner(new BufferedReader(new FileReader(“test.txt”))); ! ! while (s.hasNext()) { ! System.out.println(s.next()); ! } ! } finally { ! if (s != null) { ! s.close(); ! } ! } ! } !}
42 Java File I/O
Queues
Readings - 6.2 and 6.3
The Queue ADT q The insertion and removal routines of the
Queue ADT follow the first-in-first-out (FIFO) principle.
q Elements may be inserted at any time, but only the element which has been in the queue the longest may be removed. n Inserting an object (at the rear) – enqueue n Removing an object ( from the front) - dequeue
44 Queues
Tickets
The Queue ADT - Specification q Data Object q The queue supports the following
fundamental methods: n New():ADT – creates an empty queue n Enqueue(Q:ADT, o:element):ADT – inserts the object o at
the rear of the queue n Dequeue(Q:ADT):element – removes the object from the
front of the queue; an error occurs if the queue is empty n First(Q:ADT):element – returns, but does not remove the
object at the front of the queue; an error occurs if the queue is empty.
45 Queues
The Queue ADT - Specification q Auxiliary methods
n Size(Q:QDT):integer – returns the number of elements in the queue
n isEmpty(Q:ADT):boolean – indicates whether the queue is empty
q Axioms n Front(Enqueue(New(), v)) = v n Dequeue(Enqueue(New(), v)) = New() n Front(Enqueue(Enqueue(Q,w),v)) =
Front(Enqueue(Q,w)) n Dequeue(Enqueue(Enqueue(Q,w), v)) =
Enqueue(Dequeue(Enqueue(Q,w),v)
46 Queues
Queues 47
Example Operation Output Q enqueue(5) – (5) enqueue(3) – (5, 3) dequeue() 5 (3) enqueue(7) – (3, 7) dequeue() 3 (7) first() 7 (7) dequeue() 7 () dequeue() null () isEmpty() true () enqueue(9) – (9) enqueue(7) – (9, 7) size() 2 (9, 7) enqueue(3) – (9, 7, 3) enqueue(5) – (9, 7, 3, 5) dequeue() 9 (7, 3, 5)
© 2014 Goodrich, Tamassia, Goldwasser
Queue ADT specification in JAVA public interface Queue<E> { ! // accessor methods! int size(); // returns the number of elements in the queue! boolean isEmpty(); // returns true if the queue is empty, false otherwise! ! //manipulation methods! void enqueue(E e); // adds the element to the rear of the queue! E first() throws QueueEmptyException; // returns the first element of the queue! E dequeue() throws QueueEmptyException; // removes and returns the first element of the queue!} !
48 Queues
Array-based Queue q Use an array of size N in a circular fashion q Two variables keep track of the front and size
f index of the front element sz number of stored elements
q When the queue has fewer than N elements, array location r = (f + sz) mod N is the first empty slot past the rear of the queue
© 2014 Goodrich, Tamassia, Goldwasser 49 Queues
Q 0 1 2 r f
normal configuration
Q 0 1 2 f r
wrapped-around configuration
Queue Operations q We use the modulo operator (remainder of
division)
© 2014 Goodrich, Tamassia, Goldwasser 50 Queues
Algorithm size() return sz
Algorithm isEmpty() return (sz == 0)
Q 0 1 2 r f
Q 0 1 2 f r
Queue Operations (cont.) q Operation enqueue throws an exception if the array is
full – Implementation specific exception
© 2014 Goodrich, Tamassia, Goldwasser 51 Queues
Algorithm enqueue(o) if size() = N then throw QueueFullException else
r ← (f + sz) mod N Q[r] ← o sz ← (sz + 1)
Q 0 1 2 r f
Q 0 1 2 f r
Queue Operations (cont.) q Note that operation dequeue throws QueueEmptyException if
the queue is empty
© 2014 Goodrich, Tamassia, Goldwasser 52 Queues
Algorithm dequeue() if isEmpty() then throw QueueEmptyException else o ← Q[f] f ← (f + 1) mod N sz ← (sz - 1) return o
Q 0 1 2 r f
Q 0 1 2 f r
Array-based Implementation public class ArrayQueue<E> implements Queue<E> { ! // instance variables! public static final int CAPACITY = 1000; // default array capacity! private E[] data; // generic array used for storage! private int f = 0; // index of the front element! private int sz = 0; // current number of elements!! // constructors! public ArrayQueue() {this(CAPACITY);} // constructs queue with default capacity!! public ArrayQueue(int capacity) { // constructs queue with given capacity! data = (E[]) new Object[capacity]; // safe cast; compiler may give warning! } !! // methods! /** ! * Returns the number of elements in the queue. ! * @return number of elements in the queue ! */! public int size() { return sz; } !! public boolean isEmpty() { return (sz == 0); } // Tests whether the queue is empty.!
53 Queues
Array-based Implementation (2) ! /** ! * Inserts an element at the rear of the queue. ! * This method runs in O(1) time. ! * @param e new element to be inserted ! * @throws QueueFullException if the array storing the elements is full ! */! public void enqueue(E e) throws QueueFullException { ! if (sz == data.length) throw new QueueFullException ("Queue is full"); ! int avail = (f + sz) % data.length; // use modular arithmetic! data[avail] = e; ! sz++; ! } !! /** ! * Returns, but does not remove, the first element of the queue. ! * @return the first element of the queue ! * @throws QueueEmptyException if the array storing the elements is empty ! */! public E first() throws QueueEmptyException { ! if (isEmpty()) throws new QueueEmptyException() ; ! return data[f]; ! } !
54 Queues
Array-based Implementation (3) /** ! * Removes and returns the first element of the queue. ! * @return element removed ! * @throws QueueEmptyException if the queue is empty) ! */! public E dequeue() throws QueueEmptyException { ! if (isEmpty()) throw new QueueEmptyException (); ! E answer = data[f]; ! data[f] = null; // dereference to help garbage collection! f = (f + 1) % data.length; ! sz--; ! return answer; ! }
55 Queues
Queues 56
Applications of Queues q Direct applications
n Waiting lists, bureaucracy n Access to shared resources (e.g., printer) n Multiprogramming
q Indirect applications n Auxiliary data structure for algorithms n Component of other data structures
© 2014 Goodrich, Tamassia, Goldwasser
Application: Round Robin Schedulers q We can implement a round robin scheduler using a
queue Q by repeatedly performing the following steps:
1. e = Q.dequeue() 2. Service element e 3. Q.enqueue(e)
© 2014 Goodrich, Tamassia, Goldwasser 57 Queues
Shared Service
Queue
Enqueue Dequeue
Double-Ended Queue - Deque q Deque supports insertion and deletion from the
front and back of the queue q The deque ADT supports the following fundamental
methods n InsertFirst(Q:ADT, e:element):ADT – inserts e at the
beginning of the deque n InsertLast(Q:ADT, e:element):ADT – inserts e at the
end of the deque n RemoveFirst(Q:ADT):ADT – removes the first element n RemoveLast(Q:ADT):ADT – removes the last element n First(Q:ADT): element – returns the first element n Last(Q:ADT):element – returns the last element
58 Queues
Deque implementations q Singly linked list
q Doubly linked list
n constant time operations
59 Queues
Tail
A B C