在《Data Structure and Algorithm Analysis in C++》一书中看到一个生成迷宫的简单方法(书中第八章):将迷宫看成是有一个个单元组成的矩形,这些单元与相连的单元被墙壁分离开来。此时,不断的随即选择一面墙壁,如果被该墙分割的单元彼此不连通,那么就把这么墙拆掉,否则什么也不做。重复这个过程直到开始单元和终止单元彼此连通,那么就得到一个迷宫。实际上不断拆掉墙壁知道每一个单元都可以从其它单元到达会更好(使得迷宫会产生更多误导路径)。
上述算法是不相交类集(求并/查找数据结构)的一个典型例子,这种数据结构是解决等价问题的一种有效数据结构。涉及到的理论知识:等价关系。
若对于每一对元素(a,b), a,b属于S, a R b为true或false,则称在集合S上定义关系R。如果a R b为true,则a与b有关系。
等价关系是满足三个性质的关系R:
自反性: 对于所有a属于S,有a R a。
对称性: a R b当且仅当 b R a。
传递性: 若a R b且b R c,则a R c。
基本数据结构可以用一个数组表示,整个数组实际上是树的集合(即森林)。假设迷宫游戏用M*N的矩形来描述,那么就需要以大小为M*N的数组maze[M*N]来表示该迷宫中的所有单元。起初每个单元都不连通,每个单元是一棵单独的树的树根,高度为1,记为maze[i] = -1(表示高度为1的root)。那么随即选中一面墙,比如maze[0]和maze[1]之间的墙,判断它们的树根是否相同,如果树根不同,那么它们没有连通,那么拆掉墙,将这两棵树合并起来,将高度小的那棵树并到高度大的树的树上(限制树的高度),如果它们的树根分别为maze[i],maze[j], 将j树并到i树上,则maze[j] = i, 即maze[j]不再是树根,而是以i为根的树的一部分。
例如是2*3, 最开始有6个集合: {0},{1},{2},{3},{4},{5},对应的maze[0-6] = -1; 如果随即选中0和3之间的墙壁,它们没有连通,于是将它们并起来,现在是{0,3},{1},{2},{4},{5}; 如果入口为左上角,出口为右下角&#