From f33cf1379d221cd95120cf97e6ea0e5e691b38f3 Mon Sep 17 00:00:00 2001 From: Ivan Markovic Date: Tue, 25 Oct 2022 19:11:26 +0200 Subject: [PATCH 01/15] Update chaining.py --- hash-table/chaining.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/hash-table/chaining.py b/hash-table/chaining.py index d022cdb..c7f4d3a 100644 --- a/hash-table/chaining.py +++ b/hash-table/chaining.py @@ -90,8 +90,12 @@ def delete(self, key: int) -> None: found = True else: i += 1 - if found: - items.pop(i) + if not found: + return None + + items.pop(i) + if len(items) == 0: + self.table[index] = None return None From 426dd539824110138b72e2527dcc8324324da248 Mon Sep 17 00:00:00 2001 From: Ivan Markovic Date: Wed, 21 Dec 2022 11:47:10 +0100 Subject: [PATCH 02/15] Update queue-array-impl.py --- queue/queue-array-impl.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/queue/queue-array-impl.py b/queue/queue-array-impl.py index e4df970..8bb8b70 100644 --- a/queue/queue-array-impl.py +++ b/queue/queue-array-impl.py @@ -6,6 +6,8 @@ def enqueue(self, item): self._queue.insert(0, item) def dequeue(self): + if self.is_empty(): + raise Exception('Queue is empty') return self._queue.pop() def size(self) -> int: From 52401b3871dfe3c1129710d91cb9648fc3542a05 Mon Sep 17 00:00:00 2001 From: Ivan Markovic Date: Mon, 23 Jan 2023 23:22:41 +0100 Subject: [PATCH 03/15] Update graph.py --- .../kruskals-algorithm/graph.py | 96 ++++++++----------- 1 file changed, 42 insertions(+), 54 deletions(-) diff --git a/graphs/minimum-spanning-tree/kruskals-algorithm/graph.py b/graphs/minimum-spanning-tree/kruskals-algorithm/graph.py index 8f35405..c437f23 100644 --- a/graphs/minimum-spanning-tree/kruskals-algorithm/graph.py +++ b/graphs/minimum-spanning-tree/kruskals-algorithm/graph.py @@ -1,57 +1,45 @@ -from vertex import Vertex - -def find_root(vertex: Vertex = None) -> Vertex: - while vertex.root != vertex: - vertex = vertex.root - return vertex - -def sort_edges_by_weight_increasingly(edges: list) -> list: - # edges [[label1, label2, weight], [label1, label2, weight]] - if len(edges) < 2: - return edges - - pivot_index: int = len(edges) // 2 - pivot_value = edges[pivot_index][2] - left_list: list = [] - right_list: list = [] - for i in range(len(edges)): - if i != pivot_index: - if edges[i][2] < pivot_value: - left_list.append(edges[i]) - else: - right_list.append(edges[i]) - - return sort_edges_by_weight_increasingly(left_list) + [edges[pivot_index]] + sort_edges_by_weight_increasingly(right_list) +from typing import Set, Dict, List, Tuple +class Graph: + def __init__(self) -> None: + self.vertices:Set[str] = set() + self.root:Dict[str, str] = dict() + self.rank:Dict[str, int] = dict() + self.edges:List[Tuple[str, str, int]] = list() + self.mst:List[Tuple[str, str, int]] = list() -class Graph: - def __init__(self): - self.vertices: dict = {} - self.edges: list = [] - - def add_vertex(self, label: str = None): - self.vertices[label] = Vertex(label) - - def add_edge(self, vertex_1_label: str = None, vertex_2_label: str = None, weight: int = float("inf")): - if vertex_1_label not in self.vertices or vertex_2_label not in self.vertices: - raise Exception("Invalid label name") - self.edges.append([vertex_1_label, vertex_2_label, weight]) - self.edges.append([vertex_2_label, vertex_1_label, weight]) - - def kruskal(self): - # sort edges by weight increasingly - self.edges = sort_edges_by_weight_increasingly(self.edges) - minimum_spanning_tree: list = [] - for edge_list in self.edges: - vertex_one: Vertex = self.vertices[edge_list[0]] - vertex_two: Vertex = self.vertices[edge_list[1]] - - root_one: Vertex = find_root(vertex_one) - root_two: Vertex = find_root(vertex_two) - - if root_one != root_two: - root_one.root = root_two - minimum_spanning_tree.append([vertex_one.label, vertex_two.label]) - - print(minimum_spanning_tree) \ No newline at end of file + + def add_vertex(self, label:str) -> None: + self.vertices.add(label) + self.root[label] = label + self.rank[label] = 0 + + + def add_edge(self, label1:str, label2:str, weight:int) -> None: + self.edges.append((label1, label2, weight)) + + + def kruskal(self) -> None: + self.edges.sort(key = lambda edge: edge[2]) + for l1, l2, weight in self.edges: + + root1:str = self._find_root(l1) + root2:str = self._find_root(l2) + + if root1 != root2: + if self.rank[root1] > self.rank[root2]: + self.root[root2] = root1 + self.rank[root1] = self.rank[root1] + 1 + else: + self.root[root1] = root2 + self.rank[root2] = self.rank[root2] + 1 + self.mst.append((l1, l2, weight)) + + print(self.mst) + + + def _find_root(self, label:str) -> str: + if self.root[label] != label: + self.root[label] = self._find_root(self.root[label]) + return self.root[label] From 1a6e8fd5b93c9fe87231bef57bd92b81a40ae38d Mon Sep 17 00:00:00 2001 From: Ivan Markovic Date: Mon, 23 Jan 2023 23:22:58 +0100 Subject: [PATCH 04/15] Delete vertex.py --- graphs/minimum-spanning-tree/kruskals-algorithm/vertex.py | 4 ---- 1 file changed, 4 deletions(-) delete mode 100644 graphs/minimum-spanning-tree/kruskals-algorithm/vertex.py diff --git a/graphs/minimum-spanning-tree/kruskals-algorithm/vertex.py b/graphs/minimum-spanning-tree/kruskals-algorithm/vertex.py deleted file mode 100644 index e18cd8d..0000000 --- a/graphs/minimum-spanning-tree/kruskals-algorithm/vertex.py +++ /dev/null @@ -1,4 +0,0 @@ -class Vertex: - def __init__(self, label: str = None): - self.label: str = label - self.root = self From 42f9b62b312c5d437a002fe0f688a0e72a298eca Mon Sep 17 00:00:00 2001 From: Ivan Markovic Date: Mon, 5 Feb 2024 23:34:40 +0100 Subject: [PATCH 05/15] Update graph.py --- graphs/is-graph-bipartite/graph.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/graphs/is-graph-bipartite/graph.py b/graphs/is-graph-bipartite/graph.py index ba42c63..37bf939 100644 --- a/graphs/is-graph-bipartite/graph.py +++ b/graphs/is-graph-bipartite/graph.py @@ -16,7 +16,7 @@ def add_edge(self, label1: str = None, label2: str = None): self.adjacency_list[label1].append(label2) self.adjacency_list[label2].append(label1) - def is_bipartite(self) -> bool: + def bipartite_check(self) -> bool: for vertex in self.vertices: if self.color[vertex] is not None: continue From 0897daf8aed65c0aa634c36e6e167772ba5e354e Mon Sep 17 00:00:00 2001 From: Ivan Markovic Date: Mon, 27 May 2024 12:52:01 +0200 Subject: [PATCH 06/15] Update graph.py Prims algorithm --- graphs/minimum-spanning-tree/prims-algorithm/graph.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/graphs/minimum-spanning-tree/prims-algorithm/graph.py b/graphs/minimum-spanning-tree/prims-algorithm/graph.py index a477449..ff718d7 100644 --- a/graphs/minimum-spanning-tree/prims-algorithm/graph.py +++ b/graphs/minimum-spanning-tree/prims-algorithm/graph.py @@ -20,7 +20,7 @@ def add_vertex(self, label:str, weight:int=float('inf')): def add_edge(self, label1:str, label2:str, weight:int): self.adjacency_map[label1].append(Vertex(label2, weight)) - self.adjacency_map[label1].append(Vertex(label1, weight)) + self.adjacency_map[label2].append(Vertex(label1, weight)) def prims(self, label:str): From a62614f0bb792977c2da0be442812108044d1321 Mon Sep 17 00:00:00 2001 From: Ivan Markovic Date: Wed, 19 Jun 2024 13:04:10 +0200 Subject: [PATCH 07/15] Update convert-number-iterative.py --- recursion/convert-number-iterative.py | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/recursion/convert-number-iterative.py b/recursion/convert-number-iterative.py index 41bfa15..e43b723 100644 --- a/recursion/convert-number-iterative.py +++ b/recursion/convert-number-iterative.py @@ -13,4 +13,16 @@ def converter(num: int, base: int) -> str: return result -print(converter(1453, 16)) # 5AD \ No newline at end of file +''' +digits = "0123456789ABCDEF" +def converter(num: int, base: int) -> str: + + r:str = '' + while num > 0: + r = digits[num % base] + r + num = num // base + + return r +''' + +print(converter(1453, 16)) # 5AD From 75d6161163c97addb8de5338fbacd8537dc47101 Mon Sep 17 00:00:00 2001 From: Ivan Markovic Date: Tue, 3 Dec 2024 14:29:17 +0100 Subject: [PATCH 08/15] Dijkstra adjacency list impl, no priority queue --- .../__pycache__/vertex.cpython-312.pyc | Bin 0 -> 649 bytes graphs/dijkstra/adjacency-list-impl/main.py | 87 ++++++++++++++++++ graphs/dijkstra/adjacency-list-impl/vertex.py | 7 ++ 3 files changed, 94 insertions(+) create mode 100644 graphs/dijkstra/adjacency-list-impl/__pycache__/vertex.cpython-312.pyc create mode 100644 graphs/dijkstra/adjacency-list-impl/main.py create mode 100644 graphs/dijkstra/adjacency-list-impl/vertex.py diff --git a/graphs/dijkstra/adjacency-list-impl/__pycache__/vertex.cpython-312.pyc b/graphs/dijkstra/adjacency-list-impl/__pycache__/vertex.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..9a186d6d1037c866e48e27f71b2bcdf1f472184e GIT binary patch literal 649 zcmYLGO=}ZD7=CBJT2o7Z&!c*vm# zy?BW~LGdE^GyDT(Z{i=QMi4wXZ+4?|c%J9|oOj;&y1Cf_d!DU58NRdp9gWrTTCuoh z#T*=X3>;>_$tS0Y^r3P>H(BK)`>nCKZN(e}^a+Q)udo#Zu zRDKxL!Be4(cu~7)KB#@kj)bg(Q;`lwCUM)oNO(Kii>`$^Ovx0eRn3_?)@ttos30W0 z&`~&+3M_niLu8m?b(?AN0aCtj$>_ zD6Kn`W(6-L>dTa#luWh}e;^BHYS)f}D>e#${v)UjOX?B=Zej^2^p1rYe7ke+bNOZG z2RQ!j`{V-Y!`)vh=9*l>6$c4dAEfEejVeA>?=9k=>tQVOj7O DzyF#3 literal 0 HcmV?d00001 diff --git a/graphs/dijkstra/adjacency-list-impl/main.py b/graphs/dijkstra/adjacency-list-impl/main.py new file mode 100644 index 0000000..2de3e50 --- /dev/null +++ b/graphs/dijkstra/adjacency-list-impl/main.py @@ -0,0 +1,87 @@ + +from typing import List, Dict, Set + +from vertex import Vertex + + +class Graph: + + def __init__(self, capacity :int =10): + self.capacity :int = capacity + self.vertices :Dict[str, Vertex] = dict() + self.prev :Dict[str, str] = dict() + self.adjacency_list :Dict[str, List[Vertex]] = dict() + self.visited :Set[str] = set() + + + + def add_vertex(self, label :str, weight :int = float('inf')) -> None: + v :Vertex = Vertex(label, weight) + self.vertices[v.label] = v + self.adjacency_list[label] = list() + self.prev[label] = None + + + def add_edge(self, label1 :str, label2 :str, weight :int) -> None: + v :Vertex = Vertex(label2, weight) + self.adjacency_list[label1].append(v) + + + def dijkstra(self, label :str) -> None: + v :Vertex = self.vertices[label] + v.weight = 0 + + while v is not None: + for n in self.adjacency_list[v.label]: + o :Vertex = self.vertices[n.label] + if v.weight + n.weight < o.weight: + o.weight = v.weight + n.weight + self.prev[o.label] = v.label + self.visited.add(v.label) + v = self._find_cheapest_vertex() + + + def show_path(self, label :str) -> str: + if self.prev[label] is None: + return label + return self.show_path(self.prev[label]) + '->' + label + + + def _find_cheapest_vertex(self) -> Vertex: + vertex :Vertex = None + for v in self.vertices.values(): + if v.label not in self.visited: + if vertex is None: + vertex = v + elif vertex.weight > v.weight: + vertex = v + + return vertex + + + +graph: Graph = Graph() + +graph.add_vertex("START") +graph.add_vertex("A") +graph.add_vertex("C") +graph.add_vertex("B") +graph.add_vertex("D") +graph.add_vertex("END") + +graph.add_edge("START", "A", 0) +graph.add_edge("START", "C", 2) +graph.add_edge("A", "B", 18) +graph.add_edge("A", "D", 15) +graph.add_edge("C", "B", 3) +graph.add_edge("C", "D", 10) +graph.add_edge("B", "END", 150) +graph.add_edge("D", "END", 15) +graph.dijkstra("START") + +print(graph.show_path("END")) + + + + + diff --git a/graphs/dijkstra/adjacency-list-impl/vertex.py b/graphs/dijkstra/adjacency-list-impl/vertex.py new file mode 100644 index 0000000..e87185a --- /dev/null +++ b/graphs/dijkstra/adjacency-list-impl/vertex.py @@ -0,0 +1,7 @@ + + +class Vertex: + + def __init__(self, label :str, weight :int = float('inf')): + self.label :str = label + self.weight :int = weight \ No newline at end of file From c13d056244a732f71139b7b20f6ccab9d0486c8b Mon Sep 17 00:00:00 2001 From: Ivan Markovic Date: Tue, 3 Dec 2024 14:33:43 +0100 Subject: [PATCH 09/15] Update Readme, add link for Dijkstra adjacency list implementation --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 477e006..07edb7e 100644 --- a/README.md +++ b/README.md @@ -111,6 +111,7 @@ but it also contains other data structures, algorithms and problems. - [Dijkstra algorithm - Shortest path](https://github.com/ivanmmarkovic/Problem-Solving-with-Algorithms-and-Data-Structures-using-Python/tree/master/graphs/dijkstra) - [Priority Queue implementation](https://github.com/ivanmmarkovic/Problem-Solving-with-Algorithms-and-Data-Structures-using-Python/tree/master/graphs/dijkstra/priority-queue-impl-adjacency-map) - [Matrix implementation](https://github.com/ivanmmarkovic/Problem-Solving-with-Algorithms-and-Data-Structures-using-Python/tree/master/graphs/dijkstra/matrix-impl) + - [Adjacency list implementation](https://github.com/ivanmmarkovic/Problem-Solving-with-Algorithms-and-Data-Structures-using-Python/tree/master/graphs/dijkstra/adjacency-list-impl) - [Bellman-Ford algorithm](https://github.com/ivanmmarkovic/Problem-Solving-with-Algorithms-and-Data-Structures-using-Python/tree/master/graphs/bellman-ford) - [Bellman-Ford algorithm - negative weight cycle](https://github.com/ivanmmarkovic/Problem-Solving-with-Algorithms-and-Data-Structures-using-Python/tree/master/graphs/bellman-ford-negative-weight-cycle) - [Minimum Spanning Tree](https://github.com/ivanmmarkovic/Problem-Solving-with-Algorithms-and-Data-Structures-using-Python/tree/master/graphs/minimum-spanning-tree) From 2e8ba81581d702f5c0101c5ff71ad482c1ee0d5f Mon Sep 17 00:00:00 2001 From: Ivan Markovic Date: Fri, 18 Apr 2025 15:46:34 +0200 Subject: [PATCH 10/15] Update README.md --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 07edb7e..4d588d7 100644 --- a/README.md +++ b/README.md @@ -52,7 +52,8 @@ but it also contains other data structures, algorithms and problems. - [Fibonacci - recursive worst solution](https://github.com/ivanmmarkovic/Problem-Solving-with-Algorithms-and-Data-Structures-using-Python/blob/master/recursion/fibonacci-recursive-worst-solution.py) - [Fibonacci - memoization](https://github.com/ivanmmarkovic/Problem-Solving-with-Algorithms-and-Data-Structures-using-Python/blob/master/recursion/fibonacci-memoization.py) - [Fibonacci - recursive solution](https://github.com/ivanmmarkovic/Problem-Solving-with-Algorithms-and-Data-Structures-using-Python/blob/master/recursion/fibonacci-recursive.py) -- [Fibonacci sum](https://github.com/ivanmmarkovic/Problem-Solving-with-Algorithms-and-Data-Structures-using-Python/blob/master/recursion/fibonacci-sum-recursive.py) +- [Fibonacci sum recursive](https://github.com/ivanmmarkovic/Problem-Solving-with-Algorithms-and-Data-Structures-using-Python/blob/master/recursion/fibonacci-sum-recursive.py) +- [Fibonacci sum iterative](https://github.com/ivanmmarkovic/Problem-Solving-with-Algorithms-and-Data-Structures-using-Python/blob/master/recursion/fibonacci-sum-iterative.py) - [Maze - path finder](https://github.com/ivanmmarkovic/Problem-Solving-with-Algorithms-and-Data-Structures-using-Python/blob/master/recursion/maze.py) - [Palindrome](https://github.com/ivanmmarkovic/Problem-Solving-with-Algorithms-and-Data-Structures-using-Python/blob/master/recursion/palindrome.py) - [Reverse linked list - recursive solution](https://github.com/ivanmmarkovic/Problem-Solving-with-Algorithms-and-Data-Structures-using-Python/blob/master/recursion/reverse-linked-list.py) From 476aff09cae258f1c4fd9a3f29a5106a2b685c6a Mon Sep 17 00:00:00 2001 From: Ivan Markovic Date: Fri, 8 Aug 2025 01:01:31 +0200 Subject: [PATCH 11/15] Update graph.py --- graphs/bellman-ford/graph.py | 93 ++++++++++++++++++++++++------------ 1 file changed, 62 insertions(+), 31 deletions(-) diff --git a/graphs/bellman-ford/graph.py b/graphs/bellman-ford/graph.py index 5074fd2..2381d97 100755 --- a/graphs/bellman-ford/graph.py +++ b/graphs/bellman-ford/graph.py @@ -4,44 +4,75 @@ # to all other vertices in weighted graph. # Runtime O(V*E) +from typing import Set, Dict, List, Tuple + + class Graph: - def __init__(self): - self.vertices: list = [] - self.edges: list = [] - self.distance: dict = {} - self.prev: dict = {} - - def add_vertex(self, label: str): - self.vertices.append(label) - self.distance[label] = None + + + def __init__(self) -> None: + self.vertices:Set[str] = set() + self.edges:List[Tuple[str, str, int]] = list() + self.prev:Dict[str, str] = dict() + self.distances:Dict[str, int] = dict() + + + def add_vertex(self, label:str) -> None: + self.vertices.add(label) self.prev[label] = None + self.distances[label] = None - def add_edge(self, label1: str, label2: str, weight: int): - self.edges.append([label1, label2, weight]) - def bellman_ford(self, source: str): - self.distance[source] = 0 + def add_edge(self, v1:str, v2:str, distance:int) -> None: + self.edges.append((v1, v2, distance)) - for _ in range(len(self.vertices)): - for edge in self.edges: - label1: str = edge[0] - label2: str = edge[1] - weight: int = edge[2] + def bellman_ford(self, label:str) -> None: + self.distances[label] = 0 - if self.distance[label1] is None: - continue - if self.distance[label2] is None: - self.distance[label2] = self.distance[label1] + weight - self.prev[label2] = label1 - continue - if self.distance[label1] + weight < self.distance[label2]: - self.distance[label2] = self.distance[label1] + weight - self.prev[label2] = label1 + for _ in range(len(self.vertices) - 1): + + for v1, v2, distance in self.edges: + if self.distances[v1] is None: continue + if self.distances[v2] is None or self.distances[v2] > self.distances[v1] + distance: + self.distances[v2] = self.distances[v1] + distance + self.prev[v2] = v1 + + # Check for negative-weight cycles + for v1, v2, distance in self.edges: + if self.distances[v1] is not None and self.distances[v2] > self.distances[v1] + distance: + raise ValueError("Graph contains a negative-weight cycle") - def print_distances(self, source: str): + self._print_paths(label) + + + def _print_paths(self, label:str) -> None: for v in self.vertices: - if v != source: - distance: int = self.distance[v] - print(f'Distance from {source} to {v} is {distance}') \ No newline at end of file + if v == label: + continue + if self.distances[v] is not None: + print(f'Path from {label} to {v} is {self._return_path(v)} and distance is {self.distances[v]}') + else: + print(f'No path from {label} to {v}') + + + def _return_path(self, label:str) -> str: + if self.prev[label] is None: + return label + return self._return_path(self.prev[label]) + ' -> ' + label + + + +g = Graph() +for v in ['A', 'B', 'C', 'D']: + g.add_vertex(v) + +g.add_edge('A', 'B', 1) +g.add_edge('B', 'C', 3) +g.add_edge('A', 'C', 10) +g.add_edge('C', 'D', 2) +g.add_edge('D', 'B', 4) + +g.bellman_ford('A') + From cdac2cbb10285e1cce3b631acca0999d3d1e7390 Mon Sep 17 00:00:00 2001 From: Ivan Markovic Date: Fri, 8 Aug 2025 01:30:33 +0200 Subject: [PATCH 12/15] Update graph.py --- .../kruskals-algorithm/graph.py | 50 +++++++++++-------- 1 file changed, 29 insertions(+), 21 deletions(-) diff --git a/graphs/minimum-spanning-tree/kruskals-algorithm/graph.py b/graphs/minimum-spanning-tree/kruskals-algorithm/graph.py index c437f23..028107d 100644 --- a/graphs/minimum-spanning-tree/kruskals-algorithm/graph.py +++ b/graphs/minimum-spanning-tree/kruskals-algorithm/graph.py @@ -1,45 +1,53 @@ -from typing import Set, Dict, List, Tuple + +from typing import List, Set, Dict, Tuple class Graph: + def __init__(self) -> None: self.vertices:Set[str] = set() - self.root:Dict[str, str] = dict() - self.rank:Dict[str, int] = dict() + self.roots:Dict[str, str] = dict() + self.sizes:Dict[str, int] = dict() self.edges:List[Tuple[str, str, int]] = list() self.mst:List[Tuple[str, str, int]] = list() - + def add_vertex(self, label:str) -> None: self.vertices.add(label) - self.root[label] = label - self.rank[label] = 0 + self.roots[label] = label + self.sizes[label] = 1 def add_edge(self, label1:str, label2:str, weight:int) -> None: + if label1 not in self.vertices or label2 not in self.vertices: + raise Exception("Vertices must be added before connecting them") self.edges.append((label1, label2, weight)) - def kruskal(self) -> None: + def kruskal(self) -> List[Tuple[str, str, int]]: + self.mst.clear() self.edges.sort(key = lambda edge: edge[2]) - for l1, l2, weight in self.edges: - root1:str = self._find_root(l1) - root2:str = self._find_root(l2) + for v1, v2, weight in self.edges: + + root1:str = self._find_root(v1) + root2:str = self._find_root(v2) if root1 != root2: - if self.rank[root1] > self.rank[root2]: - self.root[root2] = root1 - self.rank[root1] = self.rank[root1] + 1 + if self.sizes[root1] >= self.sizes[root2]: + self.roots[root2] = root1 + self.sizes[root1] += self.sizes[root2] else: - self.root[root1] = root2 - self.rank[root2] = self.rank[root2] + 1 - self.mst.append((l1, l2, weight)) + self.roots[root1] = root2 + self.sizes[root2] += self.sizes[root1] + self.mst.append((v1, v2, weight)) + + return list(self.mst) + + def _find_root(self, label:str) -> str: + if self.roots[label] != label: + self.roots[label] = self._find_root(self.roots[label]) + return self.roots[label] - print(self.mst) - def _find_root(self, label:str) -> str: - if self.root[label] != label: - self.root[label] = self._find_root(self.root[label]) - return self.root[label] From 8d34862221aee96c6bfe238ba96831126b991a76 Mon Sep 17 00:00:00 2001 From: Ivan Markovic Date: Fri, 8 Aug 2025 01:31:27 +0200 Subject: [PATCH 13/15] Update main.py --- graphs/minimum-spanning-tree/kruskals-algorithm/main.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/graphs/minimum-spanning-tree/kruskals-algorithm/main.py b/graphs/minimum-spanning-tree/kruskals-algorithm/main.py index 0caa660..e761e99 100644 --- a/graphs/minimum-spanning-tree/kruskals-algorithm/main.py +++ b/graphs/minimum-spanning-tree/kruskals-algorithm/main.py @@ -19,4 +19,4 @@ g.add_edge('c', 'f', 2) g.add_edge('f', 'e', 1) -g.kruskal() +print(g.kruskal()) From da041ed1523cbb605a767314aa569e9864e6ff59 Mon Sep 17 00:00:00 2001 From: Ivan Markovic Date: Fri, 8 Aug 2025 01:50:08 +0200 Subject: [PATCH 14/15] Update graph.py --- graphs/kosarajus-algorithm/graph.py | 75 +++++++++++++++-------------- 1 file changed, 39 insertions(+), 36 deletions(-) diff --git a/graphs/kosarajus-algorithm/graph.py b/graphs/kosarajus-algorithm/graph.py index f57f10b..2a05e95 100755 --- a/graphs/kosarajus-algorithm/graph.py +++ b/graphs/kosarajus-algorithm/graph.py @@ -6,63 +6,66 @@ class Graph: + def __init__(self) -> None: - self.vertices: List[str] = [] - self.colors: Dict[str, str] = {} - self.adjacency_list: Dict[str, Set[str]] = {} - self.adjacency_list_reversed: Dict[str, Set[str]] = {} - self.stack: Stack = Stack() - self.components: List[List[str]] = [] - - def add_vertex(self, label:str): - self.vertices.append(label) - self.colors[label] = 'white' + self.vertices:Set[str] = set() + self.adjacency_list:Dict[str, Set[str]] = dict() + self.adjacency_list_reversed:Dict[str, Set[str]] = dict() + self.visited:Set[str] = set() + self.stack:Stack = Stack() + + + def add_vertex(self, label:str) -> None: + self.vertices.add(label) self.adjacency_list[label] = set() self.adjacency_list_reversed[label] = set() - def add_edge(self, label1:str, label2:str): + + def add_edge(self, label1:str, label2:str) -> None: + if label1 not in self.vertices or label2 not in self.vertices: + raise Exception('Vertices are not added') self.adjacency_list[label1].add(label2) self.adjacency_list_reversed[label2].add(label1) - def kosaraju(self): - for label in self.vertices: - if self.colors[label] == 'white': - self.dfs(label) - for color in self.colors: - self.colors[color] = 'white' + def kosaraju(self) -> List[List[str]]: + for v in self.vertices: + if v not in self.visited: + self._dfs(v) + + self.visited.clear() + + connected_components:List[List[str]] = list() while not self.stack.is_empty(): - current:str = self.stack.pop() + v:str = self.stack.pop() + if v not in self.visited: + connected:List[str] = list() + self._dfs_reversed(v, connected) - if self.colors[current] == 'white': - connected_components: List[str] = [] - self.dfs_reversed(current, connected_components) + if len(connected) > 0: + connected_components.append(connected) - self.components.append(connected_components) + return list(connected_components) - print(self.components) - def dfs(self, label:str): - self.colors[label] = 'gray' + def _dfs(self, label:str) -> None: + self.visited.add(label) for n in self.adjacency_list[label]: - if self.colors[n] == 'white': - self.dfs(n) + if n not in self.visited: + self._dfs(n) - self.colors[label] = 'black' self.stack.push(label) - def dfs_reversed(self, label: str, connected_components:List[str]): - self.colors[label] = 'gray' - - for n in self.adjacency_list_reversed[label]: - if self.colors[n] == 'white': - self.dfs_reversed(n, connected_components) - connected_components.append(label) - self.colors[label] = 'black' + def _dfs_reversed(self, v:str, connected:List[str]) -> None: + connected.append(v) + self.visited.add(v) + for n in self.adjacency_list_reversed[v]: + if n not in self.visited: + self._dfs_reversed(n, connected) From e818d94da109cd1842073df2a9c0c8c7280478ba Mon Sep 17 00:00:00 2001 From: Ivan Markovic Date: Fri, 8 Aug 2025 01:50:33 +0200 Subject: [PATCH 15/15] Update main.py --- graphs/kosarajus-algorithm/main.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/graphs/kosarajus-algorithm/main.py b/graphs/kosarajus-algorithm/main.py index dd91e6b..c3b4ca9 100755 --- a/graphs/kosarajus-algorithm/main.py +++ b/graphs/kosarajus-algorithm/main.py @@ -15,4 +15,4 @@ g.add_edge('7', '6') g.add_edge('8', '7') -g.kosaraju() +print(g.kosaraju())