## Create a stack
my_stack = [10, 45, 32, 34]
print(my_stack) # [10, 45, 32, 34]
## Add/Remove operations
# push: append at top
my_stack.append(20)
print(my_stack) # [10, 45, 32, 34, 20]
# pop: remove at top
my_stack.pop()
print(my_stack) # [10, 45, 32, 34]
## Create a queue
my_queue = [23, 67, 12, 67, 89]
print(my_queue) # [23, 67, 12, 67, 89]
## Add/Remove operations
# enqueue: append at rear
my_queue.append(20)
print(my_queue) # [23, 67, 12, 67, 89, 20]
# dequeue: remove at front
my_queue.pop(0)
print(my_queue) # [67, 12, 67, 89, 20]
from collections import deque
import sys
my_list = [23, 45, 12, 67, 132, 67]
## Create a deque, can be initialized using any iterable
dq = deque(my_list)
print(dq) # deque([23, 45, 12, 67, 132, 67])
## Add/Remove operations
# enqueue: append at rear
dq.append(20)
print(dq) # deque([23, 45, 12, 67, 132, 67, 20])
# dequeue: remove at front
dq.popleft()
print(dq) # deque([45, 12, 67, 132, 67, 20])
# only drawback is that they are data inefficient than list
print(sys.getsizeof(dq)) # 624
print(sys.getsizeof(my_list)) # 152
import heapq
## Create a priority queue, initialize with a empty list
my_pq = []
# Initialize with values, use the heapify function
# first to construct a Heap DS
my_pq = [34, 6, 23, 67, 23, 78]
heapq.heapify(my_pq)
print(my_pq) # [6, 23, 23, 67, 34, 78]
## Adding: Use the 'heappush()' function to add elements,
# syntax heappush(container, item)
# here container is our list 'my_pq'
heapq.heappush(my_pq, 3)
heapq.heappush(my_pq, 2)
heapq.heappush(my_pq, 0)
print(my_pq) # [0, 3, 2]
## Removing: Use the 'heappop()' function to get elements from the list
print(heapq.heappop(my_pq)) # 0
# smallest element is taken out first
print(my_pq) # [2, 3]
# when a element is inserted, it is put in its right sorted position
# so [0] index is always the smallest and hence the pop position
## Elements should be comparable: So once a 'int' type is inserted,
# other elements should be 'int' only else 'TypeError' will be raised
heapq.heappush(my_pq, "some string") # TypeError
# The items can also be tuple
# so for example, we can provide some name to a item
my_pq = []
heapq.heappush(my_pq, (2, "task2"))
heapq.heappush(my_pq, (1, "task1"))
heapq.heappush(my_pq, (5, "task3"))
print(heapq.heappop(my_pq)) # (1, 'task1')