数据结构作业二,用链表实现队列,用深搜宽搜解决迷宫问题,另是模版类的用法;
模版类用法举例:
栗子一:
template<class bbb>
class Node{
public:
bbb data;
Node *next;
Node(){next=NULL;}
};//只在前面加template关键字就可以;
栗子二:
template<class ttt>
class Linkquuue{
public:
Linkquuue();
~Linkquuue();
void Enqueue(ttt x);
int Dequeue();
ttt Getqueue();
int Empty(){if(Front==Rear)return 1;return 0 ;}
private:
Node<ttt>*Front,*Rear;
};
template<class ttt>
Linkquuue<ttt>::Linkquuue(){
Node<ttt> *s=new Node<ttt>;
s->next=NULL;
Front=Rear=s;
}
template<class ttt>
Linkquuue<ttt>::~Linkquuue(){
while(Rear!=Front){
Node<ttt> *p;
ttt x;
p=Front->next;
Front->next=p->next;
if(p->next==NULL)Rear=Front;
delete p;
}
}
template<class ttt>
void Linkquuue<ttt>::Enqueue(ttt x){
Node<ttt> *s=new Node<ttt>;
s->data=x;
s->next=NULL;
Rear->next=s;
Rear=s;
}
template<class ttt>
int Linkquuue<ttt>::Dequeue()
{
if(Rear==Front)return 0;
Node<ttt> *p;
ttt x;
p=Front->next;
x=p->data;
Front->next=p->next;
if(p->next==NULL)Rear=Front ;
delete p;
return 1;
}
template<class ttt>
ttt Linkquuue<ttt>::Getqueue(){
return Front->next->data;
}///类里只在类外加一个模版类声明即可,类外,在哪里加就在哪里加参数表;
///所以模版类声明的有效范围只在当前区域内有效;
链表实现队列:
代码:
template<class bbb>
class Node{
public:
bbb data;
Node *next;
Node(){next=NULL;}
};
template<class ttt>
class Linkquuue{
public:
Linkquuue();
~Linkquuue();
void Enqueue(ttt x);
int Dequeue();
ttt Getqueue();
int Empty(){if(Front==Rear)return 1;return 0 ;}
private:
Node<ttt>*Front,*Rear;
};
template<class ttt>
Linkquuue<ttt>::Linkquuue(){
Node<ttt> *s=new Node<ttt>;
s->next=NULL;
Front=Rear=s;
}
template<class ttt>
Linkquuue<ttt>::~Linkquuue(){
while(Rear!=Front){
Node<ttt> *p;
ttt x;
p=Front->next;
Front->next=p->next;
if(p->next==NULL)Rear=Front;
delete p;
}
}
template<class ttt>
void Linkquuue<ttt>::Enqueue(ttt x){
Node<ttt> *s=new Node<ttt>;
s->data=x;
s->next=NULL;
Rear->next=s;
Rear=s;
}
template<class ttt>
int Linkquuue<ttt>::Dequeue()
{
if(Rear==Front)return 0;
Node<ttt> *p;
ttt x;
p=Front->next;
x=p->data;
Front->next=p->next;
if(p->next==NULL)Rear=Front ;
delete p;
return 1;
}
template<class ttt>
ttt Linkquuue<ttt>::Getqueue(){
return Front->next->data;
}
深搜加宽搜实现迷宫问题(举例说明),
///实验问题及具体举例说明;
/*
迷宫问题。以一维数组Maze[m+2][n+2]数组描述一个迷宫,元素。值为0表示通道,值为1表示墙壁,以 Maze[1][1]表示迷宫的入口,maze[m][n]表示迷宫的出口,外层数据全为1表示外围墙壁,Maze数组内层数据表达一个迷宫(数据来源于输入或随机赋值),打印一条如何从Maze[1][1]到达出口Maze[m][n]的路径,若无解,则打印“无解”信息
迷宫问题举例:
设:
1):图大小给出,n行m列1<=n,m<=20,图中1为墙壁,0为可走的路;
2):从当前点可移动到上下左右四点(如果没有障碍及可走的情况下)
3):求(1,1)到(m,n)所走的最短路,如有多条输出任意一条,没有输出”no a way!”;
4):描述:多组数据读到文档尾,输入n,m,表示图的大小为n行m列,接下来n行每行有m个数;
输出:输出最短路径,每行一个坐标表示走过的点,多组解输出任意一组,无解情况输出”no a way!”,然后换行;
样例:
样例输入
2 5
0 1 0 0 0
0 0 0 1 0
4 6
0 1 1 0 0 0
0 0 1 0 1 1
0 1 1 1 1 0
0 1 1 1 0 0
2 2
0 1
1 0
样例输出1
1 1
2 1
2 2
2 3
1 3
1 4
1 5
2 5
no a way!
no a way!
*/
具体代码:
简版:
#include <bits/stdc++.h>
using namespace std;
template<class bbb>
class Node{
public:
bbb data;
Node *next;
Node(){next=NULL;}
};
template<class ttt>
class Linkquuue{
public:
Linkquuue();
~Linkquuue();
void Enqueue(ttt x);
int Dequeue();
ttt Getqueue();
int Empty(){if(Front==Rear)return 1;return 0 ;}
private:
Node<ttt>*Front,*Rear;
};
template<class ttt>
Linkquuue<ttt>::Linkquuue(){
Node<ttt> *s=new Node<ttt>;
s->next=NULL;
Front=Rear=s;
}
template<class ttt>
Linkquuue<ttt>::~Linkquuue(){
while(Rear!=Front){
Node<ttt> *p;
ttt x;
p=Front->next;
Front->next=p->next;
if(p->next==NULL)Rear=Front;
delete p;
}
}
template<class ttt>
void Linkquuue<ttt>::Enqueue(ttt x){
Node<ttt> *s=new Node<ttt>;
s->data=x;
s->next=NULL;
Rear->next=s;
Rear=s;
}
template<class ttt>
int Linkquuue<ttt>::Dequeue()
{
if(Rear==Front)return 0;
Node<ttt> *p;
ttt x;
p=Front->next;
x=p->data;
Front->next=p->next;
if(p->next==NULL)Rear=Front ;
delete p;
return 1;
}
template<class ttt>
ttt Linkquuue<ttt>::Getqueue(){
return Front->next->data;
}
struct zuobiao
{
int x,y;
zuobiao(int a,int b){x=a;y=b;}
zuobiao(){};
};
const int maxn=22;
int tu[maxn][maxn];
int lu[maxn][maxn];
int n,m;
int showlu(int x,int y)
{
if(x==0&&y==0){
cout<<x+1<<" "<<y+1<<endl;
return 0;
}
for(int i=-1;i<2;i++){
for(int j=-1;j<2;j++){
if((i==0||j==0)&&i^j!=0)
{
int si=x+i,wai=y+j;
if(si>=0&&si<n&&wai>=0&&j<m){
if(lu[si][wai]==(lu[x][y]-1)){
showlu(si,wai);
cout<<x+1<<" "<<y+1<<endl;
return 0;
}
}
}
}
}
return 0;
}
int main()
{
while(cin>>n>>m){
for(int i=0;i<n;i++){
for(int j=0;j<m;j++){
cin>>tu[i][j];
}
}
for(int i=0;i<n;i++){
for(int j=0;j<m;j++){
if(tu[i][j]==1)
lu[i][j]=-1;
if(tu[i][j]==0)
lu[i][j]=0;
}
}
lu[0][0]=1;
Linkquuue<zuobiao>qu;
qu.Enqueue(zuobiao(0,0));
while(!qu.Empty()){
zuobiao now=qu.Getqueue();
qu.Dequeue();
for(int i=-1;i<2;i++){
for(int j=-1;j<2;j++){
if((i==0||j==0)&&i^j!=0){
int si=now.x+i,wai=now.y+j;
if(si>=0&&si<n&&wai>=0&&wai<m){
if(lu[si][wai]==0){lu[si][wai]=lu[now.x][now.y]+1;
qu.Enqueue(zuobiao(si,wai));
}
}
}
}
}
}
if(lu[n-1][m-1]==0||lu[n-1][m-1]==-1)
cout<<"no a way!"<<endl;
else{
showlu(n-1,m-1);
cout<<endl;
}
}
return 0;
}
加注释版:
#include <bits/stdc++.h>
using namespace std;
template<class bbb>
class Node{ ///链表里的节点;
public:
bbb data;
Node *next;
Node(){next=NULL;} ///可直接生成节点;
};
template<class ttt>
class Linkquuue{ ///队列类,用链表结构存储;
public:
///构造函数,生成了一个标志节点,没注意这个,debug到天亮;
Linkquuue();
///析构函数,因为是通过new申请的内存,必须要自己动手释放,
///否则析构函数一般不用写东西;
~Linkquuue();
///入队;
void Enqueue(ttt x);
///出队,先入者先出;
int Dequeue();
///得到队头的元素,注意对头有标志节点;
ttt Getqueue();
///判断是否为空;为空输出1,不为空输出0;
int Empty(){if(Front==Rear)return 1;return 0 ;}
private:
///队列元素,只记录队首和队尾即可;
Node<ttt>*Front,*Rear;
};
template<class ttt>
///构造函数,申请一个新节点,其实不用,但是改动麻烦,注意即可;
Linkquuue<ttt>::Linkquuue(){
Node<ttt> *s=new Node<ttt>;
s->next=NULL;
Front=Rear=s;
}
template<class ttt>
///析构函数,析构掉申请的内存,主要构造时候申请的空节点;
Linkquuue<ttt>::~Linkquuue(){
while(Rear!=Front){
Node<ttt> *p;
ttt x;
p=Front->next;
Front->next=p->next;
if(p->next==NULL)Rear=Front;
delete p;
}
delete Front;
}
template<class ttt>
///入队操作,在队首添加即可,注意空节点;
void Linkquuue<ttt>::Enqueue(ttt x){
Node<ttt> *s=new Node<ttt>;
s->data=x;
s->next=NULL;
Rear->next=s;
Rear=s;
}
///出队操作,去掉队尾申请的内存即可;
template<class ttt>
int Linkquuue<ttt>::Dequeue()
{
if(Rear==Front)return 0;
Node<ttt> *p;
ttt x;
p=Front->next;
x=p->data;
Front->next=p->next;
if(p->next==NULL)Rear=Front ;
delete p;
return 1;
}
///根据先入先出的原则,拿出队首元素,
///主要第一个为空节点,返回第二个节点
template<class ttt>
ttt Linkquuue<ttt>::Getqueue(){
return Front->next->data;
}
///上面的操作均在模版类中实现,这里具体到类;
///为下面的程序开个坐标类,记录处理到的坐标;
struct zuobiao
{
int x,y;
///支持类型强转;
zuobiao(int a,int b){x=a;y=b;}
///支持直接建立坐标类,不必赋值;
zuobiao(){};
};
///本程序的参数,及地图的最大是多少,后期可调;
const int maxn=22;
///存图,即原始的数据;
int tu[maxn][maxn];
///存路,之后的操作在这里进行,可保护原始数据;
int lu[maxn][maxn];
///参数允许范围内具体地图的大小,这里开全局是为深搜的调用;
int n,m;
///输出路径,宽搜跑地图得到路径,深搜可反向进行搜索,输出路径;
int showlu(int x,int y)
{
///深搜结束条件,即搜索到起始位置;
if(x==0&&y==0){
cout<<x+1<<" "<<y+1<<endl;
return 0;
}
///从高位向低位进行搜索,因为高位是低位宽搜来的,所以一定有路,
///关系如同,根可以找到n多叶子,叶子只能找到一个根;
for(int i=-1;i<2;i++){
for(int j=-1;j<2;j++){
if((i==0||j==0)&&i^j!=0)
{
int si=x+i,wai=y+j;
if(si>=0&&si<n&&wai>=0&&j<m){
if(lu[si][wai]==(lu[x][y]-1)){
///找到下个点时进行递归操作;
showlu(si,wai);
///因为要正着输出路径,所以,
///放在递归的后面,可以从低位输出;
cout<<x+1<<" "<<y+1<<endl;
///这里符合条件就返回,保证了只输出一条路径;
return 0;
}
}
}
}
}
return 0;
}
int main()
{
///保证有数据就可以读入操作;
while(cin>>n>>m){
///读入数据结构;其实可以写成函数,不过意义不大;
for(int i=0;i<n;i++){
for(int j=0;j<m;j++){
cin>>tu[i][j];
}
}
///路径的初始化操作;
for(int i=0;i<n;i++){
for(int j=0;j<m;j++){
if(tu[i][j]==1)
lu[i][j]=-1;
if(tu[i][j]==0)
lu[i][j]=0;
}
}
///因为下面的入队条件是等零,所以这里初始化下;
lu[0][0]=1;
///首先声明队列,入队起点;
Linkquuue<zuobiao>qu;
qu.Enqueue(zuobiao(0,0));
while(!qu.Empty()){
///得到队首元素;
zuobiao now=qu.Getqueue();
///队首处理完成,出队;
qu.Dequeue();
for(int i=-1;i<2;i++){
for(int j=-1;j<2;j++){
if((i==0||j==0)&&i^j!=0){
int si=now.x+i,wai=now.y+j;
if(si>=0&&si<n&&wai>=0&&wai<m){
if(lu[si][wai]==0){lu[si][wai]=lu[now.x][now.y]+1;
qu.Enqueue(zuobiao(si,wai));
///搜索到下个符合条件的位置入队;
}
}
}
}
}
}
///lu数组没有改变,说明到达不到,输出no a way!;
if(lu[n-1][m-1]==0||lu[n-1][m-1]==-1)
cout<<"no a way!"<<endl<<endl;
///有路及输出路径;
else{
showlu(n-1,m-1);
cout<<endl;
}
}
return 0;
}