|
| 1 | +## Lesson on Stacks and Queues |
| 2 | +### Introduction on How a Computer Operates |
| 3 | +* Storage vs Memory |
| 4 | +* Analagous to a workspace |
| 5 | +* The desk is the memory and the shelf is the storage |
| 6 | + * To get something from your desk its quick and right in front of you |
| 7 | + * To get something from your shelf its slow and tedious |
| 8 | + * However, your shelf can store significantly more and your desk is usually wiped clean at the end of the day |
| 9 | +* Analagously, memory is quick to retrieve from and storage is slow to access |
| 10 | +* However storage can store more and memory can not store anything once the power is off |
| 11 | +* Specifically, reading and writing to a specific area of the shelf is usually around linear time while accessing the memory is constant time |
| 12 | + * This is why its called the **Random** Access Memory |
| 13 | + * The only thing you need to retrieve something from the RAM is the address |
| 14 | + |
| 15 | +### Stacks |
| 16 | +* This is most likely the simplest **abstract data type** (ADT) |
| 17 | +* Imagine this as a stack of plates with a description written on every one of them |
| 18 | + * This is called First In Last Out (FILO) |
| 19 | +* Only three operations: pop, push and peak, all of which are constant time |
| 20 | +* Popping returns the top-most plate as well as removes it from the stack |
| 21 | +* Pushing puts something on the top of the stack |
| 22 | +* Peaking returns the top item but does not remove it from the top (essentially popping then pushing is back) |
| 23 | +* Pro: fast at reading and writing things at the top of the stack |
| 24 | +* Cons: Slow at reading and writing anything in the middle of the stack and at the beginning of the stack |
| 25 | +* In theory: |
| 26 | + * It starts at a given index, call this index i |
| 27 | + * On push, increment i by 1 and push the item at the given element |
| 28 | + * On pop, decrement i by 1 and delete the item and return it |
| 29 | + * On peak, simply ignore i and return the last element |
| 30 | + |
| 31 | +```python |
| 32 | +# Simple implementation of a stack (practical idea not what it theoretically actually is) |
| 33 | + |
| 34 | +class Stack: |
| 35 | + |
| 36 | + def __init__(self): |
| 37 | + self.list = [] |
| 38 | + self.length = 0 # this is kinda optional |
| 39 | + def push(self, item): |
| 40 | + self.list.append(item) |
| 41 | + def pop(self): |
| 42 | + return self.list.pop() |
| 43 | + def peak(self): |
| 44 | + if self.length > 0: |
| 45 | + return self.list[-1] |
| 46 | + return None |
| 47 | + |
| 48 | +``` |
| 49 | + |
| 50 | +In Python, this is more or less just a list |
| 51 | + |
| 52 | +Practice problem: https://dmoj.ca/problem/ccc13s2 |
| 53 | + |
| 54 | +### Queue |
| 55 | +* Also likely the simplest ADT |
| 56 | +* Imagine a lineup at a concession stand |
| 57 | + * Only the front most person can leave the line and you can only leave through the back of the line |
| 58 | + * This is called First In First Out (FIFO) |
| 59 | +* Also only three operations: pop, push and peak, all of which are constant time |
| 60 | +* Popping returns the front-most person in the line as well as removes the person from the line |
| 61 | +* Pushing puts someone at the back of the line |
| 62 | +* Peaking returns the front-most person but does not remove them (essentially popping then pushing is back) |
| 63 | +* Pro: fast at reading things at the front of the queue and putting things at the back |
| 64 | + * This is crucial for BFS as you will see later on |
| 65 | + * For example: suppose you want to capitalize every name in a file directory only with a specified depth, this can be done with a queue |
| 66 | +* Cons: Slow at almost everything else, including reading things |
| 67 | +* In theory: |
| 68 | + * It starts with given starting and ending indexes, call these i and j respectively |
| 69 | + * On push, increment j by 1 and push the item at the given index |
| 70 | + * On pop, increment i by 1, delete the first item and return it |
| 71 | + * On peak, simply ignore i and j and return the last element |
| 72 | + |
| 73 | +```python |
| 74 | +# Simple implementation of a stack (practical idea not what it theoretically actually is) |
| 75 | + |
| 76 | +class Queue: |
| 77 | + |
| 78 | + def __init__(self): |
| 79 | + self.list = [] |
| 80 | + self.length = 0 # this is kinda optional |
| 81 | + def push(self, item): |
| 82 | + self.list.insert(0, item) |
| 83 | + def pop(self): |
| 84 | + return self.list.pop() |
| 85 | + def peak(self): |
| 86 | + if self.length > 0: |
| 87 | + return self.list[-1] |
| 88 | + return None |
| 89 | + |
| 90 | +``` |
| 91 | + |
| 92 | +In Python, this is builtin by running the following |
| 93 | +```python |
| 94 | +from collections import deque |
| 95 | +``` |
| 96 | + |
| 97 | +DEQue is actually a **double ended queue** which basically pops and pushes both from the front and back at constant time, which is adequate for purposes needed for queues. |
| 98 | + |
| 99 | +Though the time complexity makes it seem like DEQue is really fast however its a few times slower if you simply need a stack or a queue. |
| 100 | + |
| 101 | +Furthermore, ```collections``` as a library actually provides a lot more as you will see later on. |
| 102 | + |
| 103 | +Practice problem: https://dmoj.ca/problem/ccc13s2 |
0 commit comments