1. 程式人生 > >c++連結串列實現佇列,深搜加寬搜,加模版類實現迷宮問題;

c++連結串列實現佇列,深搜加寬搜,加模版類實現迷宮問題;

資料結構作業二,用連結串列實現佇列,用深搜寬搜解決迷宮問題,另是模版類的用法;
模版類用法舉例:
栗子一:

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;
}