I'm trying to speed up my union-find disjoint set data structure. The idea is that initially n
sets of single element sets are made, and put into a vector nodes. Each node has a parent node, and the highest parent of any particular index in the vector is the highest ranking member of set. Two concepts, union by rank and path compression, are used to achieve faster merging and finding times.
There are two querying types: Union of two values (and thus their sets), and checking if 2 members are in the same set.
Nevertheless, when using very large values for n
(such as 100,000,000) and and m (such as 1,000,000), the program takes a bit of time to run. Generally around 30 seconds for my machine.
#include <cstdlib>
#include <vector>
#include <iostream>
#include <string>
using namespace std;
int n; //number of total elements
int q; //number of queries
struct node
{
int data;
node* parent;
int rank;
node(int d);
};
node::node(int d)
{
data = d;
rank = 0;
parent = nullptr;
}
node* find(node* root)
{
if (root != root->parent)
root->parent = find(root->parent);
return root->parent;
}
void merge(node* one, node* two)
{
node* i = find(one);
node* j = find(two);
if (i->rank > j->rank)
j->parent = i;
else
i->parent = j;
if (i->rank == j->rank)
{
i->parent = j;
j->rank++;
}
}
int sameSet(int i, int j, vector<node*> v)
{
if (find(v.at(i - 1))->data == find(v.at(j - 1))->data)
return 1;
return 0;
}
int main(int argc, char** argv) {
cin >> n >> q;
vector<node*> v (n); //vector holding all pointers to sets of nodes
for (int i = 0; i < n; i++) //make n sets of 1 element each
{
node* n = new node(i);
n->parent = n;
v[i] = n;
}
}
Would using a map instead of a vector, for example, be faster? Am I not compressing the path correctly (so that every member of a sets immediate parent is the highest ranking member) or unionizing by rank? As far as I'm aware, both merge and find should take O(log n) if implemented in the most efficient way, making me think this should be faster than it is.