diff --git a/README.md b/README.md index ed0c80b..8707576 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# Graphs in Python +# Graphs in Python ![graphs-in-python-course](https://s3.stackabuse.com/media/courses/graphs-in-python-theory-and-implementation-banner.jpg) ## Repo Structure diff --git a/base_classes/graph.py b/base_classes/graph.py index c5bf6c3..af1ae48 100644 --- a/base_classes/graph.py +++ b/base_classes/graph.py @@ -5,6 +5,6 @@ def __init__(self, num_of_nodes): def __str__(self): return - + def add_edge(self, node1, node2, weight): return \ No newline at end of file diff --git a/base_classes/node.py b/base_classes/node.py index 0e8a33d..36cfd6c 100644 --- a/base_classes/node.py +++ b/base_classes/node.py @@ -12,10 +12,10 @@ def __repr__(self): def set_id(self, id): self.m_id = id - + def get_id(self): return self.m_id - + def get_name(self): return self.m_name diff --git a/graph_implementations/graph_adj_list_dict.py b/graph_implementations/graph_adj_list_dict.py index 3177be4..2cdc193 100644 --- a/graph_implementations/graph_adj_list_dict.py +++ b/graph_implementations/graph_adj_list_dict.py @@ -3,7 +3,7 @@ from queue import Queue class AdjListGraph(Graph): - + ################################### # Constructor ################################### @@ -13,10 +13,10 @@ def __init__(self, num_of_nodes, directed=True): self.m_directed = directed - self.m_graph = {} + self.m_graph = {} ################################### - # Add edge to a graph + # Add edge to a graph ################################### def add_edge(self, node1_name, node2_name, weight=1): node1 = Node(node1_name) @@ -28,7 +28,7 @@ def add_edge(self, node1_name, node2_name, weight=1): self.m_graph[node1_name] = set() else: node1 = self.get_node_by_name(node1_name) - + if (node2 not in self.m_nodes): node2_id = len(self.m_nodes) node2.set_id(node2_id) @@ -49,7 +49,7 @@ def get_node_by_name(self, name): search_node = Node(name) for node in self.m_nodes: if node == search_node: - return node + return node return None ################################### @@ -68,7 +68,7 @@ def load_from_dict(self, dict): for node1 in dict.keys(): for (node2, weight) in dict[node1]: self.add_edge(node1, node2, weight) - + ################################### # Load a graph from a list of edges # For example: @@ -102,7 +102,7 @@ def __str__(self): def get_nodes(self): return self.m_nodes - + ################################### # DFS Search ################################### @@ -122,7 +122,7 @@ def dfs(self, start_node_name, target_node_name, path = [], visited = set()): if result is not None: return result path.pop() - return None + return None ################################### # BFS Search @@ -135,7 +135,7 @@ def bfs(self, start_node, target_node): # Add the start_node to the queue and visited list queue.put(start_node) visited.add(start_node) - + # start_node has not parents parent = dict() parent[start_node] = None @@ -153,17 +153,17 @@ def bfs(self, start_node, target_node): queue.put(next_node) parent[next_node] = current_node visited.add(next_node) - + # Path reconstruction path = [] if path_found: path.append(target_node) while parent[target_node] is not None: - path.append(parent[target_node]) + path.append(parent[target_node]) target_node = parent[target_node] path.reverse() - return path - + return path + ################################### # BFS Traversal ################################### @@ -180,7 +180,7 @@ def bfs_traversal(self, start_node): for (next_node, weight) in self.m_graph[current_node]: if next_node not in visited: queue.put(next_node) - visited.add(next_node) + visited.add(next_node) g = AdjListGraph(5) adjacency_list = { diff --git a/graph_implementations/graph_adj_matrix.py b/graph_implementations/graph_adj_matrix.py index fd64fc8..e89c82b 100644 --- a/graph_implementations/graph_adj_matrix.py +++ b/graph_implementations/graph_adj_matrix.py @@ -11,9 +11,9 @@ def __init__(self, num_of_nodes, directed=True): # A representation of a graph # i.e. adjacency matrix - self.m_graph = [[0 for column in range(num_of_nodes)] + self.m_graph = [[0 for column in range(num_of_nodes)] for row in range(num_of_nodes)] - + ################################### # Assert node names ################################### @@ -44,26 +44,26 @@ def __str__(self): for i in range(self.m_num_of_nodes): out += str(self.m_graph[i]) + "\n" return out - - ################################### + + ################################### # Prims's MST Algorithm ################################### def prims_mst(self): # Defining a really big number: postitive_inf = float('inf') - # This is a list showing which nodes are already selected + # This is a list showing which nodes are already selected # so we don't pick the same node twice and we can actually know when stop looking selected_nodes = [False for vertex in range(self.m_num_of_nodes)] # Matrix of the resulting MST - result = [[0 for column in range(self.m_num_of_nodes)] + result = [[0 for column in range(self.m_num_of_nodes)] for row in range(self.m_num_of_nodes)] - + indx = 0 for i in range(self.m_num_of_nodes): print(self.m_graph[i]) - + print(selected_nodes) # While there are nodes that are not included in the MST, keep looking: @@ -82,26 +82,26 @@ def prims_mst(self): if selected_nodes[i]: for j in range(self.m_num_of_nodes): # If the analyzed node have a path to the ending node AND its not included in the MST (to avoid cycles) - if (not selected_nodes[j] and self.m_graph[i][j]>0): + if (not selected_nodes[j] and self.m_graph[i][j]>0): # If the weight path analized is less than the minimum of the MST if self.m_graph[i][j] < minimum: # Defines the new minimum weight, the starting vertex and the ending vertex minimum = self.m_graph[i][j] start, end = i, j - + # Since we added the ending vertex to the MST, it's already selected: selected_nodes[end] = True # Filling the MST Adjacency Matrix fields: result[start][end] = minimum - + if minimum == postitive_inf: result[start][end] = 0 print("(%d.) %d - %d: %d" % (indx, start, end, result[start][end])) indx += 1 - + result[end][start] = result[start][end] # Print the resulting MST @@ -110,7 +110,7 @@ def prims_mst(self): for j in range(0+i, len(result)): if result[i][j] != 0: print("%d - %d: %d" % (i, j, result[i][j])) - + graph = Graph(5) diff --git a/graph_implementations/graph_edge_list.py b/graph_implementations/graph_edge_list.py index 9cc354e..2c37fa8 100644 --- a/graph_implementations/graph_edge_list.py +++ b/graph_implementations/graph_edge_list.py @@ -24,14 +24,14 @@ def __init__(self, num_of_nodes, directed=True): ################################### def add_edge(self, node1_name, node2_name, weight=1): node1 = Node(node1_name) - node2 = Node(node2_name) + node2 = Node(node2_name) if (node1 not in self.m_nodes): node1_id = len(self.m_nodes) node1.set_id(node1_id) self.m_nodes.append(node1) else: node1 = self.get_node_by_name(node1_name) - + if (node2 not in self.m_nodes): node2_id = len(self.m_nodes) node2.set_id(node2_id) @@ -41,12 +41,12 @@ def add_edge(self, node1_name, node2_name, weight=1): # Add the edge from node1 to node2 self.m_graph.append([node1, node2, weight]) - + # If a graph is undirected, add the same edge, # but also in the opposite direction if not self.m_directed: - self.m_graph.append([node1, node2, weight]) - + self.m_graph.append([node2, node1, weight]) + ################################### # Print a graph representation ################################### @@ -56,7 +56,7 @@ def __str__(self): for i in range(num_of_edges): out += "edge " + str(i+1) + ": " + str(self.m_graph[i]) + "\n" return out - + ################################### # Find node in a graph using its name ################################### @@ -64,10 +64,10 @@ def get_node_by_name(self, name): search_node = Node(name) for node in self.m_nodes: if node == search_node: - return node + return node return None - - ################################### + + ################################### # Kruskal's MST Algorithm ################################### # Finds the root node of a subtree containing node `node` @@ -108,7 +108,7 @@ def kruskals_mst(self): # Sort edges by weight sorted_graph = sorted(self.m_graph, key=lambda item: item[2]) - + # Important property of any MST # the number of edges is equal to the number of nodes minus 1 while e < (self.m_num_of_nodes - 1): @@ -124,9 +124,9 @@ def kruskals_mst(self): print("Kruskal's MST:") for node1, node2, weight in result: - print("%s - %s: %d" % (node1, node2, weight)) - - ################################### + print("%s - %s: %d" % (node1, node2, weight)) + + ################################### # Borůvka's MST Algorithm ################################### def find_component(self, node): diff --git a/graphs_in_python_lessons/01_representing_graphs_in_code/README.md b/graphs_in_python_lessons/01_representing_graphs_in_code/README.md index eda83ef..094984c 100644 --- a/graphs_in_python_lessons/01_representing_graphs_in_code/README.md +++ b/graphs_in_python_lessons/01_representing_graphs_in_code/README.md @@ -5,6 +5,6 @@ This folder contains implementations used in the article ["Graphs in Python: Rep - `adj_matrix_graph_basic.py` - `adj_list_graph_basic.py` -Those are basic implementations we've used for illustrative purposes in the mentioned article. You can find more advanced implementations in the `advanced_implementations` folder. +Those are basic implementations we've used for illustrative purposes in the mentioned article. You can find more advanced implementations in the `advanced_implementations` folder. The main difference between simple and advanced implementations for casual user is that you can arbitratily name nodes in advanced implementation. \ No newline at end of file diff --git a/graphs_in_python_lessons/01_representing_graphs_in_code/adj_list_graph_basic.py b/graphs_in_python_lessons/01_representing_graphs_in_code/adj_list_graph_basic.py index 955a54b..2bdc60e 100644 --- a/graphs_in_python_lessons/01_representing_graphs_in_code/adj_list_graph_basic.py +++ b/graphs_in_python_lessons/01_representing_graphs_in_code/adj_list_graph_basic.py @@ -6,21 +6,21 @@ def __init__(self, num_of_nodes, directed=True): # Define the type of a graph self.m_directed = directed - self.m_adj_list = {node: set() for node in self.m_nodes} + self.m_adj_list = {node: set() for node in self.m_nodes} def add_edge(self, node1, node2, weight=1): self.m_adj_list[node1].add((node2, weight)) - + if not self.m_directed: self.m_adj_list[node2].add((node1, weight)) - + def print_adj_list(self): for key in self.m_adj_list.keys(): print("node", key, ": ", self.m_adj_list[key]) def main(): graph = Graph(5) - + graph.add_edge(0, 0, 25) graph.add_edge(0, 1, 5) graph.add_edge(0, 2, 3) diff --git a/graphs_in_python_lessons/01_representing_graphs_in_code/adj_matrix_graph_basic.py b/graphs_in_python_lessons/01_representing_graphs_in_code/adj_matrix_graph_basic.py index a1867dc..04e31de 100644 --- a/graphs_in_python_lessons/01_representing_graphs_in_code/adj_matrix_graph_basic.py +++ b/graphs_in_python_lessons/01_representing_graphs_in_code/adj_matrix_graph_basic.py @@ -5,7 +5,7 @@ def __init__(self, num_of_nodes, directed=True): # Initialize the adjacency matrix # Create a matrix with `num_of_nodes` rows and columns - self.m_adj_matrix = [[0 for column in range(num_of_nodes)] + self.m_adj_matrix = [[0 for column in range(num_of_nodes)] for row in range(num_of_nodes)] def add_edge(self, node1, node2, weight=1): @@ -17,7 +17,7 @@ def add_edge(self, node1, node2, weight=1): def print_adj_matrix(self): for i in range(self.m_num_of_nodes): print(self.m_adj_matrix[i]) - + def main(): graph = Graph(5) diff --git a/graphs_in_python_lessons/01_representing_graphs_in_code/advanced_implementations/adj_list_graph.py b/graphs_in_python_lessons/01_representing_graphs_in_code/advanced_implementations/adj_list_graph.py index e238413..1f74b53 100644 --- a/graphs_in_python_lessons/01_representing_graphs_in_code/advanced_implementations/adj_list_graph.py +++ b/graphs_in_python_lessons/01_representing_graphs_in_code/advanced_implementations/adj_list_graph.py @@ -2,7 +2,7 @@ from base_classes.graph import Graph class AdjListGraph(Graph): - + ################################### # Constructor ################################### @@ -12,10 +12,10 @@ def __init__(self, num_of_nodes, directed=True): self.m_directed = directed - self.m_graph = {} + self.m_graph = {} ################################### - # Add edge to a graph + # Add edge to a graph ################################### def add_edge(self, node1_name, node2_name, weight=1): node1 = Node(node1_name) @@ -28,7 +28,7 @@ def add_edge(self, node1_name, node2_name, weight=1): self.m_graph[node1_name] = set() else: node1 = self.get_node_by_name(node1_name) - + if (node2 not in self.m_nodes): node2_id = len(self.m_nodes) node2.set_id(node2_id) @@ -49,7 +49,7 @@ def get_node_by_name(self, name): search_node = Node(name) for node in self.m_nodes: if node == search_node: - return node + return node return None ################################### @@ -68,7 +68,7 @@ def load_from_dict(self, dict): for node1 in dict.keys(): for (node2, weight) in dict[node1]: self.add_edge(node1, node2, weight) - + ################################### # Load a graph from a list of edges # For example: diff --git a/graphs_in_python_lessons/01_representing_graphs_in_code/advanced_implementations/adj_matrix_graph.py b/graphs_in_python_lessons/01_representing_graphs_in_code/advanced_implementations/adj_matrix_graph.py index 611c50a..413cd1c 100644 --- a/graphs_in_python_lessons/01_representing_graphs_in_code/advanced_implementations/adj_matrix_graph.py +++ b/graphs_in_python_lessons/01_representing_graphs_in_code/advanced_implementations/adj_matrix_graph.py @@ -11,9 +11,9 @@ def __init__(self, num_of_nodes, directed=True): # A representation of a graph # i.e. adjacency matrix - self.m_graph = [[0 for column in range(num_of_nodes)] + self.m_graph = [[0 for column in range(num_of_nodes)] for row in range(num_of_nodes)] - + ################################### # Assert node names ################################### diff --git a/graphs_in_python_lessons/01_representing_graphs_in_code/advanced_implementations/base_classes/graph.py b/graphs_in_python_lessons/01_representing_graphs_in_code/advanced_implementations/base_classes/graph.py index c5bf6c3..af1ae48 100644 --- a/graphs_in_python_lessons/01_representing_graphs_in_code/advanced_implementations/base_classes/graph.py +++ b/graphs_in_python_lessons/01_representing_graphs_in_code/advanced_implementations/base_classes/graph.py @@ -5,6 +5,6 @@ def __init__(self, num_of_nodes): def __str__(self): return - + def add_edge(self, node1, node2, weight): return \ No newline at end of file diff --git a/graphs_in_python_lessons/01_representing_graphs_in_code/advanced_implementations/base_classes/node.py b/graphs_in_python_lessons/01_representing_graphs_in_code/advanced_implementations/base_classes/node.py index 9ac27b5..bcedbe2 100644 --- a/graphs_in_python_lessons/01_representing_graphs_in_code/advanced_implementations/base_classes/node.py +++ b/graphs_in_python_lessons/01_representing_graphs_in_code/advanced_implementations/base_classes/node.py @@ -12,10 +12,10 @@ def __repr__(self): def set_id(self, id): self.m_id = id - + def get_id(self): return self.m_id - + def get_name(self): return self.m_name diff --git a/graphs_in_python_lessons/01_representing_graphs_in_code/advanced_implementations/edge_list_graph.py b/graphs_in_python_lessons/01_representing_graphs_in_code/advanced_implementations/edge_list_graph.py index 607c48b..9ed104c 100644 --- a/graphs_in_python_lessons/01_representing_graphs_in_code/advanced_implementations/edge_list_graph.py +++ b/graphs_in_python_lessons/01_representing_graphs_in_code/advanced_implementations/edge_list_graph.py @@ -2,7 +2,7 @@ from base_classes.graph import Graph class EdgeListGraph(Graph): - + ################################### # Constructor ################################### @@ -25,14 +25,14 @@ def __init__(self, num_of_nodes, directed=True): ################################### def add_edge(self, node1_name, node2_name, weight=1): node1 = Node(node1_name) - node2 = Node(node2_name) + node2 = Node(node2_name) if (node1 not in self.m_nodes): node1_id = len(self.m_nodes) node1.set_id(node1_id) self.m_nodes.append(node1) else: node1 = self.get_node_by_name(node1_name) - + if (node2 not in self.m_nodes): node2_id = len(self.m_nodes) node2.set_id(node2_id) @@ -42,7 +42,7 @@ def add_edge(self, node1_name, node2_name, weight=1): # Add the edge from node1 to node2 self.m_graph.append([node1, node2, weight]) - + # If a graph is undirected, add the same edge, # but also in the opposite direction if not self.m_directed: @@ -68,7 +68,7 @@ def load_from_edge_list(self, edge_list): node2 = edge_list[i][1] weight = edge_list[i][2] self.add_edge(node1, node2, weight) - + ################################### # Print a graph representation ################################### @@ -78,7 +78,7 @@ def __str__(self): for i in range(num_of_edges): out += "edge " + str(i+1) + ": " + str(self.m_graph[i]) + "\n" return out - + ################################### # Find node in a graph using its name ################################### @@ -86,5 +86,5 @@ def get_node_by_name(self, name): search_node = Node(name) for node in self.m_nodes: if node == search_node: - return node + return node return None \ No newline at end of file diff --git a/graphs_in_python_lessons/01_representing_graphs_in_code/edge_list_graph_basic.py b/graphs_in_python_lessons/01_representing_graphs_in_code/edge_list_graph_basic.py index 66c97ae..8433071 100644 --- a/graphs_in_python_lessons/01_representing_graphs_in_code/edge_list_graph_basic.py +++ b/graphs_in_python_lessons/01_representing_graphs_in_code/edge_list_graph_basic.py @@ -3,15 +3,15 @@ class Graph: def __init__(self, num_of_nodes, directed=True): self.m_num_of_nodes = num_of_nodes self.m_directed = directed - + # Different representations of a graph self.m_list_of_edges = [] - + # Add edge to a graph - def add_edge(self, node1, node2, weight=1): + def add_edge(self, node1, node2, weight=1): # Add the edge from node1 to node2 self.m_list_of_edges.append([node1, node2, weight]) - + # If a graph is undirected, add the same edge, # but also in the opposite direction if not self.m_directed: @@ -35,6 +35,6 @@ def main(): graph.add_edge(4, 3, 11) graph.print_edge_list() - + if __name__=="__main__": main() \ No newline at end of file diff --git a/graphs_in_python_lessons/02_depth_first_search/dfs.py b/graphs_in_python_lessons/02_depth_first_search/dfs.py index 2e692c5..6490ed7 100644 --- a/graphs_in_python_lessons/02_depth_first_search/dfs.py +++ b/graphs_in_python_lessons/02_depth_first_search/dfs.py @@ -3,21 +3,21 @@ class Graph: def __init__(self, num_of_nodes, directed=True): self.m_num_of_nodes = num_of_nodes self.m_nodes = range(self.m_num_of_nodes) - + # Directed or Undirected self.m_directed = directed - + # Graph representation - Adjacency list # We use a dictionary to implement an adjacency list - self.m_adj_list = {node: set() for node in self.m_nodes} - + self.m_adj_list = {node: set() for node in self.m_nodes} + # Add edge to the graph def add_edge(self, node1, node2, weight=1): self.m_adj_list[node1].add((node2, weight)) if not self.m_directed: self.m_adj_list[node2].add((node1, weight)) - + # Print the graph representation def print_adj_list(self): for key in self.m_adj_list.keys(): @@ -34,7 +34,7 @@ def dfs(self, start, target, path = [], visited = set()): if result is not None: return result path.pop() - return None + return None def main(): graph = Graph(5, directed=False) diff --git a/graphs_in_python_lessons/03_breadth_first_search/bfs.py b/graphs_in_python_lessons/03_breadth_first_search/bfs.py index e191b7a..4c0b99a 100644 --- a/graphs_in_python_lessons/03_breadth_first_search/bfs.py +++ b/graphs_in_python_lessons/03_breadth_first_search/bfs.py @@ -5,26 +5,26 @@ class Graph: def __init__(self, num_of_nodes, directed=True): self.m_num_of_nodes = num_of_nodes self.m_nodes = range(self.m_num_of_nodes) - + # Directed or Undirected self.m_directed = directed - + # Graph representation - Adjacency list # We use a dictionary to implement an adjacency list - self.m_adj_list = {node: set() for node in self.m_nodes} - + self.m_adj_list = {node: set() for node in self.m_nodes} + # Add edge to the graph def add_edge(self, node1, node2, weight=1): self.m_adj_list[node1].add((node2, weight)) if not self.m_directed: self.m_adj_list[node2].add((node1, weight)) - + # Print the graph representation def print_adj_list(self): for key in self.m_adj_list.keys(): print("node", key, ": ", self.m_adj_list[key]) - + def bfs(self, start_node, target_node): # Set of visited nodes to prevent loops visited = set() @@ -33,7 +33,7 @@ def bfs(self, start_node, target_node): # Add the start_node to the queue and visited list queue.put(start_node) visited.add(start_node) - + # start_node has not parents parent = dict() parent[start_node] = None @@ -51,16 +51,16 @@ def bfs(self, start_node, target_node): queue.put(next_node) parent[next_node] = current_node visited.add(next_node) - + # Path reconstruction path = [] if path_found: path.append(target_node) while parent[target_node] is not None: - path.append(parent[target_node]) + path.append(parent[target_node]) target_node = parent[target_node] path.reverse() - return path + return path def bfs_traversal(self, start_node): visited = set() diff --git a/graphs_in_python_lessons/04_dijkstra/dijkstra.py b/graphs_in_python_lessons/04_dijkstra/dijkstra.py index f889eb2..597a917 100644 --- a/graphs_in_python_lessons/04_dijkstra/dijkstra.py +++ b/graphs_in_python_lessons/04_dijkstra/dijkstra.py @@ -5,7 +5,7 @@ def __init__(self, num_of_vertices): self.v = num_of_vertices self.edges = [[-1 for i in range(num_of_vertices)] for j in range(num_of_vertices)] self.visited = [] - + def add_edge(self, u, v, weight): self.edges[u][v] = weight self.edges[v][u] = weight @@ -13,14 +13,14 @@ def add_edge(self, u, v, weight): def dijkstra(self, start_vertex): D = {v:float('inf') for v in range(self.v)} D[start_vertex] = 0 - + pq = PriorityQueue() pq.put((0, start_vertex)) - + while not pq.empty(): (dist, current_vertex) = pq.get() self.visited.append(current_vertex) - + for neighbor in range(self.v): if self.edges[current_vertex][neighbor] != -1: distance = self.edges[current_vertex][neighbor] @@ -32,7 +32,7 @@ def dijkstra(self, start_vertex): D[neighbor] = new_cost return D - + def main(): g = Graph(9) g.add_edge(0, 1, 4) @@ -49,7 +49,7 @@ def main(): g.add_edge(4, 8, 5) g.add_edge(5, 8, 12) g.add_edge(6, 7, 1) - g.add_edge(7, 8, 3) + g.add_edge(7, 8, 3) D = g.dijkstra(0) print(D) diff --git a/graphs_in_python_lessons/07_mst_kruskal/kruskal.py b/graphs_in_python_lessons/07_mst_kruskal/kruskal.py index 88b22da..caffb59 100644 --- a/graphs_in_python_lessons/07_mst_kruskal/kruskal.py +++ b/graphs_in_python_lessons/07_mst_kruskal/kruskal.py @@ -27,7 +27,7 @@ def connect_subtrees(self, parent, subtree_sizes, x, y): def kruskals_mst(self): # Resulting tree result = [] - + # Iterator i = 0 # Number of edges in MST @@ -35,7 +35,7 @@ def kruskals_mst(self): # Sort edges by their weight self.m_graph = sorted(self.m_graph, key=lambda item: item[2]) - + # Auxiliary arrays parent = [] subtree_sizes = [] @@ -46,7 +46,7 @@ def kruskals_mst(self): subtree_sizes.append(0) # Important property of MSTs - # number of egdes in a MST is + # number of egdes in a MST is # equal to (m_num_of_nodes - 1) while e < (self.m_num_of_nodes - 1): # Pick an edge with the minimal weight @@ -60,7 +60,7 @@ def kruskals_mst(self): e = e + 1 result.append([node1, node2, weight]) self.connect_subtrees(parent, subtree_sizes, x, y) - + # Print the resulting MST for node1, node2, weight in result: print("%d - %d: %d" % (node1, node2, weight)) @@ -88,4 +88,4 @@ def main(): graph.kruskals_mst() if __name__=="__main__": - main() \ No newline at end of file + main() \ No newline at end of file diff --git a/graphs_in_python_lessons/08_mst_prim/prim.py b/graphs_in_python_lessons/08_mst_prim/prim.py index 56341f3..acad508 100644 --- a/graphs_in_python_lessons/08_mst_prim/prim.py +++ b/graphs_in_python_lessons/08_mst_prim/prim.py @@ -2,7 +2,7 @@ class Graph: def __init__(self, num_of_nodes): self.m_num_of_nodes = num_of_nodes # Initialize the adjacency matrix with zeros - self.m_graph = [[0 for column in range(num_of_nodes)] + self.m_graph = [[0 for column in range(num_of_nodes)] for row in range(num_of_nodes)] def add_edge(self, node1, node2, weight): @@ -13,14 +13,14 @@ def prims_mst(self): # Defining a really big number, that'll always be the highest weight in comparisons postitive_inf = float('inf') - # This is a list showing which nodes are already selected + # This is a list showing which nodes are already selected # so we don't pick the same node twice and we can actually know when stop looking selected_nodes = [False for node in range(self.m_num_of_nodes)] # Matrix of the resulting MST - result = [[0 for column in range(self.m_num_of_nodes)] + result = [[0 for column in range(self.m_num_of_nodes)] for row in range(self.m_num_of_nodes)] - + indx = 0 # While there are nodes that are not included in the MST, keep looking: @@ -39,24 +39,24 @@ def prims_mst(self): if selected_nodes[i]: for j in range(self.m_num_of_nodes): # If the analyzed node have a path to the ending node AND its not included in the MST (to avoid cycles) - if (not selected_nodes[j] and self.m_graph[i][j]>0): + if (not selected_nodes[j] and self.m_graph[i][j]>0): # If the weight path analized is less than the minimum of the MST if self.m_graph[i][j] < minimum: # Defines the new minimum weight, the starting vertex and the ending vertex minimum = self.m_graph[i][j] start, end = i, j - + # Since we added the ending vertex to the MST, it's already selected: selected_nodes[end] = True # Filling the MST Adjacency Matrix fields: result[start][end] = minimum - + if minimum == postitive_inf: result[start][end] = 0 indx += 1 - + result[end][start] = result[start][end] # Print the resulting MST @@ -89,4 +89,4 @@ def main(): graph.prims_mst() if __name__=="__main__": - main() \ No newline at end of file + main() \ No newline at end of file