#ifndef __UF__H__
#define __UF__H__
#include<cassert>
//只记录id值,和哪个节点联通,效率最低
class UF1
{
private:
int *id;
int count;
public:
UF1(int n){
count = n;
id = new int[n];
for (size_t i = 0; i < n; i++){
id[i] = i;
}
}
~UF1(){
delete[] id;
}
int find(int p){
assert(p < count && p>=0);
return id[p];
}
bool isConnected(int p, int q){
return find(p) == find(q);
}
void unionElement(int p, int q){
int pId = find(p);
int qId = find(q);
if (pId == qId) return;
for (size_t i = 0; i < count; i++){
if (id[i] == pId)
id[i] = qId;
}
}
};
//id改为指向父节点,只需判断两个节点根节点是否相同,没考虑每个节点的高度,效率低
class UF2
{
private:
int *parent;
int count;
public:
UF2(int n){
count = n;
parent = new int[n];
for (size_t i = 0; i < n; i++){
parent[i] = i;
}
}
~UF2(){
delete[] parent;
}
int find(int p){
assert(p < count && p >= 0);
while (p!=parent[p]){
p = parent[p];
}
return p;
}
bool isConnected(int p, int q){
return find(p) == find(q);
}
void unionElement(int p, int q){
int pRoot = find(p);
int qRoot = find(q);
if (pRoot == qRoot) return;
parent[pRoot] = qRoot;
}
};
//基于每个节点的数据规模来优化,效率高,但可能出现极端情况
class UF3
{
private:
int *parent;
int *sz;
int count;
public:
UF3(int n){
count = n;
parent = new int[n];
sz = new int[n];
for (size_t i = 0; i < n; i++){
parent[i] = i;
sz[i] = i;
}
}
~UF3(){
delete[] parent;
delete[] sz;
}
int find(int p){
assert(p < count && p >= 0);
while (p != parent[p]){
p = parent[p];
}
return p;
}
bool isConnected(int p, int q){
return find(p) == find(q);
}
void unionElement(int p, int q){
int pRoot = find(p);
int qRoot = find(q);
if (pRoot == qRoot) return;
if (sz[pRoot] < sz[qRoot]){
parent[pRoot] = qRoot;
sz[qRoot] += sz[pRoot];
}
else{
parent[qRoot] = pRoot;
sz[pRoot] += sz[qRoot];
}
}
};
//基于每个节点的高度来优化,效率高,避免极端情况
class UF4
{
private:
int *parent;
int *rank;
int count;
public:
UF4(int n){
count = n;
parent = new int[n];
rank = new int[n];
for (size_t i = 0; i < n; i++){
parent[i] = i;
rank[i] = i;
}
}
~UF4(){
delete[] parent;
delete[] rank;
}
int find(int p){
assert(p < count && p >= 0);
while (p != parent[p]){
p = parent[p];
}
return p;
}
bool isConnected(int p, int q){
return find(p) == find(q);
}
void unionElement(int p, int q){
int pRoot = find(p);
int qRoot = find(q);
if (pRoot == qRoot) return;
if (rank[pRoot] < rank[qRoot]){
parent[pRoot] = qRoot;
}
else if (rank[pRoot] > rank[qRoot]){
parent[qRoot] = pRoot;
}
else{
parent[pRoot] = qRoot;
rank[qRoot] += 1;
}
}
};
//路径压缩,在查找根节点的过程中,让节点的父节点指向父节点的父节点,可跳过一步查找,实际效率最高
class UF5
{
private:
int *parent;
int *rank;
int count;
public:
UF5(int n){
count = n;
parent = new int[n];
rank = new int[n];
for (size_t i = 0; i < n; i++){
parent[i] = i;
rank[i] = i;
}
}
~UF5(){
delete[] parent;
delete[] rank;
}
int find(int p){
assert(p < count && p >= 0);
while (p != parent[p]){
parent[p] = parent[parent[p]];
p = parent[p];
}
return p;
}
bool isConnected(int p, int q){
return find(p) == find(q);
}
void unionElement(int p, int q){
int pRoot = find(p);
int qRoot = find(q);
if (pRoot == qRoot) return;
if (rank[pRoot] < rank[qRoot]){
parent[pRoot] = qRoot;
}
else if (rank[pRoot] > rank[qRoot]){
parent[qRoot] = pRoot;
}
else{
parent[pRoot] = qRoot;
rank[qRoot] += 1;
}
}
};
//路径压缩,在查找根节点的过程中,递归让每个节点的父节点均指向根节点,理论效率最高,但递归过程耗时,实际可能比上一个版本的路径压缩效率低
class UF6
{
private:
int *parent;
int *rank;
int count;
public:
UF6(int n){
count = n;
parent = new int[n];
rank = new int[n];
for (size_t i = 0; i < n; i++){
parent[i] = i;
rank[i] = i;
}
}
~UF6(){
delete[] parent;
delete[] rank;
}
int find(int p){
assert(p < count && p >= 0);
if (p != parent[p]){
parent[p] = find(parent[p]);
}
return parent[p];
}
bool isConnected(int p, int q){
return find(p) == find(q);
}
void unionElement(int p, int q){
int pRoot = find(p);
int qRoot = find(q);
if (pRoot == qRoot) return;
if (rank[pRoot] < rank[qRoot]){
parent[pRoot] = qRoot;
}
else if (rank[pRoot] > rank[qRoot]){
parent[qRoot] = pRoot;
}
else{
parent[pRoot] = qRoot;
rank[qRoot] += 1;
}
}
private:
};
#endif
#include"UF.h"
#include<iostream>
#include<ctime>
using namespace std;
template<typename Item>
void testTime(Item* uf, int n){
srand(time(NULL));
time_t startTime = clock();
for (int i = 0; i < n; i++){
int a = rand() % n;
int b = rand() % n;
uf->unionElement(a, b);
}
for (int i = 0; i < n; i++){
int a = rand() % n;
int b = rand() % n;
uf->isConnected(a, b);
}
time_t endTime = clock();
cout << "\t" << 2 * n << " ops, " << double(endTime - startTime) / CLOCKS_PER_SEC << " s" << endl;
}
template<typename Item>
void testUF(int n){
Item *uf1 = new Item(n);
testTime(uf1, n);
delete uf1;
}
int main(){
cout << "testUF1" << endl;
testUF<UF1>(10000);
cout << "testUF2" << endl;
testUF<UF2>(10000);
cout << "testUF3" << endl;
testUF<UF3>(1000000);
cout << "testUF4" << endl;
testUF<UF4>(1000000);
cout << "testUF5" << endl;
testUF<UF5>(1000000);
cout << "testUF6" << endl;
testUF<UF6>(1000000);
system("pause");
return 0;
}
测试效果