c++連結串列實現佇列,深搜加寬搜,加模版類實現迷宮問題;
阿新 • • 發佈:2019-02-19
資料結構作業二,用連結串列實現佇列,用深搜寬搜解決迷宮問題,另是模版類的用法;
模版類用法舉例:
栗子一:
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;
}