CSE 250 Lecture 7-9
Transcript of CSE 250 Lecture 7-9
Fall 2021 ©Oliver Kennedy, Andrew HughesThe University at Buffalo, SUNY 1 / 28
CSE 250Lecture 7-9ADTs, Sequences, Arrays, and Linked ListsTextbook Ch. 1.7.2
This container provides O(1) access to a cat
Fall 2021 ©Oliver Kennedy, Andrew HughesThe University at Buffalo, SUNY 2 / 28
Sequences
● The Fibonacci Sequence
– 1, 1, 2, 3, 5, 8, 13, 21, 34, 55● Characters of a String
– ‘H’, ‘e’, ‘l’, ‘l’, ‘o’, ‘ ‘, ‘W’, ‘o’, ‘r’, ‘l’, ‘d’● Lines of a file...
A common way to store data is as a sequence
Fall 2021 ©Oliver Kennedy, Andrew HughesThe University at Buffalo, SUNY 3 / 28
What can you do with a Sequence?
● Get the first element● Enumerate every element of the sequence● Update the n’th element
Fall 2021 ©Oliver Kennedy, Andrew HughesThe University at Buffalo, SUNY 4 / 28
read nth item
read all items
update nth item
Abstract Data Types (ADTs)
Data in anopaque box
(no specified layout)
Access governed by semantics (what), not implementation (how)
Fall 2021 ©Oliver Kennedy, Andrew HughesThe University at Buffalo, SUNY 5 / 28
Immutable Sequence ADTs
● apply(idx: Int): A
– Get the element (of type A) at position idx.● iterator: Iterator[A]
– Get access to view all elements in the seq, in order, once.● length: Int
– Count the number of elements in the seq.
Fall 2021 ©Oliver Kennedy, Andrew HughesThe University at Buffalo, SUNY 6 / 28
Mutable Sequence ADTs
● apply(idx: Int): A
– Get the element (of type A) at position idx.● iterator: Iterator[A]
– Get access to view all elements in the seq, in order, once.● length: Int
– Count the number of elements in the seq.● insert(idx: Int, elem: A): Unit
– Insert the element at position idx with the value elem.● remove(idx: Int): Unit
– Remove the element at position idx.
Fall 2021 ©Oliver Kennedy, Andrew HughesThe University at Buffalo, SUNY 7 / 28
Implementation via Array
● Positives
– Fast random access– Access as a sequence (default functionality exists)
● Drawbacks
– Fixed size (can’t exceed prespecified size)– “Empty” values (wasted memory)
Fall 2021 ©Oliver Kennedy, Andrew HughesThe University at Buffalo, SUNY 8 / 28
Implementation via Array
● Things to think about…
– What happens when we run out of space?– How can an array location be empty?– How are insert and remove handled?
Let’s see an example!
Fall 2021 ©Oliver Kennedy, Andrew HughesThe University at Buffalo, SUNY 9 / 28
Implementation via Array
● The Apply Method
– Used to retrieve values in the array– Check if we are out of bounds and raise exception– One apply operation on array: O(1) runtime
● The Update Method
– Used to update values in the array– Check if we are out of bounds and raise exception– One update operation on array: O(1) runtime
Fall 2021 ©Oliver Kennedy, Andrew HughesThe University at Buffalo, SUNY 10 / 28
Implementation via Array
● The length method
– Returns the number of allocated elements (not capacity)– Always maintained in a precomputed variable
Fall 2021 ©Oliver Kennedy, Andrew HughesThe University at Buffalo, SUNY 11 / 28
Indexed Based Operations
● Index-based Insertion
– Check if the position is valid and throw error if not
– Check if the array has capacity and reserve more space if not.
– From end – 1 to idx, shift right by one
– Assign idx the inserted value
– Increase size by 1● Index-based Removal
– Check if the position is valid and throw error if not
– From idx+1 to end, shift left by one
– Decrease size by 1
Worst-case, O(n) runtime
Fall 2021 ©Oliver Kennedy, Andrew HughesThe University at Buffalo, SUNY 12 / 28
Reserving Space
● Challenge: Allow “Variable-Size” Arrays
– Reserve more space as insertions occur● Allocate new, bigger array (usually doubling capacity)● Copy every element from old to new array● Discard old array
Θ(n) runtimen = number of elements in storage
Fall 2021 ©Oliver Kennedy, Andrew HughesThe University at Buffalo, SUNY 13 / 28
Inserting at End
● What is the cost to fill an ArrayList?
– Suppose we always insert at the end of the array● with n = the number of elements we’re inserting...
– Worst case, we need to reserve space for each insert● O(n) runtime
– n total insertions● O(n2) runtime
Fall 2021 ©Oliver Kennedy, Andrew HughesThe University at Buffalo, SUNY 14 / 28
Can we do better than O(n2)
● Example!
– insert(0, )🤺– insert(1, )🤹– insert(2, )🧟– …
● When do we need to reserve memory?
– … always at powers of 2.
Fall 2021 ©Oliver Kennedy, Andrew HughesThe University at Buffalo, SUNY 15 / 28
Runtime Cost for n Appends
● Cost for adding to end
– nothing to shift right ( Θ(1) )● Cost for reserving space
– potentially O(size) – … but doesn’t occur at every insert
● Only when size = 0 or 2k
Fall 2021 ©Oliver Kennedy, Andrew HughesThe University at Buffalo, SUNY 16 / 28
Runtime Cost for Appendsi = 1 reserve(1) 0 moved
i = 2 reserve(2) 1 moved
i = 3 reserve(4) 2 moved
i = 4 ... ...
i = 5 reserve(8) 4 moved
... ... ...
i = 9 reserve(16) 8 moved
... ... ...
i = 2j+1 reserve(2j+1) 2j moved
... … ...
i = n depends on n depends on n
Fall 2021 ©Oliver Kennedy, Andrew HughesThe University at Buffalo, SUNY 17 / 28
Runtime Cost for Appends
● Suppose n = 2k+1 for some k ∈ Z+ (worst case, requires doubling on last insertion)
● Insertion costs
– n operations, O(1) each
● Doubling cost
– Double at every i where i=2j+1 for some j
● First: j = 0● Last: j = k (where k = highest j s.t. 2j < n● Remember n = 2k+1
– Cost to reserve:
● 2i at each doubling
Fall 2021 ©Oliver Kennedy, Andrew HughesThe University at Buffalo, SUNY 18 / 28
Runtime Cost for Appends
● T(n) = insert cost + reserve cost = Θ(n) + Θ(n) = Θ(n)
● Append runtime is Amortized O(1)
– Runtime for one append is O(n)
– Runtime for n appends is Θ(n)● “Amortized” describes runtime over the long run.
– reserve is only called log(n) times (very infrequently)– Not quite the same as the “average” case
● Average case is the expected runtime over any input● Here, Θ(n) is the runtime.
Amortized → Upfront costs paid off over time
Fall 2021 ©Oliver Kennedy, Andrew HughesThe University at Buffalo, SUNY 19 / 28
ArrayList
● Pros
– Constant Access/Update Time– Amortized Constant Append
● Cons
– O(n) insert, remove– O(n) for one append
Fall 2021 ©Oliver Kennedy, Andrew HughesThe University at Buffalo, SUNY 20 / 28
Linked Lists
class SingleLinkedNode[A]( var _data: A, var _next: SingleLinkedNode[A])
Fall 2021 ©Oliver Kennedy, Andrew HughesThe University at Buffalo, SUNY 21 / 28
Linked List Example
// Allocate space on-demandvar head = new cse250.objects.SingleLinkedNode(1, null)var temp = headtemp.next = new cse250.objects.SingleLinkedNode(2, null)temp = temp._nexttemp.next = new cse250.objects.SingleLinkedNode(3, null)temp = temp._next// Deallocate space on-demandtemp = head._nexthead = temptemp = head._nexthead = temptemp = head._nexthead = temp
Fall 2021 ©Oliver Kennedy, Andrew HughesThe University at Buffalo, SUNY 22 / 28
Linked Lists
● What if we need to move backwards in the list?
class DoubleLinkedNode[A]( var _data: A, var _prev: DoubleLinkedNode[A], var _next: DoubleLinkedNode[A])
Fall 2021 ©Oliver Kennedy, Andrew HughesThe University at Buffalo, SUNY 23 / 28
Doubly Linked List Example
// Allocate space on-demandvar head = new cse250.objects.DoubleLinkedNode(1, null, null)var temp = headtemp.next = new cse250.objects.DoubleLinkedNode(2, temp, null)temp = temp._nexttemp.next = new cse250.objects.DoubleLinkedNode(3, temp, null)temp = temp._next// Deallocate space on-demandtemp = head._nexthead = temphead._prev = nulltemp = head._nexthead = temphead._prev = nulltemp = head._nexthead = temp
Fall 2021 ©Oliver Kennedy, Andrew HughesThe University at Buffalo, SUNY 24 / 28
// Start with a 3-element doubly-linked listvar ptr = head._next // initialize pointer
// Append one elementvar temp = new cse250.objects.DoubleLinkedNode(42, ptr._prev, ptr)ptr._prev = temptemp._prev._next = temp
Positional Access Example
Fall 2021 ©Oliver Kennedy, Andrew HughesThe University at Buffalo, SUNY 25 / 28
List Container
● Member Variables
– _headNode: First element in the list
– _tailNode: Last element in the list
– _size: Number of nodes in the list
● Positional operations
– insert: Add a value at the provided position
– remove: Remove value at the provided position
● Index-based operations
– apply: return the ith element of the list
– update: modify the ith element of the list
– insert: insert element at the ith position of the list
– remove: remove the element at the ith position in the list
Fall 2021 ©Oliver Kennedy, Andrew HughesThe University at Buffalo, SUNY 26 / 28
ArrayList vs LinkedList
● ArrayList
– Random Access– Contiguous Memory– Easy to understand implementation
● LinkedList
– Efficient positional access– Allocate on demand
Fall 2021 ©Oliver Kennedy, Andrew HughesThe University at Buffalo, SUNY 27 / 28
Iteration
● ArrayList
– Iteration is Θ(n)– Access may be faster (‘data locality’)
● LinkedList
– Iteration is Θ(n)– Access may be slower; data scattered around memory
Fall 2021 ©Oliver Kennedy, Andrew HughesThe University at Buffalo, SUNY 28 / 28
Overview
Function Array LL by Index LL by Position
apply Θ(1) Θ(i) Θ(1)
update Θ(1) Θ(i) Θ(1)
insert O(n) Θ(i) Θ(1)
remove O(n) Θ(i) Θ(1)
append Amortized O(1) Θ(1) Θ(1)