I wrote a program to for percolation using union find (see here for details)
Union find:
#include<iostream>
class UF {
protected:
int N;
int *connections;
int *sz;
int *maxObj;
int numComponents;
int _getRoot(int p) {
while(p != connections[p]) {
// Path compression
connections[p] = connections[connections[p]];
p = connections[p];
}
return p;
}
public:
UF() {}
// Parametrized constructor
UF(int n) {
N = numComponents = n;
connections = new int[n];
maxObj = new int[n];
sz = new int[n];
for(int i = 0; i<n; i++) {
connections[i] = i;
sz[i] = 1;
maxObj[i] = i;
}
}
// ~UF() {
// delete [] connections;
// delete [] sz;
// delete [] maxObj;
// }
int findMax(int i) {
int root = _getRoot(i);
return maxObj[root];
}
int isConnectedGraph() {
std::cout << "No of components: " << numComponents << std::endl;
return numComponents == 1;
}
bool isConnected(int p, int q) {
return connections[p] == connections[q];
}
bool find(int p, int q) {
return _getRoot(p) == _getRoot(q);
}
void quickFind(int p, int q) {
// Eager algorithm
int label_p = connections[p];
int label_q = connections[q];
for(int i=0; i<N; i++) {
if(connections[i] == label_p || connections [i] == label_q) {
connections[i] = label_q;
}
}
}
void quickUnion(int p, int q) {
// Lazy approach
if(!isConnected(p, q)) {
int p_root = _getRoot(p);
int q_root = _getRoot(q);
int max = p_root > q_root ? p_root : q_root;
// Weighted quick union
if(sz[p_root] < sz[q_root]) {
connections[p_root] = q_root;
sz[q_root] += sz[p_root];
maxObj[q_root] = max;
} else {
connections[q_root] = p_root;
sz[p_root] += sz[q_root];
maxObj[p_root] = max;
}
numComponents -= 1;
}
}
void printConnectedComponents() {
std::cout << "Indices:" << std::endl;
for (int i = 0; i < N; i++) {
std::cout << i << " ";
}
std::cout << std::endl;
std::cout << "Connections:" << std::endl;
for (int i = 0; i < N; i++) {
std::cout << connections[i] << " ";
}
std::cout << std::endl;
std::cout << "Sizes:" << std::endl;
for (int i = 0; i < N; i++) {
std::cout << sz[i] << " ";
}
std::cout << std::endl;
}
};
Percolation:
#include "../union-find.h"
class Percolation {
private:
int **grid;
int N;
UF uf;
int totalOpenSites;
int site(int row, int col) {
if(row == 0) {
return 0;
}
if(row == N-1) {
return (N*N)-(2*N)+1;
}
return ((row-1)*N)+col+1;
}
public:
Percolation(int n) {
N = n;
grid = new int*[n];
for (int i=0; i < n; i++) {
grid[i] = new int[n];
for(int j=0; j<n; j++) {
grid[i][j] = 0;
}
}
uf = UF((n*n)-(2*n)+2);
totalOpenSites=0;
}
~Percolation() {
for (int i=0; i<N; i++) {
delete [] grid[i];
}
delete [] grid;
}
void open(int row, int col) {
if(!isOpen(row, col)) {
int center = site(row, col);
// std::cout << "Center site: " << center << std::endl;
grid[row][col]=1;
if(row-1 >= 0 && grid[row-1][col]) {
int north = site(row-1, col);
// std::cout << "North site: " << north << std::endl;
uf.quickUnion(center, north);
}
if(row+1 < N && grid[row+1][col]) {
int south = site(row+1, col);
// std::cout << "South site: " << south << std::endl;
uf.quickUnion(south, center);
}
if(col-1 >= 0 && grid[row][col-1]) {
int west = site(row, col-1);
// std::cout << "West site: " << west << std::endl;
uf.quickUnion(center, west);
}
if(col+1 < N &&grid[row][col+1]) {
int east = site(row, col+1);
// std::cout << "East site: " << east << std::endl;
uf.quickUnion(east, center);
}
totalOpenSites += 1;
}
}
bool isOpen(int row, int col) {
return grid[row][col] == 1;
}
bool isFull(int row, int col) {
return uf.find(0, site(row, col));
}
int numberOfOpenSites() {
return totalOpenSites;
}
bool percolates() {
return uf.find(0, (N*N)-2*N+1);
}
void printGrid() {
for(int i=0; i<N; i++) {
for(int j=0; j<N; j++) {
std::cout << grid[i][j] << " ";
}
std::cout << std::endl;
}
}
void printUF() {
uf.printConnectedComponents();
}
};
percolation.cpp
#include "percolation.h"
int main() {
Percolation p = Percolation(3);
std::cout << "Initiate..." << std::endl;
p.printGrid();
p.printUF();
std::cout << std::endl;
std::cout << "Open (0, 1):" << std::endl;
p.open(0, 1);
p.printGrid();
p.printUF();
std::cout << std::endl;
std::cout << "Open (0, 2):" << std::endl;
p.open(0, 2);
p.printGrid();
p.printUF();
std::cout << std::endl;
std::cout << "Open (1, 0):" << std::endl;
p.open(1, 0);
p.printGrid();
p.printUF();
std::cout << std::endl;
std::cout << "Open (1, 1):" << std::endl;
p.open(1, 1);
p.printGrid();
p.printUF();
std::cout << std::endl;
std::cout << "Open (2, 2):" << std::endl;
p.open(2, 2);
p.printGrid();
p.printUF();
std::cout << std::endl;
std::cout << "Open (1, 2):" << std::endl;
p.open(1, 2);
p.printGrid();
p.printUF();
std::cout << std::endl;
std::cout << "No of open sites: " << p.numberOfOpenSites() << std::endl;
bool percolates = p.percolates();
std::cout << "Percolates???" << "";
if(percolates) {
std::cout<<"YESSS!! :)";
} else {
std::cout<<"NO... :(";
}
return 0;
}
When I add destructor to union find class and run percolation.cpp
. I'm getting weird results with garbage values in class members connections, sz, maxObj
of union find class. When I remove the destructor, it's working fine.
Output without destructor:
Initiate...
0 0 0
0 0 0
0 0 0
Indices:
0 1 2 3 4
Connections:
0 1 2 3 4
Sizes:
1 1 1 1 1
Open (0, 1):
0 1 0
0 0 0
0 0 0
Indices:
0 1 2 3 4
Connections:
0 1 2 3 4
Sizes:
1 1 1 1 1
Open (0, 2):
0 1 1
0 0 0
0 0 0
Indices:
0 1 2 3 4
Connections:
0 1 2 3 4
Sizes:
1 1 1 1 1
Open (1, 0):
0 1 1
1 0 0
0 0 0
Indices:
0 1 2 3 4
Connections:
0 1 2 3 4
Sizes:
1 1 1 1 1
Open (1, 1):
0 1 1
1 1 0
0 0 0
Indices:
0 1 2 3 4
Connections:
2 2 2 3 4
Sizes:
1 1 3 1 1
Open (2, 2):
0 1 1
1 1 0
0 0 1
Indices:
0 1 2 3 4
Connections:
2 2 2 3 4
Sizes:
1 1 3 1 1
Open (1, 2):
0 1 1
1 1 1
0 0 1
Indices:
0 1 2 3 4
Connections:
2 2 2 2 2
Sizes:
1 1 5 1 1
No of open sites: 6
Percolates???YESSS!! :)
Output with destructor:
Initiate...
0 0 0
0 0 0
0 0 0
Indices:
0 1 2 3 4
Connections:
7502560 7503664 2 3 4
Sizes:
7474272 7503808 1 1 1
Open (0, 1):
0 1 0
0 0 0
0 0 0
Indices:
0 1 2 3 4
Connections:
7502560 7503664 2 3 4
Sizes:
7474272 7503808 1 1 1
Open (0, 2):
0 1 1
0 0 0
0 0 0
Indices:
0 1 2 3 4
Connections:
7502560 7503664 2 3 4
Sizes:
7474272 7503808 1 1 1
Open (1, 0):
0 1 1
1 0 0
0 0 0
Indices:
0 1 2 3 4
Connections:
7502560 7503664 2 3 4
Sizes:
7474272 7503808 1 1 1
Open (1, 1):
The program doesn't even complete running when I add the destructor to union find class. Why is this happening?