Skip to content

Instantly share code, notes, and snippets.

@HarshVardhanKumar
Created January 6, 2018 11:49
Show Gist options
  • Save HarshVardhanKumar/44f469c6d8339a50bfc5cac9462cac64 to your computer and use it in GitHub Desktop.
Save HarshVardhanKumar/44f469c6d8339a50bfc5cac9462cac64 to your computer and use it in GitHub Desktop.
Union Find Disjoint Sets implementation in c++
//
// Created by Harsh Vardhan Kumar on 01-01-2018.
//
#ifndef UNTITLED_UFDS_H
#define UNTITLED_UFDS_H
#include <vector>
#include <iostream>
#include <unordered_map>
template <class T> class UFDS {
private:
std::unordered_map<T, long> rank ;
std::unordered_map<T,T> parents ;
std::vector<T> elements ;
long no_of_disjoint_sets = 0 ;
public:
UFDS() {
// dummy constructor. User should call "resetTo" method after calling this constructor
}
UFDS(std::vector<T> & elements) {
T dummyElement ;
this->elements = elements ;
no_of_disjoint_sets = elements.size() ;
for(int i = 0 ; i<elements.size() ; i++) {
parents[elements[i]] = elements[i] ;
rank[elements[i]] = 0 ;
}
}
/**
* This method acts as the second constructor and reuses the pre-variable.
* Instead of creating a new variable for UFDS, we can call this method
* @param elements
*/
void resetTo(std::vector<T> & elements) {
clear() ;
T dummyElement ;
this->elements = elements ;
no_of_disjoint_sets = elements.size() ;
for(int i = 0 ; i<elements.size() ; i++) {
parents[elements[i]] = elements[i] ;
rank[elements[i]] = 0 ;
}
}
T findSet(T elementId) {
return parents[elementId] == elementId ? elementId : (parents[elementId] = findSet(parents[elementId])) ;
}
bool isSameSet(T element1, T element2) {
return findSet(element1) == findSet(element2) ;
}
/**
* If element1 and element2 are two different elements from two
* different sets, then the two sets are merged
* @param element1
* @param element2
*/
void unionElements(T element1, T element2) {
if(!isSameSet(element1, element2)) {
T parent1 = findSet(element1) ;
T parent2 = findSet(element2) ;
if(rank[parent1]>rank[parent2]) {
// parent1 has higher rank.
parents[parent2] = parent1 ;
}
else if(rank[parent2]>rank[parent1]) {
parents[parent1] = parent2 ;
} else {
parents[parent1] = parent2 ;
rank[parent2] ++ ;
}
no_of_disjoint_sets -- ;
}
/**
* Just for updating the parents of the elements
* Is useful when determining the size of the set of the element
*/
}
long number_of_disjoint_sets() {
return no_of_disjoint_sets ;
}
long sizeOfSet(T elementId) {
long size = 0 ;
for(T elementid : elements ){
findSet(elementid) ;
}
T parent = findSet(elementId) ;
for(std::pair<T, T> p : parents) {
if(p.second==parent) {
size++ ;
}
}
return size ;
}
long no_of_single_elements() {
long ans = 0 ;
for(std::pair<T,T> p : parents) {
if(p.first == p.second && rank[p.second] == 0) {
ans++ ;
}
}
return ans ;
}
std::vector<T> getFriends(T elementId) {
std::vector<T> result ;
for(T element: elements) {
findSet(element) ;
}
T parent = findSet(elementId) ;
for(std::pair<T,T> p : parents) {
if(p.second == parent) {
result.push_back(p) ;
}
}
return result ;
}
void clear() {
rank.clear() ;
parents.clear() ;
no_of_disjoint_sets = 0 ;
}
};
#endif //UNTITLED_UFDS_H
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment