def count_components_union_find(adjacency_list): if not adjacency_list: return 0 union_find = UnionFind(len(adjacency_list)) for node in adjacency_list: for neighbor in adjacency_list[node]: union_find.union(node, neighbor) return union_find.num_components
def test_root_points_to_itself(self): """Test to ensure that the root of the set points to itself when created. """ elements = [0, 1, 2, 3] union_find = UnionFind(len(elements)) for element in elements: self.assertEqual(union_find.find(element), element)
def count_components_union_find(adjacency_matrix): if not adjacency_matrix: return 0 num_nodes = len(adjacency_matrix) union_find = UnionFind(num_nodes) for row_index, row in enumerate(adjacency_matrix): for col_index, col_value in enumerate(row): if col_value == 1: union_find.union(row_index, col_index) return union_find.num_components
def test_invalid_size(self): """Test to ensure that an exception is raised when the UnionFind is instantiated with a size that isn't greater than 0. """ with self.assertRaises(ValueError): union_find = UnionFind(0) with self.assertRaises(ValueError): union_find = UnionFind(-1) with self.assertRaises(ValueError): union_find = UnionFind(-2349)
def kruskals_algorithm(num_vertices, edge_list): # initialize UnionFind union_find = UnionFind(num_vertices) # Sort edges by ascending edge weight edge_list.sort(key=lambda e: e.weight) # final list of edges contained within the minimum spanning tree minimum_spanning_tree = [] total_tree_weight = 0 # Walk through list of edges unifying nodes which don't belong to the same set # within the union find for edge in edge_list: if union_find.find(edge.vertex_one) != union_find.find( edge.vertex_two): minimum_spanning_tree.append(edge) total_tree_weight += edge.weight union_find.union(edge.vertex_one, edge.vertex_two) # you can terminate early if there is only one set left in the union find if union_find.get_num_components() == 1: break # The graph contains multiple connected components and thus we cannot find a minimum spanning tree if union_find.get_num_components() > 1: return [], 0 return minimum_spanning_tree, total_tree_weight
def test_is_connected(self): """Test to ensure UnionFind reports that elements are in the same set after a union operation is performed. """ elements = [0, 1, 2, 3] union_find = UnionFind(len(elements)) for element in elements: #element should be connected to itself self.assertTrue(union_find.is_connected(element, element)) union_find.union(0, 1) self.assertTrue(union_find.is_connected(0, 1)) self.assertTrue(union_find.is_connected(1, 0)) self.assertFalse(union_find.is_connected(0, 2)) self.assertFalse(union_find.is_connected(0, 3)) self.assertFalse(union_find.is_connected(1, 2)) self.assertFalse(union_find.is_connected(1, 3)) self.assertFalse(union_find.is_connected(3, 2))
def test_num_components(self): """Test to ensure UnionFind reports the corrent number of components after a union operation. """ elements = [0, 1, 2, 3] union_find = UnionFind(len(elements)) self.assertEqual(union_find.get_num_components(), 4) union_find.union(0, 1) self.assertEqual(union_find.get_num_components(), 3) union_find.union(2, 3) self.assertEqual(union_find.get_num_components(), 2) union_find.union(1, 3) self.assertEqual(union_find.get_num_components(), 1) #since both are now in the same set, the number of #components should stay the same union_find.union(1, 2) self.assertEqual(union_find.get_num_components(), 1)
def test_element_out_of_range(self): """Test to ensure that the find method throws an exception when an element that is out of range of the Union Find is passed as an arguement. """ elements = [0, 1, 2, 3] union_find = UnionFind(len(elements)) with self.assertRaises(ValueError): union_find.find(5) with self.assertRaises(ValueError): union_find.find(-1) with self.assertRaises(ValueError): union_find.union(1, 6) with self.assertRaises(ValueError): union_find.union(-1, 3) with self.assertRaises(ValueError): union_find.is_connected(1, 78) with self.assertRaises(ValueError): union_find.is_connected(-10, 3)