Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
81 changes: 81 additions & 0 deletions Python/Graphs/BFS.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
import collections
from collections import defaultdict

# This class represents a directed graph using
# adjacency list representation


class Graph:

# Constructor
def __init__(self):

# default dictionary to store graph
self.graph = defaultdict(list)

# function to add an edge to graph
def addEdge(self, u, v):
self.graph[u].append(v)

def adjacency(self):
print(self.graph)

# BFS algorithm
def bfs(self, source):

visited, queue = set(), collections.deque([source])
visited.add(source)

while queue:

# Dequeue a vertex from queue
vertex = queue.popleft()
print(str(vertex) + " ", end="")

# If not visited, mark it as visited, and
# enqueue it
for neighbour in self.graph[vertex]:
if neighbour not in visited:
visited.add(neighbour)
queue.append(neighbour)

def shortest_path(self, source, dest):

if source == dest:
return [source]

visited, queue = set(), collections.deque([(source, [])])
visited.add(source)

while queue:

# Dequeue a vertex from queue
vertex, path = queue.popleft()
# print(str(vertex) + " ", end="")

# If not visited, mark it as visited, and
# enqueue it
for neighbour in self.graph[vertex]:
if neighbour == dest:
return path + [vertex, neighbour]

if neighbour not in visited:
visited.add(neighbour)
queue.append((neighbour, path + [vertex]))
return "No path found."
# Time Complexity : O(V + E)
# Auxiliary Space : O(V)


# Driver code
g = Graph()
g.addEdge(0, 1)
g.addEdge(0, 2)
g.addEdge(1, 2)
g.addEdge(2, 0)
g.addEdge(2, 3)
g.addEdge(3, 3)
g.adjacency()
print("Following is BFS from (starting from vertex 2)")
g.bfs(0)
print(g.shortest_path(0, 5))
49 changes: 49 additions & 0 deletions Python/Graphs/Bellman-Ford.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
class Graph:
def __init__(self, vertices):
self.V = vertices # Total number of vertices in the graph
self.graph = [] # Array of edges

# Add edges
def add_edge(self, s, d, w):
self.graph.append([s, d, w])

# Print the solution
def print_solution(self, dist):
print("Vertex Distance from Source")
for i in range(self.V):
print("{0}\t\t{1}".format(i, dist[i]))

def bellman_ford(self, src):

# Step 1: fill the distance array and predecessor array
dist = [float("Inf")] * self.V
# Mark the source vertex
dist[src] = 0

# Step 2: relax edges |V| - 1 times
for _ in range(self.V - 1):
for s, d, w in self.graph:
if dist[s] != float("Inf") and dist[s] + w < dist[d]:
dist[d] = dist[s] + w

# Step 3: detect negative cycle
# if value changes then we have a negative cycle in the graph
# and we cannot find the shortest distances
for s, d, w in self.graph:
if dist[s] != float("Inf") and dist[s] + w < dist[d]:
print("Graph contains negative weight cycle")
return

# No negative weight cycle found!
# Print the distance and predecessor array
self.print_solution(dist)


g = Graph(5)
g.add_edge(0, 1, 5)
g.add_edge(0, 2, 4)
g.add_edge(1, 3, 3)
g.add_edge(2, 1, 6)
g.add_edge(3, 2, 2)

g.bellman_ford(0)
52 changes: 52 additions & 0 deletions Python/Graphs/DFS.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
# Python3 program to print DFS traversal
# from a given given graph
from collections import defaultdict

# This class represents a directed graph using
# adjacency list representation


class Graph:

# Constructor
def __init__(self):

# default dictionary to store graph
self.graph = defaultdict(list)

# function to add an edge to graph
def addEdge(self, u, v):
self.graph[u].append(v)

def adjacency(self):
print(self.graph)

# DFS algorithm
def dfs(self, start, visited=None):
print("GRAPH", self.graph)
if visited is None:
visited = set()
visited.add(start)

print(str(start) + " ", end="")

for next in set(self.graph[start]) - (visited):
self.dfs(next, visited)
return visited

# The time complexity of the DFS algorithm is represented in the form of O(V + E), where V is the number of nodes and E is the number of edges.

# The space complexity of the algorithm is O(V).


# Driver code
g = Graph()
g.addEdge(0, 1)
g.addEdge(0, 2)
g.addEdge(1, 2)
g.addEdge(2, 0)
g.addEdge(2, 3)
g.addEdge(3, 3)
g.adjacency()
print("Following is DFS from (starting from vertex 2)")
g.dfs(2)
67 changes: 67 additions & 0 deletions Python/Graphs/Dijkstra.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import sys

# Providing the graph
vertices = [
[0, 0, 1, 1, 0, 0, 0],
[0, 0, 1, 0, 0, 1, 0],
[1, 1, 0, 1, 1, 0, 0],
[1, 0, 1, 0, 0, 0, 1],
[0, 0, 1, 0, 0, 1, 0],
[0, 1, 0, 0, 1, 0, 1],
[0, 0, 0, 1, 0, 1, 0],
]

edges = [
[0, 0, 1, 2, 0, 0, 0],
[0, 0, 2, 0, 0, 3, 0],
[1, 2, 0, 1, 3, 0, 0],
[2, 0, 1, 0, 0, 0, 1],
[0, 0, 3, 0, 0, 2, 0],
[0, 3, 0, 0, 2, 0, 1],
[0, 0, 0, 1, 0, 1, 0],
]

# Find which vertex is to be visited next
def to_be_visited():
global visited_and_distance
v = -10
for index in range(num_of_vertices):
if visited_and_distance[index][0] == 0 and (
v < 0 or visited_and_distance[index][1] <= visited_and_distance[v][1]
):
v = index
return v


num_of_vertices = len(vertices[0])

visited_and_distance = [[0, 0]]
for i in range(num_of_vertices - 1):
visited_and_distance.append([0, sys.maxsize])

for vertex in range(num_of_vertices):

# Find next vertex to be visited
to_visit = to_be_visited()
for neighbor_index in range(num_of_vertices):

# Updating new distances
if (
vertices[to_visit][neighbor_index] == 1
and visited_and_distance[neighbor_index][0] == 0
):
new_distance = (
visited_and_distance[to_visit][1] + edges[to_visit][neighbor_index]
)
if visited_and_distance[neighbor_index][1] > new_distance:
visited_and_distance[neighbor_index][1] = new_distance

visited_and_distance[to_visit][0] = 1

i = 0
# Time Complexity: O(E Log V)
# Space Complexity: O(V)
# Printing the distance
for distance in visited_and_distance:
print("Distance of ", chr(ord("a") + i), " from source vertex: ", distance[1])
i = i + 1
66 changes: 66 additions & 0 deletions Python/Graphs/Kruskal.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
class Graph:
def __init__(self, vertices):
self.V = vertices
self.graph = []

def add_edge(self, u, v, w):
self.graph.append([u, v, w])

# Search function

def find(self, parent, i):
if parent[i] == i:
return i
return self.find(parent, parent[i])

def apply_union(self, parent, rank, x, y):
xroot = self.find(parent, x)
yroot = self.find(parent, y)
if rank[xroot] < rank[yroot]:
parent[xroot] = yroot
elif rank[xroot] > rank[yroot]:
parent[yroot] = xroot
else:
parent[yroot] = xroot
rank[xroot] += 1

# Applying Kruskal algorithm
def kruskal_algo(self):
result = []
i, e = 0, 0
self.graph = sorted(self.graph, key=lambda item: item[2])
parent = []
rank = []
for node in range(self.V):
parent.append(node)
rank.append(0)
while e < self.V - 1:
u, v, w = self.graph[i]
i = i + 1
x = self.find(parent, u)
y = self.find(parent, v)
if x != y:
e = e + 1
result.append([u, v, w])
self.apply_union(parent, rank, x, y)
for u, v, weight in result:
print("%d - %d: %d" % (u, v, weight))


g = Graph(6)
g.add_edge(0, 1, 4)
g.add_edge(0, 2, 4)
g.add_edge(1, 2, 2)
g.add_edge(1, 0, 4)
g.add_edge(2, 0, 4)
g.add_edge(2, 1, 2)
g.add_edge(2, 3, 3)
g.add_edge(2, 5, 2)
g.add_edge(2, 4, 4)
g.add_edge(3, 2, 3)
g.add_edge(3, 4, 3)
g.add_edge(4, 2, 4)
g.add_edge(4, 3, 3)
g.add_edge(5, 2, 2)
g.add_edge(5, 4, 3)
g.kruskal_algo()
42 changes: 42 additions & 0 deletions Python/Graphs/Prims.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
INF = 9999999
# number of vertices in graph
V = 5
# create a 2d array of size 5x5
# for adjacency matrix to represent graph
G = [[0, 9, 75, 0, 0],
[9, 0, 95, 19, 42],
[75, 95, 0, 51, 66],
[0, 19, 51, 0, 31],
[0, 42, 66, 31, 0]]
# create a array to track selected vertex
# selected will become true otherwise false
selected = [0, 0, 0, 0, 0]
# set number of edge to 0
no_edge = 0
# the number of egde in minimum spanning tree will be
# always less than(V - 1), where V is number of vertices in
# graph
# choose 0th vertex and make it true
selected[0] = True
# print for edge and weight
print("Edge : Weight\n")
while (no_edge < V - 1):
# For every vertex in the set S, find the all adjacent vertices
#, calculate the distance from the vertex selected at step 1.
# if the vertex is already in the set S, discard it otherwise
# choose another vertex nearest to selected vertex at step 1.
minimum = INF
x = 0
y = 0
for i in range(V):
if selected[i]:
for j in range(V):
if ((not selected[j]) and G[i][j]):
# not in selected and there is an edge
if minimum > G[i][j]:
minimum = G[i][j]
x = i
y = j
print(str(x) + "-" + str(y) + ":" + str(G[x][y]))
selected[y] = True
no_edge += 1
Loading