diff --git a/Python/Graphs/BFS.py b/Python/Graphs/BFS.py new file mode 100644 index 00000000..7164514b --- /dev/null +++ b/Python/Graphs/BFS.py @@ -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)) diff --git a/Python/Graphs/Bellman-Ford.py b/Python/Graphs/Bellman-Ford.py new file mode 100644 index 00000000..7d3aaf03 --- /dev/null +++ b/Python/Graphs/Bellman-Ford.py @@ -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) diff --git a/Python/Graphs/DFS.py b/Python/Graphs/DFS.py new file mode 100644 index 00000000..a54cc860 --- /dev/null +++ b/Python/Graphs/DFS.py @@ -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) diff --git a/Python/Graphs/Dijkstra.py b/Python/Graphs/Dijkstra.py new file mode 100644 index 00000000..bc939d4d --- /dev/null +++ b/Python/Graphs/Dijkstra.py @@ -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 diff --git a/Python/Graphs/Kruskal.py b/Python/Graphs/Kruskal.py new file mode 100644 index 00000000..5de9d523 --- /dev/null +++ b/Python/Graphs/Kruskal.py @@ -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() diff --git a/Python/Graphs/Prims.py b/Python/Graphs/Prims.py new file mode 100644 index 00000000..28488ddb --- /dev/null +++ b/Python/Graphs/Prims.py @@ -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 \ No newline at end of file diff --git a/Python/Graphs/Topological.py b/Python/Graphs/Topological.py new file mode 100644 index 00000000..e3c7327d --- /dev/null +++ b/Python/Graphs/Topological.py @@ -0,0 +1,89 @@ +# 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, vertices): + self.V = vertices + self.verticeslist = [] + + # default dictionary to store graph + self.digraph = defaultdict(list) + + # function to add an edge to graph + def addEdge(self, u, v): + self.digraph[u].append(v) + self.verticeslist.append(u) + self.verticeslist.append(v) + + def adjacency(self): + print(self.digraph) + + def topological_sort(self): + # self.digraph is a dictionary: + # key: a node + # value: a set of adjacent neighboring nodes + + # construct a dictionary mapping nodes to their + # indegrees + # indegrees = {node: 0 for node in self.digraph.keys()} + # print("IN", indegrees) + self.verticeslist = set(self.verticeslist) + indegrees = {} + for k in self.verticeslist: + indegrees[k] = 0 + # print("IN", indegrees) + # print("GRAPH", self.digraph) + for node in self.digraph.keys(): + for neighbor in self.digraph[node]: + indegrees[neighbor] = indegrees[neighbor] + 1 + print(indegrees[neighbor]) + + # track nodes with no incoming edges + nodes_with_no_incoming_edges = [] + for node in self.digraph: + if indegrees[node] == 0: + nodes_with_no_incoming_edges.append(node) + + # initially, no nodes in our ordering + topological_ordering = [] + + # as long as there are nodes with no incoming edges + # that can be added to the ordering + while len(nodes_with_no_incoming_edges) > 0: + + # add one of those nodes to the ordering + node = nodes_with_no_incoming_edges.pop() + topological_ordering.append(node) + + # decrement the indegree of that node's neighbors + for neighbor in self.digraph[node]: + indegrees[neighbor] -= 1 + if indegrees[neighbor] == 0: + nodes_with_no_incoming_edges.append(neighbor) + + # we've run out of nodes with no incoming edges + # did we add all the nodes or find a cycle? + if len(topological_ordering) == len(self.digraph): + return topological_ordering # got them all + else: + raise Exception("Graph has a cycle! No topological ordering exists.") + + # Time Complexity: O(V+E). + # Auxiliary space: O(V). + + +# Driver code +g = Graph(6) +g.addEdge(5, 2) +g.addEdge(5, 0) +g.addEdge(4, 0) +g.addEdge(4, 1) +g.addEdge(2, 3) +g.addEdge(3, 1) +print("Following is a Topological Sort of the given graph") +print("ORDER", g.topological_sort()) diff --git a/Python/Graphs/count_paths.py b/Python/Graphs/count_paths.py new file mode 100644 index 00000000..e41f5a54 --- /dev/null +++ b/Python/Graphs/count_paths.py @@ -0,0 +1,74 @@ +# Python 3 program to count all paths +# from a source to a destination. + +# A directed graph using adjacency +# list representation +class Graph: + + def __init__(self, V): + self.V = V + self.adj = [[] for i in range(V)] + + def addEdge(self, u, v): + + # Add v to u’s list. + self.adj[u].append(v) + + # Returns count of paths from 's' to 'd' + def countPaths(self, s, d): + + # Mark all the vertices + # as not visited + visited = [False] * self.V + + # Call the recursive helper + # function to print all paths + pathCount = [0] + self.countPathsUtil(s, d, visited, pathCount) + return pathCount[0] + + # A recursive function to print all paths + # from 'u' to 'd'. visited[] keeps track + # of vertices in current path. path[] + # stores actual vertices and path_index + # is current index in path[] + def countPathsUtil(self, u, d, + visited, pathCount): + visited[u] = True + + # If current vertex is same as + # destination, then increment count + if (u == d): + pathCount[0] += 1 + + # If current vertex is not destination + else: + + # Recur for all the vertices + # adjacent to current vertex + i = 0 + while i < len(self.adj[u]): + if (not visited[self.adj[u][i]]): + self.countPathsUtil(self.adj[u][i], d, + visited, pathCount) + i += 1 + + visited[u] = False + + +# Driver Code +if __name__ == '__main__': + + # Create a graph given in the + # above diagram + g = Graph(4) + g.addEdge(0, 1) + g.addEdge(0, 2) + g.addEdge(0, 3) + g.addEdge(2, 0) + g.addEdge(2, 1) + g.addEdge(1, 3) + + s = 2 + d = 3 + print(g.countPaths(s, d)) diff --git a/Python/Graphs/graphs.py b/Python/Graphs/graphs.py new file mode 100644 index 00000000..2a07c6cb --- /dev/null +++ b/Python/Graphs/graphs.py @@ -0,0 +1,64 @@ +# A class to represent the adjacency list of the node + + +class AdjNode: + def __init__(self, data): + self.vertex = data + self.next = None + + +class Graph: + def __init__(self, vertices): + self.V = vertices + self.graph = [None] * self.V + self.verticeslist = [] + + def add_edge(self, src, dest): + self.verticeslist.append(src) + self.verticeslist.append(dest) + node = AdjNode(dest) + node.next = self.graph[src] + self.graph[src] = node + # Adding the source node to the destination as + # it is the undirected graph + node = AdjNode(src) + node.next = self.graph[dest] + self.graph[dest] = node + + def adjacency_list(self): + for i in range(self.V): + print("Adjacency list of vertex {}\n head".format(i), end="") + temp = self.graph[i] + while temp: + print(" -> {}".format(temp.vertex), end="") + temp = temp.next + print(" \n") + # Saves space O(|V|+|E|) . In the worst case, there can be C(V, 2) number of edges in a graph thus consuming O(V^2) space. Adding a vertex is easier. + + def adjacency_matrix(self): + self.verticeslist = set(self.verticeslist) + print(self.verticeslist) + print("ADJACENCY MATRIX for ") + for i in self.verticeslist: + d = [] + print("I", i) + temp = self.graph[i] + while temp: + d.append(temp.vertex) + temp = temp.next + print(d) + + +if __name__ == "__main__": + V = 5 + graph = Graph(V) + graph.add_edge(0, 1) + graph.add_edge(0, 4) + graph.add_edge(1, 2) + graph.add_edge(1, 3) + graph.add_edge(1, 4) + graph.add_edge(2, 3) + graph.add_edge(3, 4) + + # graph.adjacency_list() + graph.adjacency_matrix() diff --git a/Stack/stack application(infix->postfix and infix->prefix conversion).c b/Stack/stack application(infix->postfix and infix->prefix conversion).c deleted file mode 100644 index d9523299..00000000 --- a/Stack/stack application(infix->postfix and infix->prefix conversion).c +++ /dev/null @@ -1,277 +0,0 @@ -#include -#include -#include -#include -#define MAX 40 -typedef struct{ - char ele[MAX]; - int top; -}stack; -void reverse(char ex[]); -void infixtopost(char exp[],stack s); -int check(char exp[],stack s); -void infixtoprefix(char exp[],stack s); - -char pop(stack *s); -void push(stack *s,char item); -char peek(stack s); -int isEmpty(stack *s); -int isFull(stack *s); -void deletion(stack s); -void display(stack s); -int prec2(char ch); -int prec1(char ch); -void reverse(char exp[],stack s); -char post[MAX]; -int main(){ - stack s; - s.top=-1; - do{ - int ch; - char exp[MAX]; - - printf("\n\nMenue\n\n\nEnter 1 for infix to postfix\n\n\nEnter 2 for infix to prefix\n"); - printf("\n\nEnter your choice\n\n"); - scanf("%d",&ch); - switch(ch){ - case 1: - printf("\nEnter the expression to be evaluated\n"); - scanf("%s",exp); - if(check(exp,s)) - - infixtopost(exp,s); - else{ - printf("\n\nThe entered expression is invalid enter some valid expression\n\n"); - } - - break; - - case 2: - printf("\nEnter the expression to be evaluated\n"); - scanf("\n%s",exp); - if(check(exp,s)){ - - infixtoprefix(exp,s); - - } - else{ - printf("\n\nThe entered expression is invalid enter some valid expression\n\n"); - } - break; - case 3: - printf("\n\nBye!Bye you exit\n\n"); - exit(0); - - default: - printf("\n\nWrong Choice\n\n"); - - } - }while(1); -} -int check(char exp[],stack s){ - - int i,k; - k=strlen(exp); - for(i=0;exp[i]!='\0';i++) - { - - if(exp[i]=='(') - push(&s,exp[i]); - else if(exp[i]==')') - { - if(s.top==-1) - break; - else - pop(&s); - } - - } - if(s.top==-1&& i==k) - return 1; - else - return 0; - - - } - -void reverse(char ex[]){ - int i,n,end; - char temp; - n=strlen(ex); - end=n-1; - for(i=0;itop++; - s->ele[s->top]=item; - - } -} -char pop(stack *s){ - char item; - if(isEmpty(s)){ - printf("\nStack Underflow......\n"); - return -1; - - } - else{ - item=s->ele[s->top]; - s->top--; - return item; - } -} -char peek(stack s){ - char item; - if(isEmpty(&s)){ - printf("\nStack nderflow\n"); - return -1; - } - else - { - item=s.ele[s.top]; - return item; - } - } - -int isEmpty(stack *s) -{ - if(s->top==-1) - { - return 1; - } - else{ - return 0; - } -} -int isFull(stack *s) -{ - if(s->top==MAX) - { - return 1; - } - else{ - return 0; - } -} - - - - -