迷宮求解演算法(棧DFS以及佇列BFS)

2021-07-06 09:41:48 字數 4313 閱讀 6669

我們首先給出乙個迷宮,它的規格是5 * 5,在這裡我使用int的二維陣列表示迷宮,其中1表示障礙,0表示可以通行的道路,要求從(0,0)座標走到(4, 4)座標,並輸出走過的座標路徑。

int maze[5][5] = ;
①使用棧來實現dfs(深度優先搜尋)

首先,我們給出棧在迷宮中的的結構定義。

/*  

* x是迷宮中的橫座標

* y是迷宮中的縱座標

* direction表示在當前座標內要走的下乙個方向

* next指標則指向棧中的下乙個座標

*/typedef

struct lnode lnode;

/* * top指標指向棧的頂部

* 不需要base指標

*/typedef

struct stack;

接著,我們定義一些棧的基本函式操作:

/*

* intistack()

* 初始化乙個棧,傳入乙個stack結構體的位址或結構指標

* top指標指向乙個頭結點,該頭結點不包含座標但next指標指向棧的頂部座標結點

*/void intistack(stack

*result)

/*

* push()

* 將乙個新的座標結點放入棧中,所使用的方法類似於表頭插入法

* 其中direction是現在的座標點下一步要走的方向

*/void push(stack

*result, int x, int y, int direction)

/*

* pop()

* 該函式用於走到迷宮的死路時向後退以及遍歷輸出結點

* 彈出top指標中next指標所指向的結點,也就是棧的頂部節點

* 類似於從表頭刪除乙個節點,並返回該節點

*/ lnode *pop(stack

*result)

temp->next =

null;

return temp;

}

我們再給出main函式的定義

int main(void)

}stack result;

intistack(&result);

/** 當處於乙個迷宮結點的時候,我們應該分別檢測四個方向是否有路走

* 暫定direction = 1, 2, 3, 4分別表示東,南,西,北

* flagdirection 則表示已經找到乙個可行的方向,它是乙個哨兵

* row, col表示當前結點的座標

* 首先將(0, 0)結點入棧,direction預設從1開始,它還將經過一次順時針遍 歷,所以它的東方向即使是障礙也沒關係

* 因為已經遍歷過(0, 0)這個點我們不會再走這個點所以把它堵上

* current指標指向棧的頂部節點

*/int flagdirect = 1;

int row = 0;

int col = 0;

int direction = 1;

push(&result, row, col, direction);

maze[row][col] = 1;

lnode *current;

/** 設定了乙個無限迴圈,跳出迴圈的條件是到達點(4, 4)

* 如何順時針的遍歷四個方向?通過使用switch判斷可行的方向,當方向不可行的 時候direction加1測試下乙個方向是否可行

* 但是當所有方向都不可行時證明該座標是迷宮中的一條死路需要退回去

* 這時通過pop操作出棧退回到有路可走的座標點

* 之前把走過的座標點堵上就是為了不再走重複的路避免在死路裡迴圈,也方便出棧

*/while(1)

flagdirect = 1;

current = result.top->next;

row = current->x;

col = current->y;

while(flagdirect)

else

break;

case

2:if(row + 1

< max && maze[row + 1][col] == 0)

else

break;

case

3:if(col - 1 >= 0 && maze[row][col - 1] == 0)

else

break;

case

4:if(row - 1 >= 0 && maze[row - 1][col] == 0)

else

break;

default:pop(&result);

flagdirect = 0;

break;}}

}show(&result);

return

0;}

最後當我們輸出棧的路徑的時候,我們是從終點倒回到起點出棧輸出的,這時,我們可以使用乙個遞迴輸出起點到終點

void show(stack

*result)

}

②使用佇列來實現bfs(廣度優先搜尋)

佇列在迷宮中的資料結構定義

/*

* 該隊列為乙個雙重鍊錶, 通過prev指標向前索引,但該索引關係不符合順序關係, next指標符合順序關係

*/typedef

struct qnode qnode;

typedef

struct queue;

接著給出佇列基本函式操作定義:

* intiqueue()

* 初始化佇列,建立front指標的頭結點

* rear指標一開始的時候也指向頭結點

*/ void intiqueue(queue *result)

/*

* push()

* 將當前座標的結點入隊,其中prev指標表示該結點的上乙個座標

* 表尾插入法就好了

*/void push(queue

*result, int x, int y, qnode *prev)

給出main函式定義

int main(void)

}queue result;

intiqueue(&result);

/** row, col 為當前的橫縱座標

* (0, 0)的先前座標是佇列的頭結點,也就是result.front

* find是乙個哨兵,標誌著是否到達終點

* current指標指向當前的座標結點,並將當前座標節點周圍可走的座標入隊,如果 current為空的時候則表明找不到終點,佇列的遍歷類似於樹中的層序遍歷

int row = 0, col = 0;

push(&result, row, col, result.front);

maze[row][col] = 0;

int direction = 1;

int find = 0;

qnode *current = result.front->next;

/** 使用順時針遍歷,能走的座標就入隊,並且為了防止重複的座標入隊,必須將走過 的路堵上

*/while(current != null && !find)

while(direction <= 4)

break;

case

2:if(row + 1

< max && maze[row + 1][col] == 0)

break;

case

3:if(col - 1 >= 0 && maze[row][col - 1] == 0)

break;

case

4:if(row - 1 >= 0 && maze[row - 1][col] == 0)

break;

}direction++;

}current = current->next;

}show(&result, current);

return

0;}

show函式只要通過prev指標索引就能得到一條從起點走向終點的路徑,當然需要遞迴。

void show(queue

*result, qnode *current)

}

該解法其實是poj 3984迷宮問題的解法,鏈結

基於棧和佇列的迷宮問題求解

問題描述 以乙個m n的長方陣表示迷宮,0和1分別表示迷宮中的通路和障礙。設計乙個程式,對任意設定的迷宮,求出一條從入口到出口的通路,或得出沒有通路的結論。測試資料 迷宮的測試資料如下 左上角 1,1 為入口,右下角 8,9 為出口。一 需求分析 值得注意的是,題目要求中的測試資料給的是右下角 8,...

棧 深度優先搜尋與回溯演算法求解迷宮

利用棧和回溯演算法求解迷宮 這是老師帶著做的,自己寫不知道什麼時候能調出來 這就是和老師的差距,這樣的程式他就10幾分鐘而已 code include define max row 5 define max col 5 int maze max row max col struct pointsta...

棧與佇列應用 迷宮問題(DFS非最短路徑)

先輸入行列,在輸入迷宮 以 1 1 結束 include include define maxsize 100 define error 1 define ok 1 struct direction direction direct 4 方向試探 struct box typedef struct ...