迷宮問題(上)之堆疊詳解(C語言描述)

2021-09-10 17:52:40 字數 3011 閱讀 9785

迷宮問題,顧名思義就是求出從入口到出口的路徑。正常情況下,我們的想法都是採用「窮舉求解」的方法,即從迷宮入口出發,順著某一方向向前試探,若能走通則繼續向前走;否則就沿著原路返回,換乙個方向再繼續進行試探,直到所有可能的路徑均被試探完。為了保證我們可以沿著原路返回(回溯),我們可以選用棧這個先入後出的資料結構來儲存從入口到當前位置的路徑。

首先我們建立了這樣乙個8*8的迷宮,為了在一會兒計算方位的時候更加便利,我們給迷宮外面加上了乙個「外牆」,如下圖所示,白色代表通路,黑色代表牆,題目要求我們的路徑必須是簡單路徑即在所求得的路徑上不能重複出現同一通道塊。

為了表示迷宮,我們建立了乙個二維陣列mg,用0來表示通路,用1來表示牆,在迷宮中的每乙個方塊,其上下左右均有乙個方塊與之相鄰,如下圖所示,我們假設當前方塊的位置為(i, j),規定其上方的方塊的方位號為0,按照順時針的遞增順序依次給其餘三個方位的方位號進行編號。在試探的過程中,我們按照方位號從0到3進行查詢下乙個可走的方塊的位置。

我們採用棧這個資料結構來進行方塊的儲存,自然要對棧進行相應的定義,其定義如下

用c語言的思路來求解迷宮問題(從(1,1)到(m,n)的路徑)演算法:先將入口位置的方塊進棧(初始方塊的位置設定為-1),在棧不空的時候進迴圈:讀棧頂方塊(不退棧),如果該方塊是出口,則輸出棧中的方塊位置即為路徑;否則就在相鄰的方塊中尋找下乙個可走的方塊,若不存在可走的方塊,則退棧(即向後退一步);若存在這樣的方塊,則將其位置存在棧中,並將這個可走的相鄰方塊入棧(並將新方塊的初始位置設定為1)。

為了保證試探的可走的相鄰方塊不是已經走過的方塊,我們可以在乙個方塊入棧後將其對應的迷宮陣列(mg陣列)元素改為-1(變為不可走的方塊),在退棧時(當沒有可以走的方塊的時候)再將其恢復為0。例如方塊(i, j)已經入棧,在試探(i +1 ,j)的時候,又會試探到(i, j),這樣可能會引起死迴圈,採用上述方法之後就會避免這種情況發生。

對應的具體實現如下:

/*

1表示對應通道是牆,0表示對應通道為通路

*/#include#define maxsize 10001 //棧的最大容量

#define m 8 //8行

#define n 8 //8列

struct

st[maxsize]; //定義棧

int top = -1; //初始化棧頂指標

int mg[m + 2][n + 2] = //為了計算方便,在最外邊加了"外牆",即增加了兩行兩列 , ,

, ,, ,

, ,, ,

}; //路徑為,入口(x1, y1),出口(x2, y2)

void mgpath(int x1, int y1, int x2, int y2)

puts("");

return;

} find = 0;

while(find == 0 && di < 4) //尋找下乙個可走的方塊

if(mg[i][j] == 0) //如果找到了通路,就不用再進行上面的迴圈了

find = 1;

} if(find == 1) //找到了下乙個可走的方塊

else //沒有路徑就退棧(回溯)

}puts("沒有可走路徑。");

}int main()

如果本題稍作改動,變為輸出迷宮所有路徑並求出最短路徑及其長度。對比上面的解法,在成功的找到一條可以走下去的路徑之後就會退出;那我們可以將路徑儲存到另乙個棧path中,並定義變數minlen來儲存最短路徑長度。當 while迴圈結束的時候輸出path中最短的路徑。具體實現如下:

#include#define maxsize 10001		//棧的最大容量 

#define m 8 //8行

#define n 8 //8列

struct

st[maxsize], path[maxsize]; //定義棧

int top = -1; //初始化棧頂指標

int count = 1; //初始化計數器

int minlen = maxsize; //最短路徑長度

int mg[m + 2][n + 2] = //為了計算方便,在最外邊加了"外牆",即增加了兩行兩列 , ,

, ,, ,

, ,, ,

}; //路徑為,入口(x1, y1),出口(x2, y2)

void mgpath(int x1, int y1, int x2, int y2)

puts("");

if(top + 1 < minlen)

mg[st[top].i][st[top].j] = 0; //讓該位置方塊變為其他路徑可走的方塊

top--;

i = st[top].i;

j = st[top].j;

di = st[top].di;

} find = 0;

while(find == 0 && di < 4) //尋找下乙個可走的方塊

if(mg[i][j] == 0) //如果找到了通路,就不用再進行上面的迴圈了

find = 1;

} if(find == 1) //找到了下乙個可走的方塊

else //沒有路徑就退棧(回溯)

}if(minlen == 10001 && st[top].i == 0 == st[top].j == 0) //如果輸出的元素均為0,則說明沒有路徑可走

puts("沒有路徑可走");

else }

}int main()

堆疊 用C語言描述

include include 堆疊順序儲存 typedef int position typedef int elementtype typedef struct snode ptrtosnode elementtype error 1 struct snode typedef ptrtosnod...

詳解C語言之堆疊

目錄 a.堆疊是一種特殊的線性表 b.堆疊的資料元素以及資料元素間的邏輯關係和線性表完全相同,其不同點是 線性表允許在任意位置插入和刪除資料元素,但堆疊只允許在固定一端進行插入和刪除資料元素,所以棧又稱為 先進後出 filo 或 後進先出 lifo 的線性表 c.堆疊中允許進行插入和刪除資料元素的一...

詳解c c 鏈式堆疊描述進製轉換問題示例

目錄 基礎操作需要建立鍊錶來儲存資料 使用尾插法和尾刪法來表示棧中的入棧和出棧 typedef struct node node,lpnode lpnode creatnode int data void insertbytail lpnode www.cppcns.comhead,int data...