資料結構之迷宮求解問題(一)

2021-08-19 00:23:33 字數 4071 閱讀 7477

我們小時候都玩過迷宮,走迷宮可以說是非常有意思了。而在我們大腦裡是如何對這個遊戲進行思考的呢?其實我們在玩這個遊戲的是,大多是一條路走到黑,如果到達出口那麼就走出來了,如果是死胡同,那麼回到剛才的分叉口,再找一條路再一條路走到黑,以此類推。而我們在實現迷宮求解的時候也是利用這種方法,這種方法又稱作回溯法。

我們要實現迷宮求解問題,首先應當是建立乙個迷宮。這裡我們用乙個二維陣列當做乙個平面,然後用01序列當做牆與路,最終通過走1的路,看是否能夠到達出口。

如上圖,此時1就是可以走的路,而0就是牆,無法行走。

我們可以建立乙個結構體,在結構體內放置地圖map。

#define row 6

#define col 6

typedef struct maze maze;

在定義完地圖以後,我們考慮的是,如何在地圖中走?以及定義規則。

首先我們應該確定入口點的位置。設為entry,而在我們的二維陣列中,區別元素的唯一法則就是下標與內容,這裡不考慮內容,下標應該是最理想的,所以我們應該再定義乙個結構體來存放下標。

typedef

struct pointpoint;

這樣我們在定義入口點,以及接下來每乙個走的點都可以用這個point來處理操作。

接下來就是如何走的問題了。

我們這裡採用的是從出口點開始,以順時針為方向,依次判斷入口點上、右、下、左是否能夠落腳,而落腳的判斷就是這四個點內的元素值是否為1,如果為1,那麼證明可以落腳,然後對落腳點進行標記併入棧,落腳以後利用遞迴對落腳點四周繼續判斷,以此類推,直至走到出口,或者是無路可走,出棧並返回。然後再判斷入口點右、下、左。

所以此時一旦落腳了(1,1)這個點,那麼就應該對其進行標記及入棧,接下來應該判斷這個點是否為出口,顯然不是,那麼接著以這個點為主,判斷它的四周,以此類推。接下來我們實現。

void mazeinit(maze* maze)//初始化地圖

intmap[row][col] = ,,,

,,};size_t i = 0;

size_t j = 0;

for(; i < row; ++i)

} return;

} printf("\n");

size_t i = 0;

size_t j = 0;

for(; i < row; ++i)

printf("\n");

}}int canstay(maze* maze, point cur)//是否能夠落腳

if(cur.col < 0 || cur.col >= col || \

cur.row < 0 || cur.row >= row)

if(maze->map[cur.row][cur.col] == 1)

return0;}

void markstay(maze* maze, point cur)//標記落腳點

maze->map[cur.row][cur.col] = 2;

}int i***it(maze* maze, point cur, point entry)//判斷是否是出口點

if((cur.row == 0 || cur.row == row - 1 || \

cur.col == 0 || cur.col == col - 1) && \

(cur.col != entry.col || cur.row != entry.row))

return0;}

int _getpathmaze(maze* maze, point cur, point entry)

//判斷是否能落腳

if(!canstay(maze, cur))

//標記落腳點

markstay(maze, cur);

//判斷是否是出口點

if(i***it(maze, cur, entry))

//如果不是出口點那麼就判斷它的四周

//預定順序為上、右、下、左

point up = cur;

up.row -= 1;

_getpathmaze(maze, up, entry);

point right = cur;

right.col += 1;

_getpathmaze(maze, right, entry);

point down = cur;

down.row += 1;

_getpathmaze(maze, down, entry);

point left = cur;

left.col -= 1;

_getpathmaze(maze, left, entry);

return1;}

void getpathmaze(maze* maze,point entry)//查詢路徑

entry.row = 0;

entry.col = 1;

_getpathmaze(maze, entry, entry);

}

我們發現,上面的**並沒有入棧用任何的入棧出棧操作,但是我們的思路裡面卻說入棧出棧,這是為什麼呢?其實這裡我們是利用了系統給予我們的棧,函式呼叫時每次呼叫函式都會形成自己的棧,函式返回後,棧銷毀,資料釋放。所以我們不必維護棧,就可以實現這個目的。

接下來,我們利用自己的棧來實現一下這一系列操作。

int _getpathmazebymystack(maze* maze, point entry) 

seqstack stack;

seqstackinit(&stack);

//首先判斷是否能夠落腳

if(!(canstay(maze, entry)))

//如果能夠落腳,那麼這個時候就標記落腳點,並且入棧

markstay(maze, entry);

seqstackpush(&stack, entry);

//判斷是否是出口,如果是出口就進行列印並標記

//如果不是出口點,此時應該判斷其四周的點,是否能夠落腳

//如果可以落腳就標記併入棧依次迴圈

point cur;

while(seqstackgetfront(&stack, &cur))

point up = cur;

up.row -= 1;

if(canstay(maze, up))

point right = cur;

right.col += 1;

if(canstay(maze, right))

point down = cur;

down.row += 1;

if(canstay(maze, down))

point left = cur;

left.col -= 1;

if(canstay(maze, left))

seqstackpop(&stack);

} return1;}

void getpathmazebymystack(maze* maze, point entry)

entry.row = 0;

entry.col = 1;

_getpathmazebymystack(maze, entry);

return;

}

這裡我們利用自己的棧,之前寫過的棧操作這裡直接使用,不再多說。

我們每次判斷能夠落腳以後首先先進行入棧操作,而接著判斷是否是出口點,如果不是那麼進入迴圈,取棧頂元素判斷它的四周是否可以落腳以及是否是出口點,可以落腳就再次入棧並直接continue進行下次迴圈,再去棧頂元素,比較,以此類推。直至迴圈結束。

資料結構 迷宮求解

定義迷宮 include seqstack.h define max row 6 最大行數 define max col 6 最大列數 typedef struct mazemaze void mazeinit maze maze size t i 0 for imap i j map i j vo...

資料結構 迷宮求解

include include int mg 10 10 地圖 int m 8 行數 int n 8 列數 typedef struct box 定義方塊型別 typedef struct sttype 定義順序棧型別 bool mgpath int xi,int yi,int xe,int ye ...

迷宮求解(資料結構)

include stdio.h include malloc.h define max 10 define l 10 define c 10 int sum l c typedef struct postype typedef struct selemtype typedef struct stac...