Lecture 2: Stacks and Queues: CSE 373: Data Structures and Algorithms
Lecture 2: Stacks and Queues: CSE 373: Data Structures and Algorithms
Queues Algorithms
Project 0 Live!
- Individual assignment
- 14x content review
- GitLab/IntelliJ setup
- You should have already gotten an automatic email with a link to your gitlab repo.
- Check your spam folder
For ArrayLists and LinkedLists, what is the O() for each of these operations?
- Time needed to access element:
- Time needed to insert at end (the array is full!)
‘h’ ‘e’ ‘l’ ‘l’ ‘o’ front ‘h’ ‘e’ ‘l’ ‘l’ ‘o’ /
CSE 373 19 SU -- ROBBIE WEBER 5
List ADT tradeoffs
Time needed to access element:
- ArrayList: O(1) constant time ArrayList<Character> myArr
- LinkedList: O(N) linear time 0 1 2 3 4
Time needed to insert at element (the array is full!) ‘h’ ‘e’ ‘l’ ‘l’ ‘o’
- ArrayList: O(N) linear time
- LinkedList: O(N) linear time
0 1 2 3
push(3)
3 45
push(4)
pop()
numItems = 2
0
1
push(5)
CSE 373 19 SU - ROBBIE WEBER 9
Implementing a Stack with Nodes
Stack ADT LinkedStack<E> Big O Analysis
state state pop() O(1) Constant
Set of ordered items Node top
Number of items size
peek() O(1) Constant
behavior behavior
push add new node at top
push(item) add item to top
numItems++ size() O(1) Constant
pop() return and remove item at
pop return and remove node at
top
top, numItems-=1 isEmpty() O(1) Constant
peek() look at item at top
peek return node at top
size() count of items
size return numItems push() O(1) Constant
isEmpty() count of items is 0?
isEmpty return numItems == 0
push(3)
front 3
push(4)
pop() numItems = 0
1
2
CSE 373 19 SU - ROBBIE WEBER 10
Review: What is a Queue?
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
examine/remove the front of the queue.
front back
remove, peek add
1 2 3
Queue ADT
state supported operations:
Set of ordered items
Number of items - add(item): aka “enqueue” add an element to the back.
behavior - remove(): aka “dequeue” Remove the front element and return.
add(item) add item to back
remove() remove and return - peek(): Examine the front element without removing it.
item at front
peek() return item at front
- size(): how many items are stored in the queue?
size() count of items - isEmpty(): if 1 or more items in the queue returns true, false otherwise
isEmpty() count of items is 0?
CSE 373 19 SU - ROBBIE WEBER 11
Implementing a Queue with an Array
Queue ADT ArrayQueue<E> Big O Analysis
state state remove() O(1) Constant
Set of ordered items data[]
Number of items numItems
peek() O(1) Constant
front index
behavior back index
add(item) add item to back size() O(1) Constant
remove() remove and return behavior
add – data[back] = value, if out of
item at front
room grow data, back++, numItems++ isEmpty() O(1) Constant
peek() return item at front
remove – return data[front],
size() count of items
numItems-=1, front++ add() Don’t resize: O(1) Constant
isEmpty() count of items is 0?
peek – return data[front] Do resize: O(N) linear
size – return numItems
isEmpty – return numItems == 0
0 1 2 3 4
add(5) 5 8 9
add(8)
numItems = 3
2
1
0
add(9) front = 01
remove() back = 0
2
1 CSE 373 19 SU - ROBBIE WEBER 12
Implementing a Queue with an Array
> Wrapping Around
front back
add(7)
add(4) 0 1 2 3 4
add(1) 4 5 9 2 7
0 1 2 3 4 5 6 7 8 9
5 9 2 7 4 1
CSE 373 19 SU - ROBBIE WEBER 13
Implementing a Queue with Nodes
Queue ADT LinkedQueue<E> Big O Analysis
state state remove() O(1) Constant
Set of ordered items Node front
Number of items Node back
peek() O(1) Constant
numItems
behavior
add(item) add item to back size() O(1) Constant
remove() remove and return behavior
add – add node to back, numItems++
item at front
remove – return and remove node at isEmpty() O(1) Constant
peek() return item at front
size() count of items front, numItems--
isEmpty() count of items is 0? peek – return node at front add() O(1) Constant
size – return numItems
isEmpty – return numItems == 0
numItems = 2
0
1
add(5)
add(8) front 5 8
remove() back
CSE 373 19 SU - ROBBIE WEBER 14
Multiple Levels of Design Decisions
Implementation Details
- Do we overwrite old values with null or do we leave the garbage value?
- Do we validate input and throw exceptions or just wait for the code to fail?
Choice of ADT
- Which of the ADTs that we’ve seen is the best fit?
Discuss with your neighbors: For each scenario select the appropriate ADT and implementation
to best optimize for the given scenario.
Situation #1: You are writing a program to manage a todo list with a specific approach to tasks.
This program will order tasks for so that the most recent task is addressed first. You don’t want to
risk a long delay between submission of an item and its appearance.
Stack – First in Last out
Nodes – make addition and removal of tasks very easy
Situation #2: You are writing a program to schedule jobs sent to a laser printer. The laser printer
should process these jobs in the order in which the requests were received. The printer has very
limited memory.
Queue – First in First out
Array – want to save the extra pointers to fit in our limited space
In the real world, coding projects don’t come with their own tests.
- You have to write your own.
You might be frustrated with us at some point for not giving you test cases.
- I understand. I was frustrated with my data structures professor when she didn’t give us tests.
- Learning to test your own code is integral to maturing as a computer scientist.
- We’re always tweaking things to make this as painless as we can.
Software Test: a separate piece of code that exercises the code you are assessing by providing
input to your code and finishes with an assertion of what the result should be.
White Box
- Includes an understanding of the implementation
- Written by the author as they develop their code
- Break apart requirements into smaller steps
- “unit tests” break implementation into single assertions
Forbidden Input
- What are all the ways the user can mess up?
Empty/Null
- Protect yourself!
- How do things get started?
- 0, -1, null, empty collections
Boundary/Edge Cases
- First items
- Last item
- Full collections (resizing)
Scale
- Is there a difference between 10, 100, 1000, 10000 items?
Trust no one!
- How can the user mess up?
Assertions:
- assertThat(thingYoureTesting, is(ExpectedResult)) is most common. Calls .equals() method
- May write your own helper methods here to check that internal state is identical.
- Other assertions exist; see official documentation, or our documentation on the webpage.
- a.k.a. "dictionary"
map.get("the") 56
supported operations:
Dictionary ADT
- put(key, value): Adds a given item into
state collection with associated key, if the
Set of items & keys map previously had a mapping for the
Count of items given key, old value is replaced
behavior
put(key, item) add item to - get(key): Retrieves the value mapped to
collection indexed with key
get(key) return item associated
the key
with key - containsKey(key): returns true if key is
containsKey(key) return if key
already in use
already associated with value in map,
remove(key) remove item and false otherwise
associated key
size() return count of items
- remove(key): Removes the given key
and its mapped value
CSE 373 19 SU - ROBBIE WEBER 29
2 Minutes
Implementing a Dictionary with an Array
Dictionary ADT ArrayDictionary<K, V> Big O Analysis
state state put() O(N) linear
Set of items & keys Pair<K, V>[] data
Count of items
get() O(N) linear
behavior behavior
containsKey() O(N) linear
put create new pair, add to
put(key, item) add item to next available spot, grow
collection indexed with key array if necessary
get(key) return item associated get scan all pairs looking remove() O(N) linear
with key for given key, return
containsKey(key) return if key associated item if found size() O(1) constant
already in use containsKey scan all pairs,
remove(key) remove item and return if key is found
associated key remove scan all pairs,
size() return count of items replace pair to be removed
with last pair in collection
size return count of items in
put(‘a’, 1) dictionary
put(‘b’, 2)
put(‘c’, 3) 0 1 2 3
put(‘d’, 4)
97)
(‘a’, 1) (‘b’, 2) (‘c’, 3) (‘d’, 4)
remove(‘b’)
put(‘a’, 97) CSE 373 19 SU - ROBBIE WEBER 30
2 Minutes
Implementing a Dictionary with Nodes
Dictionary ADT LinkedDictionary<K, V> Big O Analysis
state state put() O(N) linear
Set of items & keys front
Count of items size
get() O(N) linear
behavior behavior
containsKey() O(N) linear
put if key is unused, create new with
put(key, item) add item to
pair, add to front of list, else
collection indexed with key
replace with new value
get(key) return item associated
get scan all pairs looking for given remove() O(N) linear
with key
key, return associated item if found
containsKey(key) return if key
containsKey scan all pairs, return if size() O(1) constant
already in use
key is found
remove(key) remove item and
remove scan all pairs, skip pair to be
associated key
removed
size() return count of items
size return count of items in
dictionary
put(‘a’, 1)
put(‘b’, 2) front
put(‘c’, 3)
put(‘d’, 4)
remove(‘b’) ‘d’ 4 ‘c’ 3 ‘b’ 2 ‘a’ 97
1
put(‘a’, 97) CSE 373 19 SU - ROBBIE WEBER 31