在不相交类中,定义了求并/查找函数极其灵巧方法,本次给出不相交类的一个应用:应用求并/查找数据结构的一个例子是迷宫的生成,如下图为一个10*10的迷宫。
生成迷宫的一个简单的算法是从各处的墙壁开始(除了入口和出口外) 。此时,不断地随机选择一面墙,如果被该墙分割的单元彼此不连通,那么就把这面墙拆掉,重复这个过程直到开始单元和终止单元连通,就得到一个迷宫。实际上,不断地拆掉墙壁直到每个单元都可以从其他单元达到更好(以下为部分随机生成的“wall”)。
实例:
1、disjointSet.h
//disjointSet.h
#ifndef DISJOINTSET_H_
#define DISJOINTSET_H_
#include<iostream>
#include<vector>
using std::vector;
class DisjointSet{
public:
//DisjointSet constructor
explicit DisjointSet(int n = 10):s(n){
for(int i = 0; i < s.size(); i++){
s[i] = -1;
}
};
//find root without path compression
int find(int root) const{
if(s[root] < 0){
return root;
}else{
return find(s[root]);
}
};
//unionSet by height
void unionSet(int r1, int r2){
//if root1 and root2 are in same class, do nothing
int root1 = find(r1);
int root2 = find(r2);
if(root1 == root2){
return;
}
//otherwise unionSet
if(s[root2] < s[root1]){
s[root1] = root2;
}else if(s[root2] == s[root1]){
s[root1]--;
s[root2] = root1;
}else{
s[root2] = root1;
}
};
//judge whether the root1 and root2 has same root
bool isConnected(int root1, int root2){
return find(root1) == find(root2);
};
private:
vector<int> s;
};
#endif
2、main.cpp
//main.cpp
#include<iostream>
#include<ctime>
#include<cstdlib>
#include"disjointSet.h"
using namespace std;
const int N = 10;
int wall_row[N+1][N];
int wall_column[N][N+1];
//init the maze
void init();
//print the maze
void print();
//get random number
int getRand();
//reallcate flage type and location
void mapRand(int rdm, int &type, int &row, int &column);
//reallcate the root
void mapRoot(int type, int row, int column, int &root1, int &root2);
int main(){
init();
//print();
srand(time(0));
int amount = N * 10;
DisjointSet disjointSet(amount);
int count = 0;
while(!disjointSet.isConnected(0, amount - 1)){
count++;
int type, row, column;
do{
int rdm = getRand();
mapRand(rdm, type, row, column);
}while((type == 0 && wall_column[row][column] == 0) || (type == 1 && wall_row[row][column] == 0));
int root1, root2;
mapRoot(type, row, column, root1, root2);
print();
if( !disjointSet.isConnected(root1, root2)){
if(type == 0){
wall_column[row][column] = 0;
}else{
wall_row[row][column] = 0;
}
disjointSet.unionSet(root1, root2);
}
}
cout << "After " << count << " times random access btreak the wall, the results as follow " << endl;
print();
return 0;
}
void init(){
int i,j;
for(i= 0; i < N+1; i++){
for(j = 0; j < N; j++){
wall_row[i][j] = 1;
}
}
for(i= 0; i < N; i++){
for(j = 0; j < N+1; j++){
wall_column[i][j] = 1;
}
}
wall_row[0][0] = 0;
wall_column[0][0] = 0;
wall_row[N][N-1] = 0;
wall_column[N-1][N] = 0;
}
void print(){
int i, j;
for(i = 0; i < N+1; i++){
for(j = 0; j < N+1; j++){
if(i > 0){
if(wall_column[i-1][j]){
cout << "|";
}else{
cout << " ";
}
}
if(j < N){
if(i > 0){
if(wall_row[i][j]){
cout << "_";
}else{
cout << " ";
}
}else{
if(wall_row[i][j]){
cout << "_";
}else{
cout << " ";
}
}
}
}
cout << endl;
}
}
int getRand(){
return rand() % (N * (N - 1) * 2);
}
void mapRand(int rdm, int &type, int &row, int &column){
type = rdm >= (N * (N -1)) ? 1 : 0;
if(type == 0){
row = rdm / (N - 1);
column = rdm % (N - 1) + 1;
}else{
rdm -= N * (N - 1);
row = rdm / N + 1;
column = rdm % N;
}
}
void mapRoot(int type, int row, int column, int &root1, int &root2){
if(type == 0){
root1 = row * N + column - 1;
root2 = row * N + column;
}else{
root1 = (row - 1) * N + column;
root2 = row * N + column;
}
}
practice makes perfect !