Skip to content

Commit d8b5de8

Browse files
authored
Added Algorithms and DS
0 parents  commit d8b5de8

24 files changed

+1570
-0
lines changed

Diff for: Dasgupta-Papadimitriou-Vazirani.pdf

1.93 MB
Binary file not shown.

Diff for: Introduction-to-Algorithms-CLRS-3rd-Edition.pdf

5.39 MB
Binary file not shown.

Diff for: bfs.py

+63
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
from collections import defaultdict
2+
class Graph:
3+
"""docstring for Graph"""
4+
def __init__(self):
5+
# super(Graph, self).__init__()
6+
# self.arg = arg
7+
self.graph= defaultdict(list)
8+
9+
10+
def addEdge(self,u,v):
11+
self.graph[u].append(v)
12+
13+
def BFS(self,s):
14+
queue=[]
15+
visited=[False]*(len(self.graph))
16+
queue.append(s)
17+
visited[s]=True
18+
bfs=[]
19+
while queue:
20+
v=queue.pop(0)
21+
bfs.append(v)
22+
for i in self.graph[v]:
23+
if visited[i]==False:
24+
queue.append(i)
25+
visited[i]=True
26+
27+
return bfs
28+
29+
30+
def bfsTree(self,root):
31+
queue=deque()
32+
queue.append(root)
33+
ans=[]
34+
while queue:
35+
curSize=len(queue)
36+
temp=[]
37+
for _ in range(curSize):
38+
curRoot=queue.popleft()
39+
temp.append(curRoot.val)
40+
if curRoot.left:
41+
queue.append(curRoot.left)
42+
if curRoot.right:
43+
queue.append(curRoot.right)
44+
ans.append(temp)
45+
return ans
46+
47+
48+
49+
50+
51+
if __name__ == '__main__':
52+
g=Graph()
53+
54+
g.addEdge(0,1)
55+
g.addEdge(0,2)
56+
g.addEdge(1,2)
57+
g.addEdge(2,0)
58+
g.addEdge(2,3)
59+
g.addEdge(3,3)
60+
61+
print(g.BFS(2))
62+
63+

Diff for: boundedblockingqueue.py

+85
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
from threading import *
2+
import time
3+
4+
class Node:
5+
def __init__(self,val):
6+
self.val=val
7+
self.next=None
8+
self.prev=None
9+
10+
class BoundedBlockingQueue:
11+
def __init__(self,capacity):
12+
self.capacity=capacity
13+
self.queue_lock=Lock()
14+
self.enqueue_condition=Condition(self.queue_lock)
15+
self.dequeue_condition=Condition(self.queue_lock)
16+
self.size=0
17+
self.head=Node(-1)
18+
self.tail=Node(-2)
19+
self.head.next=self.tail
20+
self.tail.prev=self.head
21+
22+
23+
def enqueue(self,v):
24+
with self.queue_lock:
25+
while self.size==self.capacity:
26+
self.enqueue_condition.wait()
27+
nex=self.tail
28+
prev=self.tail.prev
29+
cur=Node(v)
30+
cur.next=nex
31+
nex.prev=cur
32+
prev.next=cur
33+
cur.prev=prev
34+
self.size+=1
35+
self.dequeue_condition.notify()
36+
37+
38+
39+
40+
def deque(self):
41+
with self.queue_lock:
42+
while self.size==0:
43+
self.dequeue_condition.wait()
44+
prev=self.head
45+
cur=self.head.next
46+
nex=cur.next
47+
prev.next=nex
48+
nex.prev=prev
49+
v=cur.val
50+
cur.prev=None
51+
cur.next=None
52+
self.size-=1
53+
self.enqueue_condition.notify()
54+
return v
55+
56+
def get_size(self):
57+
with self.queue_lock:
58+
return self.size
59+
60+
if __name__ == "__main__":
61+
def producer(queue, items):
62+
for item in items:
63+
print(f"Producing {item}")
64+
queue.enqueue(item)
65+
time.sleep(0.1) # Simulate production time
66+
67+
def consumer(queue, n):
68+
for _ in range(n):
69+
item = queue.deque()
70+
print(f"Consumed {item}")
71+
time.sleep(0.2) # Simulate consumption time
72+
73+
queue = BoundedBlockingQueue(5)
74+
items = range(10)
75+
76+
producer_thread = Thread(target=producer, args=(queue, items))
77+
consumer_thread = Thread(target=consumer, args=(queue, len(items)))
78+
79+
producer_thread.start()
80+
consumer_thread.start()
81+
82+
producer_thread.join()
83+
consumer_thread.join()
84+
85+

Diff for: bridges.py

+43
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
from collections import defaultdict as dt
2+
import sys
3+
sys.setrecursionlimit(10**9)
4+
5+
6+
class Graph:
7+
def __init__(self,nodes):
8+
self.graph=dt(lambda:[])
9+
self.nodes=nodes
10+
self.bridges=[]
11+
12+
13+
def add_edge(self,u,v):
14+
self.graph[u].append(v)
15+
self.graph[v].append(u)
16+
17+
def dfs(self,u,lowest_reachable_node,time_of_insertion,visited,time,par):
18+
time_of_insertion=lowest_reachable_node=time+1
19+
visited[u]=1
20+
21+
for v in self.graph[u]:
22+
if not visited[v]:
23+
self.dfs(v,lowest_reachable_node,time_of_insertion,visited,time+1,u)
24+
lowest_reachable_node[u]=min(lowest_reachable_node[u],lowest_reachable_node[v])
25+
26+
if lowest_reachable_node[v]>time_of_insertion[u]:
27+
self.bridges.append((u,v))
28+
29+
elif visited[v] and v!=par:
30+
lowest_reachable_node[u]=min(lowest_reachable_node[u],lowest_reachable_node[v])
31+
32+
33+
34+
35+
36+
if __name__ == '__main__':
37+
graph=Graph(15)
38+
39+
for i,j in zip(range(10),range(15,5,-1)):
40+
g.add_edge(i,j)
41+
42+
g.dfs(0,[0]*15,[0]*15,[0]*15,0,-1)
43+

Diff for: cc.py

+48
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
from collections import defaultdict
2+
3+
class Graph:
4+
"""docstring for Graph"""
5+
def __init__(self, ver):
6+
# super(Graph, self).__init__()
7+
self.ver = ver
8+
self.graph=defaultdict(list)
9+
10+
def addEdge(self,u,v):
11+
self.graph[u].append(v)
12+
self.graph[v].append(u)
13+
14+
def util(self,v,visited,compo):
15+
visited[v]=True
16+
17+
compo.append(v)
18+
19+
for i in self.graph[v]:
20+
if visited[i]==False:
21+
compo=self.util(i,visited,compo)
22+
return compo
23+
24+
def conncompo(self):
25+
visited=[False]*self.ver
26+
27+
cc=[]
28+
29+
for i in range(self.ver):
30+
if visited[i]==False:
31+
compo=[]
32+
cc.append(self.util(i,visited,compo))
33+
return cc
34+
35+
if __name__=="__main__":
36+
37+
# Create a graph given in the above diagram
38+
# 5 vertices numbered from 0 to 4
39+
g = Graph(5);
40+
g.addEdge(1, 0)
41+
g.addEdge(2, 3)
42+
g.addEdge(3, 4)
43+
cc = g.conncompo()
44+
print("Following are connected components")
45+
print(cc)
46+
47+
48+

Diff for: consistentHashing.py

+77
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
import sys,traceback,hashlib,bisect,re
2+
from sortedcontainers import SortedList
3+
4+
class Node:
5+
def __init__(self,nodeId,name,weight):
6+
self.id=nodeId
7+
self.name=name
8+
self.weight=weight #relative load that this node can handle, the more the weight more the number of virtual nodes on the hash ring
9+
10+
11+
class ConsistentHashing:
12+
def __init__(self):
13+
self.nodes=SortedList()
14+
self.nodeIdToNodes={}
15+
self.nodeToId=defaultdict(lambda:[])
16+
17+
def hash(self,request, limit=4294967295):
18+
keyHash=hashlib,sha512(request.encode())
19+
key=int.from_bytes(keyHash.digest(),"big")%limit
20+
return key
21+
22+
def deleteNode(self,node):
23+
'''
24+
Function that could be used to remove the node from the cluster
25+
'''
26+
return True
27+
28+
def addNode(self,node):
29+
'''
30+
Function that could be used to add the node from the cluster
31+
'''
32+
return True
33+
34+
def getNode(self,request):
35+
requestId=self.hash(request)
36+
nodeIdIndex=self.nodes.bisect_left(requestId)
37+
if nodeIdIndex<len(self.nodes):
38+
return self.nodeIdToNodes[self.nodes[nodeIdIndex]]
39+
return self.nodeIdToNodes[self.nodes[0]]
40+
41+
def addNode(self,node):
42+
nodeId=node.id
43+
for i in range(1,node.weight+1):
44+
virtualNodeId=self.hash(nodeId+i)
45+
self.nodeIdToNodes[virtualNodeId]=node
46+
self.node.add(virtualNodeId)
47+
self.nodeToId[node].append(virtualNodeId)
48+
self.addNode(node)
49+
return "Successfully Added Node"
50+
51+
def removeNode(self,node):
52+
for nodeId in self.nodeToId[node]:
53+
del self.nodeIdToNodes[nodeId]
54+
self.nodes.remove(nodeId)
55+
del self.nodeToId[node]
56+
self.deleteNode(node)
57+
return "Successfully removed the Node"
58+
59+
60+
61+
62+
class LoadBalancer:
63+
def __init__(self):
64+
self.algorithm=ConsistentHashing()
65+
66+
67+
def addNode(self,node):
68+
self.algorithm.addNode(node)
69+
70+
def removeNode(self,node):
71+
self.algorithm.removeNode(node)
72+
73+
def getNode(self,request):
74+
return self.algorithm(request)
75+
76+
77+

Diff for: cycledg.py

+60
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
from collections import defaultdict
2+
3+
class Graph:
4+
"""docstring for Graph"""
5+
def __init__(self, ver):
6+
# super(Graph, self).__init__()
7+
self.ver = ver
8+
self.graph=defaultdict(list)
9+
10+
11+
def addEdge(self,u,v):
12+
self.graph[u].append(v)
13+
14+
def cycleutil(self,v,visited,rec):
15+
16+
visited[v]=True
17+
rec[v]=True
18+
19+
for i in self.graph[v]:
20+
if visited[i]==False:
21+
if self.cycleutil(i,visited,rec):
22+
return True
23+
24+
elif rec[i]==True:
25+
return True
26+
27+
rec[v]=False
28+
29+
return False
30+
31+
def cycle(self):
32+
33+
visited=[False]*self.ver
34+
35+
rec=[False]*self.ver
36+
37+
for i in range(self.ver):
38+
39+
if visited[i]==False:
40+
if self.cycleutil(i,visited,rec)==True:
41+
return True
42+
43+
return False
44+
45+
46+
47+
48+
g = Graph(4)
49+
g.addEdge(0, 1)
50+
g.addEdge(0, 2)
51+
g.addEdge(1, 2)
52+
g.addEdge(2, 0)
53+
g.addEdge(2, 3)
54+
g.addEdge(3, 3)
55+
if g.cycle():
56+
print ("Graph has a cycle")
57+
else:
58+
print( "Graph has no cycle")
59+
60+

0 commit comments

Comments
 (0)