数据结构与算法分析-C++描述 第8章 迷宫生成(不相交类的一个应用)

本文介绍了一种利用并查集数据结构生成迷宫的算法。通过随机选择并拆除墙壁,确保迷宫的连通性,最终生成一个复杂的迷宫。代码示例展示了如何实现并查集类及迷宫生成的过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

不相交类中,定义了求并/查找函数极其灵巧方法,本次给出不相交类的一个应用:应用求并/查找数据结构的一个例子是迷宫的生成,如下图为一个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 !

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值