// 第十一章--迷宫问题(二).cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include
using namespace std;
enum
StatusCode{SUCCESS,FAIL,UNDER_FLOW,OVER_FLOW,RANGE_ERROR,DUPLICATE_ERROR,NOT_PRESENT,ENTRY_INSERTED,ENTRY_FOUND,VISITED,UNVISITED};//状态码
// 结点类模板
template
struct Node
{
// 数据成员:
ElemType
data; //
数据域
Node
*next; // 指针域
// 构造函数模板:
Node(); //
无参数的构造函数模板
Node(ElemType item,
Node *link =
NULL); // 已知数据元素值和指针建立结构
};
// 结点类模板的实现部分
template
Node::Node()
// 操作结果:构造指针域为空的结点
{
next = NULL;
}
template
Node::Node(ElemType item,
Node *link)
// 操作结果:构造一个数据域为item和指针域为link的结点
{
data = item;
next = link;
}
// 链队列类模板
template
class LinkQueue
{
protected:
// 链队列实现的数据成员:
Node
*front,
*rear; //
队头队尾指指
// 辅助函数模板:
void
Init(); //
初始化队列
public:
// 抽象数据类型方法声明及重载编译系统默认方法声明:
LinkQueue(); //
无参数的构造函数模板
virtual
~LinkQueue(); //
析构函数模板
int Length()
const; //
求队列长度 bool Empty()
const; //
判断队列是否为空
void
Clear(); //
将队列清空
void Traverse(void (*visit)(const ElemType
&)) const ; // 遍历队列
StatusCode OutQueue(ElemType
&e); //
出队操作
StatusCode GetHead(ElemType &e)
const; //
取队头操作
StatusCode InQueue(const ElemType
&e); //
入队操作
LinkQueue(const
LinkQueue
©); //
复制构造函数模板
LinkQueue
&operator =(const
LinkQueue
©);// 重载赋值运算符
};
// 链队列类模板的实现部分
template
void
LinkQueue::Init()
// 操作结果:初始化队列
{
rear = front = new
Node; //
生成头结点
}
template
LinkQueue::LinkQueue()
// 操作结果:构造一个空队列
{
Init();
}
template
LinkQueue::~LinkQueue()
// 操作结果:销毁队列
{
Clear(); }
template
int LinkQueue::Length()
const
//
操作结果:返回队列长度 {
int count =
0; // 计数器
for (Node
*tmpPtr = front->next; tmpPtr != NULL; tmpPtr =
tmpPtr->next)
{ // 用tmpPtr依次指向每个元素
count++; //
对栈每个元素进行计数
}
return count;
}
template
bool LinkQueue::Empty()
const
// 操作结果:如队列为空,则返回true,否则返回false
{
return rear == front;
}
template
void
LinkQueue::Clear()
// 操作结果:清空队列
{
ElemType tmpElem; // 临时元素值
while (Length() > 0)
{ // 队列非空,则出列
OutQueue(tmpElem);
}
}
template
void
LinkQueue::Traverse(void
(*visit)(const ElemType &)) const
// 操作结果:依次对队列的每个元素调用函数(*visit)
{
for (Node
*tmpPtr = front->next; tmpPtr != NULL;
tmpPtr =
tmpPtr->next)
{ // 对队列每个元素调用函数(*visit)
(*visit)(tmpPtr->data);
}
}
template
StatusCode
LinkQueue::OutQueue(ElemType
&e)
// 操作结果:如果队列非空,那么删除队头元素,并用e返回其值,返回SUCCESS,
// 否则返回UNDER_FLOW,
{
if (!Empty())
{ // 队列非空
Node
*tmpPtr = front->next; //
指向队列头素
e =
tmpPtr->data; //
用e返回队头元素
front->next =
tmpPtr->next; //
front指向下一元素
if (rear == tmpPtr)
{ //
表示出队前队列中只有一个元素,出队后为空队列
rear =
front;
}
delete
tmpPtr; //
释放出队的结点
return SUCCESS;
}
else
{ // 队列为空
return UNDER_FLOW;
}
}
template
StatusCode
LinkQueue::GetHead(ElemType
&e) const
// 操作结果:如果队列非空,那么用e返回队头元素,返回SUCCESS,
// 否则返回UNDER_FLOW,
{
if (!Empty())
{ // 队列非空
Node
*tmpPtr = front->next; //
指向队列头素
e =
tmpPtr->data; //
用e返回队头元素
return SUCCESS;
}
else
{ // 队列为空
return UNDER_FLOW;
}
}
template
StatusCode
LinkQueue::InQueue(const
ElemType &e)
// 操作结果:插入元素e为新的队尾,返回SUCCESS
{
Node
*tmpPtr = new
Node(e); //
生成新结点
rear->next =
tmpPtr; //
新结点追加在队尾
rear =
tmpPtr; //
rear指向新队尾
return SUCCESS;
}
template
LinkQueue::LinkQueue(const
LinkQueue
©)
// 操作结果:由队列copy构造新队列——复制构造函数模板
{
Init();
for (Node
*tmpPtr = copy.front->next; tmpPtr != NULL;
tmpPtr =
tmpPtr->next)
{ //
对copy队列每个元素对当前队列作入队列操作
InQueue(tmpPtr->data);
}
}
template
LinkQueue
&LinkQueue::operator
=(const LinkQueue
©)
// 操作结果:将队列copy赋值给当前队列——重载赋值运算符
{
if (© != this)
{
Clear();
for
(Node *tmpPtr =
copy.front->next; tmpPtr != NULL;
tmpPtr =
tmpPtr->next)
{ //
对copy队列每个元素对当前队列作入队列操作
InQueue(tmpPtr->data);
}
}
return *this;
}
// 链栈类模板
template
class LinkStack
{
protected:
// 链栈实现的数据成员:
Node
*top; //
栈顶指针
// 辅助函数模板:
void
Init(); //
初始化栈
public:
// 抽象数据类型方法声明及重载编译系统默认方法声明:
LinkStack(); //
无参数的构造函数模板
virtual
~LinkStack(); //
析构函数模板
int Length()
const; //
求栈长度 bool Empty()
const; //
判断栈是否为空
void
Clear(); //
将栈清空
void Traverse(void (*visit)(const ElemType
&)) const ; //
遍历栈
StatusCode Push(const ElemType
&e); //
入栈
StatusCode Top(ElemType &e)
const; //
返回栈顶元素
StatusCode Pop(ElemType
&e); //
出栈
LinkStack(const
LinkStack
©); //
复制构造函数模板
LinkStack
&operator =(const
LinkStack
©); // 重载赋值运算符
};
// 链栈类模板的实现部分
template
void
LinkStack::Init()
// 操作结果:初始化栈
{
top =
NULL; //
构造栈顶指针
}
template
LinkStack::LinkStack()
// 操作结果:构造一个空栈表
{
Init();
}
template
LinkStack::~LinkStack()
// 操作结果:销毁栈
{
Clear();
}
template
int LinkStack::Length()
const
// 操作结果:返回栈元素个数
{
int count =
0; // 计数器
for (Node
*tmpPtr = top; tmpPtr != NULL; tmpPtr =
tmpPtr->next)
{ // 用tmpPtr依次指向每个元素
count++; //
对栈每个元素进行计数
}
return count;
}
template
bool LinkStack::Empty()
const
// 操作结果:如栈为空,则返回true,否则返回false
{
return top == NULL;
}
template
void
LinkStack::Clear()
// 操作结果:清空栈
{
ElemType tmpElem; // 临时元素值
while (!Empty())
Pop(tmpElem);
}
template
void
LinkStack::Traverse(void
(*visit)(const ElemType &)) const
// 操作结果:从栈底到栈顶依次对栈的每个元素调用函数(*visit)
{
Node
*tmpPtr; LinkStack
tmpS; // 临时栈,tmpS中元素顺序与当前栈元素顺序相反
for (tmpPtr = top; tmpPtr != NULL; tmpPtr =
tmpPtr->next)
{ // 用tmpPtr依次指向当前栈的每个元素
tmpS.Push(tmpPtr->data); //
对当前栈的每个元素入栈到tmpS中
}
for (tmpPtr = tmpS.top; tmpPtr != NULL; tmpPtr =
tmpPtr->next)
{ //
用tmpPtr从栈顶到栈底依次指向栈tmpS的每个元素
(*visit)(tmpPtr->data); //
对栈tmpS的每个元素调用函数(*visit)
}
}
template
StatusCode
LinkStack::Push(const
ElemType &e)
// 操作结果:将元素e追加到栈顶,如成功则返加SUCCESS,否则如动态内存已耗尽
// 将返回OVER_FLOW
{
Node
*new_top = new Node(e,
top);
if (new_top == NULL)
{ // 动态内存耗尽
return OVER_FLOW;
}
else
{ // 操作成功
top = new_top;
return SUCCESS;
}
}
template
StatusCode
LinkStack::Top(ElemType
&e) const
// 操作结果:如栈非空,用e返回栈顶元素,返回SUCCESS,否则返回UNDER_FLOW
{
if(Empty())
{ // 栈空
return UNDER_FLOW;
}
else
{ // 栈非空,操作成功
e =
top->data; //
用e返回栈顶元素
return SUCCESS;
}
}
template
StatusCode
LinkStack::Pop(ElemType
&e)
// 操作结果:如栈非空,删除栈顶元素,并用e返回栈顶元素,返回SUCCESS,否则
// 返回UNDER_FLOW
{
if (Empty())
{ // 栈空
return UNDER_FLOW;
}
else
{ // 操作成功
Node
*old_top = top; // 旧栈顶
e =
old_top->data; //
用e返回栈顶元素
top =
old_top->next; //
top指向新栈顶
delete
old_top; //
删除旧栈顶
return SUCCESS;
}
}
template
LinkStack::LinkStack(const
LinkStack
©)
// 操作结果:由栈copy构造新栈——复制构造函数模板
{
if (copy.Empty())
{ // copy为空
Init(); //
构造一空栈
}
else
{ // copy非空,复制栈
top = new
Node(copy.top->data); //
生成当前栈项
Node
*buttomPtr =
top; //
当前栈底指针
for
(Node *tmpPtr =
copy.top->next; tmpPtr != NULL; tmpPtr =
tmpPtr->next)
{ //
用tmpPtr依次指向其余元素
buttomPtr->next
= new
Node(tmpPtr->data);
// 向栈底追加元素 buttomPtr =
buttomPtr->next; //
buttomPtr指向新栈底
}
}
}
template
LinkStack
&LinkStack::operator
= (const LinkStack
©)
// 操作结果:将栈copy赋值给当前栈——重载赋值运算符
{
if (© != this)
{
if (copy.Empty())
{ //
copy为空
Init(); //
构造一空栈
}
else
{ //
copy非空,复制栈
Clear(); //
清空当前栈
top = new
Node(copy.top->data); //
生成当前栈项
Node
*buttomPtr =
top; //
当前栈底指针
for
(Node *tmpPtr =
copy.top->next; tmpPtr != NULL; tmpPtr =
tmpPtr->next)
{ //
用tmpPtr依次指向其余元素
buttomPtr->next
= new
Node(tmpPtr->data);
// 向栈底追加元素 buttomPtr
=
buttomPtr->next; //
buttomPtr指向新栈底
}
}
}
return *this;
}
// 矩阵类模板
template
class Matrix
{
protected:
// 矩阵的数据成员:
ElemType
*elems; // 存储知阵元素
int rows,
cols; //
矩阵行数和列数
public:
// 抽象数据类型方法声明及重载编译系统默认方法声明:
Matrix(int rs, int cs); //
构造一个rs行cs列的矩阵
~Matrix(); //
析构函数模板
int GetRows() const; //
返回矩阵行数
int GetCols() const; //
返回矩阵列数
ElemType &operator()(int i, int
j); //
重载函数运算符
Matrix(const
Matrix
©); //
复制构造函数模板
Matrix
&operator =(const
Matrix
©); // 重载赋值运算符
};
// 三对角类模板的实现部分
template
Matrix::Matrix(int rs, int
cs)
// 操作结果:构造一个rs行cs列的矩阵
{
if (rs < 1
&& cs <
1) cout<
rows =
rs; //
rs为行数
cols =
cs; //
cs为列数
elems = new ElemType[rows *
cols]; // 分配存储空间
}
template
Matrix::~Matrix()
// 操作结果:释放矩阵所占用空间
{
if (elems != NULL) delete []elems;
}
template
int Matrix::GetRows()
const
// 操作结果:返回矩阵行数
{
return rows;
}
template
int Matrix::GetCols()
const
// 操作结果:返回矩阵列数
{
return cols;
}
template
ElemType
&Matrix::operator()(int
i, int j)
// 操作结果:重载函数运算符
{
if (i < 1 || i >
rows || j < 1 || j >
cols) cout<
return elems[(i - 1) * cols + j -
1]; // 返回元素
}
template
Matrix::Matrix(const
Matrix
©)
// 操作结果:由矩阵copy构造新矩阵——复制构造函数模板
{
rows =
copy.rows; // 复制行数
cols =
copy.cols; // 复制列数
elems = new ElemType[rows *
cols]; // 为数据元素分配存储空间
for (int i = 0; i < rows * cols;
i++)
{ // 复制数据元素值
elems[i] = copy.elems[i];
}
}
template
Matrix
&Matrix::operator
=(const Matrix
©)
// 操作结果:将矩阵copy赋值给当前矩阵——重载赋值运算符
{
if (© != this)
{
if (elems != NULL) delete
[]elems; // 释放数据元素空间
rows =
copy.rows; // 复制行数
cols =
copy.cols; // 复制列数
elems = new ElemType[rows *
cols]; // 为数据元素分配存储空间
for (int i = 0; i
< rows * cols; i++)
{ //
复制数据元素值
elems[i] =
copy.elems[i];
}
}
return *this;
}
// 迷宫单元格状态,VIA:已经过,BLOCK:阻塞(阴影),EMPTY:空
enum MazeCellStatus { EMPTY, BLOCK,VIA} ;
struct
CellType //
迷宫单元格
{
int x,
y; //
单元格的坐标
};
void OutSolution(Matrix
&mazePath, const CellType &entry,
const CellType &out); // 输出迷宫问题的解
void
MazeSolution(Matrix
&maze, int w, int h, const CellType
&entry,
const CellType &out)
// 操作结果: 求解迷宫问题
{
Matrix
mazePath(h,
w); //
迷宫路线
LinkQueue
cellQueue; //
单元格队列
CellType NullCell = {0,
0}; //
空单元格
mazePath(entry.y, entry.x) =
NullCell; //
将入口存入路径,作为路径的起始点,前驱为空
cellQueue.InQueue(entry); //
入口进队
while (!cellQueue.Empty())
{ // InQueue非空,可继续求迷宫出口
CellType
curCell; //
当前单元格
cellQueue.OutQueue(curCell); //
取出当前单元格
if (curCell.x == out.x
&& curCell.y ==
out.y) { //
已达到出口,输出解
OutSolution(mazePath,
entry, out);
return;
}
else
{
int xShift[4]
= {0, 0 , -1,
1}; //
相邻位置相对于当前位置的x相对坐标
int yShift[4]
= {-1, 1, 0,
0}; //
相邻位置相对于当前位置的y相对坐标
CellType
adjCell; //
当前位置的相邻位置
for (int i =
0; i < 4; i++)
{
adjCell.x
= curCell.x + xShift[i]; //
当前位置的相邻位置的x坐标
adjCell.y
= curCell.y + yShift[i]; //
当前位置的相邻位置的y坐标
if
(adjCell.x >= 1 &&
adjCell.x <= w &&
adjCell.y >= 1 &&
adjCell.y <= h
&&
(maze(adjCell.y, adjCell.x) == EMPTY))
{ //
相邻位置在迷宫内,并且为空白
mazePath(adjCell.y,
adjCell.x) = curCell; //
在路径上adjCell是curCell的下一个位置
maze(adjCell.y,
adjCell.x) = VIA; // 经过相邻位置
cellQueue.InQueue(adjCell); //
adjCell进队
}
}
}
}
}
void OutSolution(Matrix
&mazePath, const CellType &entry,
const CellType &out)
// 操作结果: 输出迷宫问题的解
{
LinkStack
cellStack; //
存入从出口到入口的路径上的单元格
CellType curCell =
out; //
路径上的当前单元格
cellStack.Push(curCell); //
入栈
CellType preCell = mazePath(curCell.y,
curCell.x); // 路径上curCell的上一个单元格
while (preCell.x != entry.x || preCell.y !=
entry.y)
{ // 当前单元格在路径上的上一个单元格不是入口
curCell =
preCell; //
curCell在路径上向后退一个单元格
preCell = mazePath(curCell.y,
curCell.x); // 路径上curCell的上一个单元格
cellStack.Push(curCell); //
入栈
}
cellStack.Push(entry); //
入栈
cout <<
"路径:"<
while (!cellStack.Empty())
{ // 从入口到出口输出路径
cellStack.Pop(curCell); // 出栈
cout
<< "("
<< curCell.x
<< ","
<< curCell.y
<< ")
"<
}
cout << endl;
}
int _tmain(int argc, _TCHAR* argv[])
{
const int h = 6, w =
10; //
迷宫高与宽
MazeCellStatus arrayMaze[h][w]
= // 迷宫二维数组
{ // 迷宫
{EMPTY, BLOCK, BLOCK, BLOCK,
BLOCK, BLOCK, BLOCK, BLOCK, BLOCK, BLOCK},
{EMPTY, BLOCK, EMPTY, EMPTY,
BLOCK, EMPTY, EMPTY, EMPTY, BLOCK, BLOCK},
{EMPTY, EMPTY, EMPTY, BLOCK,
BLOCK, EMPTY, BLOCK, EMPTY, EMPTY, BLOCK},
{EMPTY, BLOCK, BLOCK, EMPTY,
EMPTY, EMPTY, BLOCK, BLOCK, EMPTY, BLOCK},
{EMPTY, EMPTY, EMPTY, EMPTY,
EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, BLOCK},
{BLOCK, BLOCK, BLOCK, BLOCK,
BLOCK, BLOCK, BLOCK, BLOCK, EMPTY, EMPTY} };
Matrix
maze(h, w); // 迷宫
CellType entry = {1,
1}; //
入口位置
CellType out = {10,
6}; //
出口位置
cout<
for (int r = 1; r <= h; r++)
{ // 行
for (int c = 1; c
<= w; c++)
{ // 列
maze(r, c) =
arrayMaze[r - 1][c - 1]; // 为迷宫赋初值
cout<
";
}
cout<
}
MazeSolution(maze, w, h, entry,
out); // 求解迷宫
system("PAUSE"); //
调用库函数system()
return 0;
}