Skip to content

Commit b4372b8

Browse files
committed
added demo modules
Signed-off-by: ABHIJIT SINHA <[email protected]>
1 parent ad1759f commit b4372b8

File tree

6 files changed

+371
-0
lines changed

6 files changed

+371
-0
lines changed
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
#!/usr/bin/env python3
2+
3+
# author: greyshell
4+
# description: demo how to use PriorityQue
5+
6+
from queue import PriorityQueue
7+
8+
9+
class MyHeap(PriorityQueue):
10+
11+
def __init__(self):
12+
super(MyHeap, self).__init__()
13+
14+
def __lt__(self, other):
15+
# compare based on weight
16+
return self.key > other.key
17+
18+
19+
def main():
20+
min_heap = PriorityQueue()
21+
# push an item
22+
min_heap.put(2, 'code')
23+
min_heap.put(1, 'eat')
24+
min_heap.put(0, 'bat')
25+
26+
# peek
27+
print(min_heap)
28+
# pop the min item
29+
print(min_heap.get())
30+
31+
32+
if __name__ == '__main__':
33+
main()
Lines changed: 171 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,171 @@
1+
#!/usr/bin/env python3
2+
3+
# author: greyshell
4+
# description: demo how to use heapq library
5+
6+
import heapq
7+
8+
9+
class MaxHeapNode(object):
10+
def __init__(self, key):
11+
self.key = key
12+
13+
def __lt__(self, other):
14+
# compare based on val
15+
# tweak the comparison logic to build max heap: change less_than_sign to greater_than_sign
16+
return self.key > other.key
17+
18+
def __gt__(self, other):
19+
# compare based on val
20+
# tweak the comparison logic to build max heap
21+
return self.key < other.key
22+
23+
def __eq__(self, other):
24+
return self.key == other.key
25+
26+
def __ne__(self, other):
27+
return self.key != other.key
28+
29+
def __str__(self):
30+
return str(self.key)
31+
32+
33+
def demo_max_heap():
34+
print(f"========================================")
35+
print(f"demo max heap ")
36+
print(f"========================================")
37+
# create a max heap that stores an object (key, index, name) and the key is key
38+
max_heap = list()
39+
40+
heapq.heappush(max_heap, MaxHeapNode(17))
41+
heapq.heappush(max_heap, MaxHeapNode(1000))
42+
heapq.heappush(max_heap, MaxHeapNode(250))
43+
heapq.heappush(max_heap, MaxHeapNode(500))
44+
45+
print(f"max value {max_heap[0]}")
46+
node = heapq.heappop(max_heap)
47+
print(f"popped item: {node.key}")
48+
print(f"max value {max_heap[0]}")
49+
50+
51+
class HeapSatelliteNode(object):
52+
def __init__(self, name, age):
53+
# self.val = val
54+
self.name = name
55+
self.age = age
56+
57+
def __lt__(self, other):
58+
# compare based on age
59+
# tweak the comparison logic to build max heap: change less_than_sign to greater_than_sign
60+
# key = age, so compare based on the key
61+
return self.age > other.age
62+
63+
def __eq__(self, other):
64+
return self.age == other.age
65+
66+
def __str__(self):
67+
return f"name:{self.name}, age:{self.age}"
68+
69+
70+
def demo_max_satellite_heap():
71+
print(f"========================================")
72+
print(f"demo max satellite heap ")
73+
print(f"========================================")
74+
# create a max heap that stores an object (key, index, name) and the key is key
75+
max_heap = list()
76+
77+
# compare based on the age
78+
heapq.heappush(max_heap, HeapSatelliteNode('asinha', 39))
79+
heapq.heappush(max_heap, HeapSatelliteNode('dhaval', 22))
80+
heapq.heappush(max_heap, HeapSatelliteNode('ravi', 23))
81+
82+
print(f"max value {max_heap[0]}")
83+
node = heapq.heappop(max_heap)
84+
print(f"popped item: {node.name}")
85+
print(f"max value {max_heap[0]}")
86+
87+
print(heapq.heappop(max_heap))
88+
print(heapq.heappop(max_heap))
89+
90+
if max_heap: # check if the list is empty or not
91+
print(heapq.heappop(max_heap))
92+
93+
94+
def heap_sort(nums):
95+
heapq.heapify(nums)
96+
return [heapq.heappop(nums) for _ in range(0, len(nums))]
97+
98+
99+
def main():
100+
min_heap = [12, 7, 11, 15, 35, 17]
101+
102+
print(f"========================================")
103+
print(f"demo heap sort")
104+
print(f"========================================")
105+
106+
print(f"before heap sort: {min_heap}")
107+
r = heap_sort(min_heap)
108+
print(f"after heap sort: {r}")
109+
110+
print(f"========================================")
111+
print(f"demo min heap ")
112+
print(f"========================================")
113+
# build a min heap
114+
heapq.heapify(min_heap) # in-place, in linear time, O(n), Heap elements can be tuples.
115+
116+
# push an item
117+
heapq.heappush(min_heap, 25) # O(log(n))
118+
heapq.heappush(min_heap, 5) # O(log(n))
119+
heapq.heappush(min_heap, 10) # O(log(n))
120+
121+
# peek the min item
122+
data = min_heap[0] # O(1)
123+
124+
# pop an item
125+
data = heapq.heappop(min_heap) # O(log(n))
126+
print(f"popped item: {data}")
127+
print(f"current heap : {min_heap}")
128+
129+
# when we need to make the heap size constant, we can use heappushpop() and heapreplace()
130+
# time complexity: O(log(n)), improving the performance
131+
dummy_nums = min_heap.copy() # copy all elements to another list
132+
data = -1
133+
popped_value = heapq.heappushpop(min_heap, data) # 1st push then pop
134+
print(f"popped value: {popped_value}")
135+
136+
popped_value = heapq.heapreplace(dummy_nums, data) # 1st pop from existing min then push
137+
print(f"popped value: {popped_value}")
138+
139+
print(f"========================================")
140+
print(f"demo nlargest / smallest element or element ")
141+
print(f"========================================")
142+
143+
# k largest / smallest elements
144+
# best for smaller values of k
145+
min_heap.append(100)
146+
min_heap.append(200)
147+
min_heap.append(50)
148+
print(f"nums = {min_heap}")
149+
150+
large_items = heapq.nlargest(3, min_heap)
151+
small_items = heapq.nsmallest(3, min_heap)
152+
print(f"3 largest values: {large_items}")
153+
print(f"3 smallest values: {small_items}")
154+
# when k==1, it is more efficient to use the built-in min() and max() functions.
155+
156+
# for larger k values it is more efficient to use the sorted() function.
157+
158+
# kth largest element
159+
k = 3
160+
kth_large = heapq.nlargest(k, min_heap)[-1]
161+
print(f"{k}th/rd/nd largest value: {kth_large}") # last element of the kth_large list
162+
163+
# demo max heap
164+
demo_max_heap()
165+
166+
# demo satellite data in the max heap
167+
demo_max_satellite_heap()
168+
169+
170+
if __name__ == '__main__':
171+
main()
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
#!/usr/bin/env python3
2+
3+
# author: greyshell
4+
# description: how to use queue ADT
5+
6+
from collections import deque as queue
7+
8+
9+
def main():
10+
q = queue()
11+
# enque: adding items at rear
12+
q.append(9)
13+
q.append(5)
14+
q.append(3)
15+
q.append(1)
16+
17+
# display the queue elements
18+
print(f"display the queue elements: {list(q)}")
19+
20+
# dequeue: deleting items from front
21+
data = q.popleft()
22+
print(f"item deleted from font: {data}")
23+
print(f"display the queue elements: {list(q)}")
24+
25+
# peek
26+
print(f"peek the front: {q[0]}")
27+
print(f"peek the rare: {q[-1]}")
28+
29+
# dequeue at rear
30+
data = q.pop()
31+
print(f"item deleted from rare: {data}")
32+
33+
34+
if __name__ == '__main__':
35+
main()
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
# !/usr/bin/env python3
2+
3+
# author: greyshell
4+
# description: stack using list
5+
6+
7+
def main():
8+
"""
9+
- python list is backed by dynamic array, so occasionally it needs to be resized when item
10+
is added / removed
11+
- it does not guarantee the stable O(1) push and pop
12+
- however, it provides the amortize time complexity is O(1) when the item is added / remove at
13+
the end of list
14+
- adding / removing from front / middle is much slower and it takes O(n) time as shifting of
15+
existing elements
16+
are required
17+
- no parallel processing support / it handles locking and unlocking
18+
:return:
19+
"""
20+
s = list()
21+
# push: O(1), stack grows from left to right
22+
s.append(9)
23+
s.append(5)
24+
s.append(3)
25+
s.append(2)
26+
27+
# display the stack elements
28+
print(f"display the stack elements: {s}")
29+
30+
# peek, O(1)
31+
data = s[-1]
32+
print(f"peek the stack top: {data}")
33+
34+
# pop: O(1), stack shrinks from right to left
35+
# raise IndexError => pop from an empty list
36+
try:
37+
data = s.pop()
38+
print(f"popped: {data}")
39+
except IndexError as e:
40+
print(f"{e}")
41+
42+
print(f"display the stack elements: {list(s)}")
43+
44+
45+
if __name__ == '__main__':
46+
main()
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
#!/usr/bin/env python3
2+
3+
# author: greyshell
4+
# description: stack using deque
5+
6+
from collections import deque
7+
8+
9+
def main():
10+
"""
11+
- deque is backed by doubly linked list
12+
- it that guarantees the stable O(1) push and pop
13+
- no parallel processing support / it handles locking and unlocking
14+
:return:
15+
"""
16+
s = deque()
17+
# push: O(1), stack grows from left to right
18+
s.append(9)
19+
s.append(5)
20+
s.append(3)
21+
s.append(1)
22+
23+
# display the stack elements: convert the deque into list
24+
print(f"display the stack elements: {s}")
25+
print(f"display the stack elements: {list(s)}")
26+
27+
# peek, O(1)
28+
data = s[-1]
29+
print(f"peek the stack top: {data}")
30+
31+
# pop: O(1), stack shrinks from right to left
32+
# raise IndexError => pop from an empty list
33+
try:
34+
data = s.pop()
35+
print(f"popped: {data}")
36+
except IndexError as e:
37+
print(f"{e}")
38+
39+
print(f"display the stack elements: {list(s)}")
40+
41+
42+
if __name__ == '__main__':
43+
main()
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
#!/usr/bin/env python3
2+
3+
# author: greyshell
4+
# description: stack using queue.LifoQueue
5+
6+
from queue import LifoQueue
7+
8+
9+
def main():
10+
"""
11+
- used for parallel computing / multi producer and consumer scenarios
12+
- locking and un-locking needs to be implemented manually
13+
:return:
14+
"""
15+
s = LifoQueue()
16+
# push: O(1)
17+
s.put(9)
18+
s.put(2)
19+
20+
# check if the stack is empty
21+
print(f"{s.empty()}")
22+
23+
# not found any method for peek and display stack elements
24+
25+
# pop: O(1)
26+
data = s.get_nowait()
27+
data = s.get_nowait()
28+
29+
try:
30+
data = s.get_nowait() # not wait for producer to add the element if the stack is empty
31+
print(f"popped: {data}")
32+
except Exception as e:
33+
print(f"{e}")
34+
35+
exit(0)
36+
37+
data = s.get() # popped out the last stack element
38+
data = s.get() # waits for ever as the stack is empty, producer needs to add an element
39+
print(f"popped: {data}")
40+
41+
42+
if __name__ == '__main__':
43+
main()

0 commit comments

Comments
 (0)