# Elementary Data Structures --- CS 137 // 2021-09-13 ## Administrivia - You should have turned in: + Your reflection for daily exercise 2 + Your solution to daily exercise 3 # Questions ## ...about anything? # Daily Exercise # Elementary Data Structures ## Elementary Data Structures - Lists, stacks, and queues are all "off the shelf" data structures to employ in algorithms - Each data structure has two aspects: 1. The **abstract operations** it supports. 2. Its **implementation** of those operations. ## Abstract Data Types - What operations does a **list** have? + `append`, `get`, `remove`, ... - What about a **stack**? + `pop`, `push`, ... - What about a **queue**? + `enqueue`, `dequeue`, ... - Reasoning about these ADTs abstractly makes them easier to think about ## Implementations - What are the common **implementations** of sequential ADTs like lists, stacks, and queues? + **Contiguous**: Uses a single slab of memory to contain all elements (e.g., an array) + **Linked**: Composed of multiple, distinct, chunks of memory connected by *pointers* ## Sequential Comparison | **Operation** | **Array** | **Linked** | |-----------------|-----------|------------| | `add to front` | ??? | ??? | | `add to back` | ??? | ??? | | `remove front` | ??? | ??? | | `remove back` | ??? | ??? | | `random access` | ??? | ??? | ## Array List - An **array list** is an implementation of a sequential data structure using *dynamic arrays* - If the array is full when a new value is added, a **new** array is created with twice as many elements + Worst-case runtime of insertion is $O(n)$ since it is possible to need to copy the entire array ## Amortized Analysis - What is the worst-case complexity of making $n$ insertions into an array list? + $n$ copies during the last insertion + $\frac{n}{2}$ more from the previous copy + $\frac{n}{4}$ more from the one before that + ... - Total: $n + \frac{n}{2} + \frac{n}{4} + \cdots + 1 = n\left(\sum_{i=0}^{\log n} 2^{-i}\right)$ ## Amortized Analysis - $\sum_{i=0}^\infty 2^{-i} = 2$, the total number of copies is $2n$ - Thus, inserting $n$ elements is $O(n)$ - We say that a single add is $O(1)$ **amortized time** since $n$ insertions is guaranteed to take $O(n)$ time - Array lists are commonly preferred over linked lists unless insertions need a guarantee of $O(1)$ time ## Comparison, Revisited | **Operation** | **Array** | **Linked** | |-----------------|-----------|------------| | `add to front` | O(n) | O(1) | | `add to back` | O(1)* | O(1) | | `remove front` | O(n) | O(1) | | `remove back` | O(1) | O(1) | | `random access` | O(1) | O(n) | --- \* means *amortized* constant time ## Improving Array List - Is it possible to improve the $O(n)$-time removal of the first element of an array list? - Discuss with your neighbors any ideas that you have + You **must** use an array as a back-end ## Double-Ended Queue - A **Double-Ended Queue** (a.k.a. **Deque**) is a data structure with operations to add/remove elements from the front and back of the container - A deque can be implemented with an array or linked structure, but an array is commonly used - Operations for add front, add back, remove front, and remove back are all **amortized $O(1)$** - Removing in the middle is still $O(n)$ ## Deques in the Wild - In Java, `java.util.ArrayDeque` is such an implementation - In Python, `collections.deque` is such an implementation # Dictionaries ## Dictionaries - Another common ADT is the **dictionary** which provides a useful interface for *associative data* + "Keys" are associated with "values" - What operations should a dictionary support? + `insert`, `search`, `delete` - How could we implement a dictionary? ## Dictionary Comparison - We could use an array (or linked list) of key/value pairs to implement a dictionary - We could use unsorted or sorted arrays --- | **Operation** | **Unsorted** | **Sorted** | |-----------------|--------------|------------| | `search` | ??? | ??? | | `insert` | ??? | ??? | | `delete` | ??? | ??? |