Created
January 6, 2018 11:49
-
-
Save HarshVardhanKumar/44f469c6d8339a50bfc5cac9462cac64 to your computer and use it in GitHub Desktop.
Union Find Disjoint Sets implementation in c++
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// 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