Presentation is loading. Please wait.

Presentation is loading. Please wait.

Generics, Stack, Queue Based on slides by Alyssa Harding

Similar presentations


Presentation on theme: "Generics, Stack, Queue Based on slides by Alyssa Harding"— Presentation transcript:

1 Generics, Stack, Queue Based on slides by Alyssa Harding
CSE 143 Lecture 10 Generics, Stack, Queue Based on slides by Alyssa Harding

2 Review: ArrayIntList client
Now that we’ve built ArrayIntList , we can be its client ArrayIntList list1 = new ArrayIntList(); list1.add(42); list1.add(7); list1.add(-10); for (int i = 0; i < list1.size(); i++) { System.out.println(list1.get(i)); } 2

3 Generics But what if we want to have a list of Strings?
We could copy ArrayIntList and change it into ArrayStringList… Java to the rescue: Generics! Redundant! 3

4 ArrayList<E> uses Generics
<E> is a type parameter

5 ArrayList<E> ArrayList<E> has all the methods we want:
// adds given value to end of list void add(E value) // adds given value at the given index void add(E value, int index) // removes value at the given index void remove(int index) // returns value at given index E get(int index) // returns size of list int size() E is the Element type 5

6 ArrayList<E> Now we can create and use a list of any type of Object: ArrayList<String> list = new ArrayList<String>(); list.add(“hello”); String s = list.get(0); However, this only works for Objects, not primitive data types, such as ints or doubles 6

7 Wrapper classes Java has classes that wrap the primitive types in objects: Example of autoboxing: ArrayList<Integer> list = new ArrayList<Integer>(); list.add(42); int x = list.get(0); primitive type object type int Integer double Double char Character boolean Boolean 7

8 ArrayList<E> client
Now we can get back to our client code ArrayList<Integer> list1 = new ArrayList<Integer>(); list1.add(42); list1.add(7); list1.add(-10); for (int i = 0; i < list1.size(); i++) { System.out.println(list1.get(i)); } 8

9 Stacks & Queues

10 Stacks and Queues Sometimes it is good to have a collection that is less powerful, but is optimized to perform certain operations very quickly. Today we will examine two specialty collections: stack: Retrieves elements in the reverse of the order they were added. queue: Retrieves elements in the same order they were added. queue stack

11 Abstract data types (ADTs)
abstract data type (ADT): A specification of a collection of data and the operations that can be performed on it. Describes what a collection does, not how it does it We don't know exactly how a stack or queue is implemented, and we don't need to. We just need to understand the idea of the collection and what operations it can perform. (Stacks are usually implemented with arrays; queues are often implemented with a linked list.)

12 Stacks stack: A collection based on the principle of adding elements and retrieving them in the opposite order. Last-In, First-Out ("LIFO") The elements are stored in order of insertion, but we do not think of them as having indexes. The client can only add/remove the last element added (the "top"). basic stack operations: push: Add an element to the top. pop: Remove the top element. analogy: trays of food at the sizzler

13 Stacks in computer science
Programming languages and compilers: method calls are placed onto a stack (call=push, return=pop) compilers use stacks to evaluate expressions Matching up related pairs of things: find out whether a string is a palindrome examine a file to see if its braces { } and other operators match convert "infix" expressions to "postfix" or "prefix" Sophisticated algorithms: searching through a maze with "backtracking" many programs use an "undo stack" of previous operations method3 return var local vars parameters method2 method1

14 Queues queue: Retrieves elements in the order they were added.
First-In, First-Out ("FIFO") Elements are stored in order of insertion but don't have indexes. Client can only add to the end of the queue, and can only remove the front of the queue. basic queue operations: enqueue: Add an element to the back. dequeue: Remove the front element. queue analogy: trays of food at the sizzler

15 Queues in computer science
Operating systems: queue of print jobs to send to the printer queue of programs / processes to be run queue of network data packets to send Programming: modeling a line of customers or clients storing a queue of computations to be performed in order Real world examples: people on an escalator or waiting in a line cars at a gas station (or on an assembly line)

16 Stacks Stacks are a Last In First Out (LIFO) structure
// add value to the top of the stack void push(E value) // remove and return the value at the top E pop() // return the size int size() // return whether the stack is empty boolean isEmpty()

17 Queues Queues are a First In First Out (FIFO) structure
// add value to the back of the queue void enqueue(E value) // remove and return the value at the front E dequeue() // return the size int size() // return whether the queue is empty boolean isEmpty()

18 Interfaces & Implementations
Important!! We’re using our own Stack<E> and Queue<E> interfaces We’re using our own ArrayStack<E> and LinkedQueue<E> implementations (classes) We are using generics with both the interfaces and the implementations, so we can store any type of Object in them Note: There are other implementations (and interfaces) of stacks and queues in the Java collections. They have more method and use different names for the methods. We are NOT using these!

19 Our Stack Interface public interface Stack<E> {
public void push(E value); public E pop(); public int size(); public boolean isEmpty(); }

20 Our Queue Interface public interface Queue<E> {
public void enqueue(E value); public E dequeue(); public int size(); public boolean isEmpty(); }

21 Stack and Queue client Stack<Integer> s = new ArrayStack<Integer>(); Queue<Integer> q = new LinkedQueue<Integer>(); for (int i = 0; i < 3; i++) { s.push(i); q.enqueue(i); } System.out.println("stack = " + s); System.out.println("queue = " + q); 21

22 What does this do? Stack<Integer> s = new ArrayStack<Integer>(); Queue<Integer> q = new LinkedQueue<Integer>(); for (int i = 0; i < 3; i++) { s.push(i); q.enqueue(i); } System.out.println(s.pop()); System.out.println("stack = " + s); System.out.println(q.dequeue()); System.out.println("queue = " + q); 22

23 Stack and Queue client methods: fillQueue
We might want to fill a Queue with values: public static Queue<Integer> fillQueue(int n) { Queue<Integer> q = new LinkedQueue<Integer>(); return q; } Note that the variable declaration and return value use the interface type

24 Stack and Queue client methods: fillQueue
We might want to fill a Queue with values: public static Queue<Integer> fillQueue(int n) { Queue<Integer> q = new LinkedQueue<Integer>(); for (int i = 0; i < n; i++) { q.enqueue(i); } return q; } Note that the variable declaration and return value use the interface type 24

25 Stack and Queue client methods: queueToStack
We might want to move values from a Queue to a Stack: public static void queueToStack( Queue<Integer> q, Stack<Integer> s) { while ( ) { }

26 Stack and Queue client methods: queueToStack
We might want to move values from a Queue to a Stack: public static void queueToStack( Queue<Integer> q, Stack<Integer> s) { while ( !q.isEmpty() ) { int n = q.dequeue(); s.push(n); } } Boolean zen! 26

27 Stack and Queue client methods: sum (first attempt)
We might want to sum the values in a Queue: public static int sum(Queue<Integer> q) { int sum = 0; while ( !q.isEmpty() ) { sum += q.dequeue(); } return sum; } 27

28 Stack and Queue client methods: sum (first attempt)
We might want to sum the values in a Queue: public static int sum(Queue<Integer> q) { int sum = 0; while ( !q.isEmpty() ) { sum += q.dequeue(); } return sum; } But this destroys the Queue and leaves it empty!

29 Stack and Queue client methods: sum (2nd attempt)
We might want to sum the values in a Queue: public static int sum(Queue<Integer> q) { int sum = 0; for ( ) { } return sum; } 29

30 Stack and Queue client methods: sum
We might want to sum the values in a Queue: public static int sum(Queue<Integer> q) { int sum = 0; for (int i = 0; i < q.size(); i++) { int n = q.dequeue(); sum += n; q.enqueue(n); } return sum; } So we store values back in the Queue and loop the correct number of times.

31 Stack and Queue client methods: fillStack
We might also want to fill a Stack: public static Stack<Integer> fillStack(int n) { Stack<Integer> s = new ArrayStack<Integer>(); for (int i = 0; i < n; i++) return s; } We can copy the Queue code and change it to use a Stack. 31

32 Stack and Queue client methods: fillStack
We might also want to fill a Stack: public static Stack<Integer> fillStack(int n) { Stack<Integer> s = new ArrayStack<Integer>(); for (int i = 0; i < n; i++) s.push(i); return s; } We can copy the Queue code and change it to use a Stack.

33 Stack and Queue client methods: stackToQueue
We might also want to move values from a Stack to a Queue: public static void stackToQueue( Stack<Integer> s, Queue<Integer> q) { while ( !s.isEmpty() ) { int n = s.pop(); q.enqueue(n); } } We can copy the Queue code and change it to use a Stack.

34 Stack and Queue client methods: sum (first attempt)
We might want to sum the values in a Stack: public static int sum(Stack<Integer> s) { int sum = 0; for (int i = 0; i < s.size(); i++) { int n = s.pop(); sum += n; s.push(n); } return sum; } What is wrong with this code?

35 Stack and Queue client methods: sum (first attempt)
We might want to sum the values in a Stack: public static int sum(Stack<Integer> s) { int sum = 0; for (int i = 0; i < s.size(); i++) { int n = s.pop(); sum += n; s.push(n); } return sum; } But if we copy the Queue code, we push and pop the same value over and over. 35

36 Stack and Queue client methods: sum (2nd attempt)
We might want to sum the values in a Stack: public static int sum(Stack<Integer> s) { int sum = 0; Queue<Integer> q = new LinkedQueue<Integer>(); for (int i = 0; i < s.size(); i++) { int n = s.pop(); sum += n; q.enqueue(n); } queueToStack(q,s); return sum; } Does this work?

37 Stack and Queue client methods: sum (2nd attempt)
We might want to sum the values in a Stack: public static int sum(Stack<Integer> s) { int sum = 0; Queue<Integer> q = new LinkedQueue<Integer>(); for (int i = 0; i < s.size(); i++) { int n = s.pop(); sum += n; q.enqueue(n); } queueToStack(q,s); return sum; } Even though we store values in a Queue, i increases and s.size() decreases, so we only examine half the values 37

38 Stack and Queue client methods: sum (3rd attempt)
We might want to sum the values in a Stack: public static int sum(Stack<Integer> s) { int sum = 0; Queue<Integer> q = new LinkedQueue<Integer>(); while ( !s.isEmpty() ) { int n = s.pop(); sum += n; q.enqueue(n); } queueToStack(q,s); return sum; } Does this work?

39 Stack and Queue client methods: sum (3rd attempt)
We might want to sum the values in a Stack: public static int sum(Stack<Integer> s) { int sum = 0; Queue<Integer> q = new LinkedQueue<Integer>(); while ( !s.isEmpty() ) { int n = s.pop(); sum += n; q.enqueue(n); } queueToStack(q,s); return sum; } Now the sum is correct, but our resulting Stack is reversed! This happens when we transfer from a Stack to Queue and back. 39

40 Stack and Queue client methods: sum (final version)
We might want to sum the values in a Stack: public static int sum(Stack<Integer> s) { int sum = 0; Queue<Integer> q = new LinkedQueue<Integer>(); while ( !s.isEmpty() ) { int n = s.pop(); sum += n; q.enqueue(n); } queueToStack(q,s); stackToQueue(s,q); queueToStack(q,s); return sum; } Now both the sum and the Stack are correct.

41 Stack and Queue client methods: findMin
We might want to find the minimum value in a Stack: public static int findMin(Stack<Integer> s) { int min = 0; Queue<Integer> q = new LinkedQueue<Integer>(); while ( !s.isEmpty() ) { int n = s.pop(); if ( n < min ) min = n; q.enqueue(n); } queueToStack(q,s); stackToQueue(s,q); queueToStack(q,s); return min; } Does this work? 41

42 Stack and Queue client methods: findMin
We might want to find the minimum value in a Stack: public static int findMin(Stack<Integer> s) { int min = 0; Queue<Integer> q = new LinkedQueue<Integer>(); while ( !s.isEmpty() ) { int n = s.pop(); if ( n < min ) min = n; q.enqueue(n); } queueToStack(q,s); stackToQueue(s,q); queueToStack(q,s); return min; } What if the values in the Stack are all greater than 0? This would still return 0 as the minimum.

43 Stack and Queue client methods: findMin(final version)
We might want to find the minimum value in a Stack: public static int findMin(Stack<Integer> s) { Queue<Integer> q = new LinkedQueue<Integer>(); int min = s.pop(); s.push(min); while ( !s.isEmpty() ) { int n = s.pop(); if ( n < min ) min = n; q.enqueue(n); } queueToStack(q,s); stackToQueue(s,q); queueToStack(q,s); return min; } Instead, we start our minimum at a value that is in the Stack.

44 Preconditions Remember the precondition of Stack’s pop method?
The Stack cannot be empty when we call pop Since we call pop in our method without checking that the Stack isn’t empty, our method has this precondition too

45 Preconditions How are we going to deal with this?
We need to return a value, but what would we return if we were passed an empty Stack? We can comment this precondition, but that doesn’t stop clients from using our method incorrectly

46 Exceptions Java lets us throw exceptions in our methods:
throw new <exception type here>(); In this case, we want to throw an exception if the method was given an illegal argument, so we throw an IllegalArgumentException: if ( s.isEmpty() ) throw new IllegalArgumentException();

47 Exceptions Always comment the type and cause of any exceptions you throw: // throws IllegalArgumentException if the // stack is empty


Download ppt "Generics, Stack, Queue Based on slides by Alyssa Harding"

Similar presentations


Ads by Google