佇列的應用——求解迷宮問題
阿新 • • 發佈:2019-02-13
程式碼示例:
#include <iostream> using namespace std; const int MaxSize = 20; //迷宮最大行、列數 const int QueueSize = 100; //順序隊大小 struct Box //方塊結構體型別 { int i; //方塊的行號 int j; //方塊的列號 int pre; //本路徑中上一方塊在佇列中的下標 }; class Queue //非迴圈順序佇列類 { Box *data; //存放隊中方塊 int front, rear; //隊頭隊尾指標 public: Queue(); //建構函式:佇列初始化 ~Queue(); //解構函式:釋放佇列空間 bool QueueEmpty(); //判斷佇列是否為空 void edQueue(int x, int y, int pre1); //進隊一個方塊 void deQueue(int &x, int &y, int &cfront); //出隊一個方塊 void DispBox(int cfront); //從cfront出發找一條迷宮路徑 void DispQueue(); //用於輸出隊中所有元素,除錯用 }; Queue::Queue() //建構函式:佇列初始化 { data = new Box[QueueSize]; front = rear = -1; } Queue::~Queue() //解構函式:釋放佇列空間 { delete[] data; } bool Queue::QueueEmpty() //判斷佇列是否為空 { return(front == rear); } void Queue::edQueue(int x, int y, int pre1) //進隊一個方塊 { rear++; data[rear].i = x; data[rear].j = y; data[rear].pre = pre1; } void Queue::deQueue(int &x, int &y, int &cfront) //出隊一個方塊 { front++; x = data[front].i; y = data[front].j; cfront = front; } void Queue::DispBox(int cfront) //從cfront出發找一條迷宮路徑 { Box path[QueueSize]; int k, d = -1; k = cfront; while (k != -1) //找到入口為止 { d++; //將一個方塊儲存到path中 path[d].i = data[k].i; path[d].j = data[k].j; k = data[k].pre; //回退找上一個方塊 } cout << "一條迷宮路徑如下:\n"; for (k = d; k >= 0; k--) //反向輸出構成一條正向的迷宮路徑 { cout << " (" << path[k].i << "," << path[k].j << ")"; if ((d - k + 1) % 5 == 0) cout << endl; //每行輸出5個方塊 } cout << endl; } void Queue::DispQueue() //用於輸出隊中所有元素,除錯用 { int i; cout << "隊中所有元素:\n"; for (i = 0; i <= rear; i++) cout << " " << i << " (" << data[i].i << "," << data[i].j << ") " << data[i].pre << endl; } class Maze2 //用佇列求解一條迷宮路徑類 { int a[MaxSize][MaxSize]; //迷宮陣列 int m, n; //迷宮行列數 public: void Seta(int mg[][MaxSize], int m1, int n1); //設定迷宮陣列 bool mgpath(int xi, int yi, int xe, int ye); }; void Maze2::Seta(int mg[][MaxSize], int m1, int n1) //設定迷宮陣列 { int i, j; m = m1; n = n1; for (i = 0; i<m; i++) for (j = 0; j<n; j++) a[i][j] = mg[i][j]; } bool Maze2::mgpath(int xi, int yi, int xe, int ye) { int i, j, di, cfront, i1, j1; Queue qu; //建立一個空隊qu qu.edQueue(xi, yi, -1); //入口進隊,其pre置為-1 a[xi][yi] = -1; //為避免來回找相鄰方塊,將進隊的方塊置為-1 while (!qu.QueueEmpty()) //隊不空時迴圈 { qu.deQueue(i, j, cfront); //出隊一個方塊,該方塊仍在佇列中 if (i == xe && j == ye) //找到了出口,輸出路徑 { qu.DispBox(cfront); qu.DispQueue(); return true; //找到一條路徑時返回true } for (di = 0; di<4; di++) //迴圈掃描每個方位,把每個可走的方塊進隊 { switch (di) { case 0:i1 = i - 1; j1 = j; break; case 1:i1 = i; j1 = j + 1; break; case 2:i1 = i + 1; j1 = j; break; case 3:i1 = i; j1 = j - 1; break; } if (a[i1][j1] == 0) //找到一個相鄰可走方塊 { qu.edQueue(i1, j1, cfront); //將該相鄰方塊進隊,並置其pre為父方塊下標cfront a[i1][j1] = -1; //為避免來回找相鄰方塊,將進隊的方塊置為-1 } } } return false; //未找到任何路徑時返回false } void main() { int mg[][MaxSize] = { { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, { 1, 0, 0, 1, 0, 0, 0, 1, 0, 1 }, { 1, 0, 0, 1, 0, 0, 0, 1, 0, 1 }, { 1, 0, 0, 0, 0, 1, 1, 0, 0, 1 }, { 1, 0, 1, 1, 1, 0, 0, 0, 0, 1 }, { 1, 0, 0, 0, 1, 0, 0, 0, 0, 1 }, { 1, 0, 1, 0, 0, 0, 1, 0, 0, 1 }, { 1, 0, 1, 1, 1, 0, 1, 1, 0, 1 }, { 1, 1, 0, 0, 0, 0, 0, 0, 0, 1 }, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 } }; Maze2 mz; //建立一個Maze2物件mz mz.Seta(mg, 10, 10); //設定迷宮陣列 cout << "求(1,1)到(8,8)的迷宮路徑\n"; if (!mz.mgpath(1, 1, 8, 8)) //求入口為(1,1)出口為(8,8)的迷宮路徑 cout << "不存在迷宮路徑\n"; }