数据结构-----迷宫问题(C语言)
生活随笔
收集整理的這篇文章主要介紹了
数据结构-----迷宫问题(C语言)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
數據結構-----迷宮問題
作者:黑衣俠客
前言
最近學習數據結構中,需要完成老師布置的作業,所以,研究了下迷宮問題,看起來很難的迷宮問題,其實,解決方法有很多,下面我將為大家介紹,用棧是如何解決迷宮問題的。
思路
首先,我們應該在代碼中布置迷宮的地圖,在布置迷宮地圖時,以二維數組來存儲每個點的數值,二維數組的好處是可以用坐標進行表示,此時,我設的是1為障礙物(墻),0為通路,下面來看一下,我在代碼中所寫的迷宮地圖。
使用二維數組來對迷宮地圖進行編輯
之后,我們定義一個棧結構,棧的每一層用來存儲走過的每個格子的橫坐標,縱坐標,以及從這個格子到下一格子所對應的方向的數字(在這里,我定義的方向是:0-上,1-右,2-下,3-左),然后再定義一個int型的指針,用于從棧底一次遍歷到棧頂,方便對每一層的數據進行操作。具體代碼是這樣的:
typedef struct {int i; //當前方塊的行號int j; //當前方塊的列號int di; //di是下一可走相鄰方位的方位號---上下左右的標記 } Box; typedef struct {Box data[MaxSize]; //是用來存儲位置坐標的,當MaxSize<位置坐標的數目時,則程序出錯,停止運行int top; //棧頂指針 } StType; //定義棧類型然后我們再來說一下,具體的操作方法:
1.定義了mgpath方法,用來執行具體的走迷宮的思想操作
int mgpath(int xi,int yi,int xe,int ye)其中,xi為原點的橫坐標,yi為原點的縱坐標,xe為終點的橫坐標,ye為終點的縱坐標。
2.初始化之前定義的棧,將棧的指針top賦值-1,然后top自增為0,就是棧的第一層,也就是棧底,存放橫縱坐標,以及方位值,然后將點所在位置標為-1,以免走重。
int i,j,k,di,find;StType st; //定義棧stst.top=-1; //初始化棧頂指針st.top++; //初始方塊進棧st.data[st.top].i=xi;//棧底一號存入橫坐標數值st.data[st.top].j=yi;//棧底一號存入縱坐標數值st.data[st.top].di=-1;//????????????????????????????????mg[xi][yi]=-1;3.這是最重要的一步,當棧不是空的時候就一直循環,直到找到終點為止,每次循環開始時,find都為0,而di為0~3,因此,滿足條件時,進入內層循環,在內層循環的第一行有一個di++,原因是:每次循環開始時,di的值都為-1,di自增后,就滿足了對橫縱坐標操作的條件了,我按照上右下左的順序,改變此時所在的位置坐標,(詳解:當di=0時,若走不通,那么就再次進入循環,進行自增,依次類推…),然后,當找到下一個位置為0時(通路),find=1,然后top向上走,在創建一行空間,讓每個走過的0位置,都變為-1,此外,需要注意是彈棧操作,當碰到死胡同的時候,那么就需要進行彈棧了,返回到上一步,并將該位置的值從-1變回到0(在進行圖像操作時需要用到這一點),(這里不用擔心會再次重復走到這個死胡同的位置,因為di++,直接在上一基礎方位自增,而不是重新開始,所以不必擔心這一點),至此,迷宮思想已全部完成,接下來就該做一些優化了。
while (st.top>-1) //棧不空時循環{i=st.data[st.top].i;j=st.data[st.top].j;di=st.data[st.top].di; //取棧頂方塊if (i==xe && j==ye) //找到了出口,輸出路徑{printf("迷宮路徑如下:\n");for (k=0; k<=st.top; k++){printf("\t(%d,%d)",st.data[k].i,st.data[k].j);if ((k+1)%5==0) //每輸出5個元素,就換行printf("\n");}printf("\n");return 0; //找到路徑之后,將所有路徑打印出來,然后,程序結束}find=0;while (di<4 && find==0) //找下一個可走方塊{di++;switch(di){case 0://向上走i=st.data[st.top].i-1;j=st.data[st.top].j;break;case 1://向右走i=st.data[st.top].i;j=st.data[st.top].j+1;break;case 2://向下走i=st.data[st.top].i+1;j=st.data[st.top].j;break;case 3://向左走i=st.data[st.top].i;j=st.data[st.top].j-1;break;}if (mg[i][j]==0) find=1; //mg[i][j]==0說明:該點可以走--------------(該點為此時所在點的下一預判點)}if (find==1) //找到了下一個可走方塊{st.data[st.top].di=di; //修改原棧頂元素的di值st.top++; //下一個可走方塊進棧st.data[st.top].i=i;st.data[st.top].j=j;st.data[st.top].di=-1; //再次初始化方向數值mg[i][j]=-1; //避免重復走到該方塊-----------------------//讓每一個點都變成起點,因此,既滿足遞歸的條件,也避免重復走到該位置}else //沒有路徑可走,則退棧-----------???????????為什么要退棧?不是剛剛只判斷了一個方向嗎?{mg[st.data[st.top].i][st.data[st.top].j]=0;//讓該位置變為其他路徑可走方塊st.top--; //將該方塊退棧}4.我在主函數中,添加了一些優化操作,主要對輸入原點以及圖像做了簡單處理。
while(1){printf("請輸入起點坐標:\n");printf("(橫坐標范圍:0~9,縱坐標范圍:0~9)\n");scanf("%d %d",&x,&y);if(mg[x][y]==1){printf("輸入坐標有誤,該位置為墻,請重新輸入:\n");}else{break;}}圖像處理:
printf("\n\n圖像表示:\n");for(t=0;t<10;t++){printf("\t\t");for(k=0;k<10;k++){if(mg[t][k]==1){printf("#");}else if(mg[t][k]==0){printf(" ");}else{printf("o");}}if(k==10){printf("\n");}}printf("\n此時,o所代表的圖標為迷宮行走路徑!!!\n");代碼部分
#include <stdio.h> #define MaxSize 100 #define M 8 #define N 8 int mg[M+2][N+2]= {{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} };//構造地圖 typedef struct {int i; //當前方塊的行號int j; //當前方塊的列號int di; //di是下一可走相鄰方位的方位號---上下左右的標記 } Box; typedef struct {Box data[MaxSize]; //是用來存儲位置坐標的,當MaxSize<位置坐標的數目時,則程序出錯,停止運行int top; //棧頂指針 } StType; //定義棧類型 //該棧中:每一個位置用于存儲Box,該棧對應了一個int型的top作為指針,依次移動,方便對棧中每一個位置進行操作,而Box中,存儲了該迷宮位置的橫坐標,縱坐標,和從上一位置移動到該位置所對應的方向數值 int mgpath(int xi,int yi,int xe,int ye) //求解路徑為:(xi,yi)->(xe,ye)//初位置橫坐標,初位置縱坐標,終點橫坐標,終點縱坐標 {int i,j,k,di,find;StType st; //定義棧stst.top=-1; //初始化棧頂指針st.top++; //初始方塊進棧st.data[st.top].i=xi;//棧底一號存入橫坐標數值st.data[st.top].j=yi;//棧底一號存入縱坐標數值st.data[st.top].di=-1;//????????????????????????????????mg[xi][yi]=-1;while (st.top>-1) //棧不空時循環{i=st.data[st.top].i;j=st.data[st.top].j;di=st.data[st.top].di; //取棧頂方塊if (i==xe && j==ye) //找到了出口,輸出路徑{printf("迷宮路徑如下:\n");for (k=0; k<=st.top; k++){printf("\t(%d,%d)",st.data[k].i,st.data[k].j);if ((k+1)%5==0) //每輸出5個元素,就換行printf("\n");}printf("\n");return 0; //找到路徑之后,將所有路徑打印出來,然后,程序結束}find=0;while (di<4 && find==0) //找下一個可走方塊{di++;switch(di){case 0://向上走i=st.data[st.top].i-1;j=st.data[st.top].j;break;case 1://向右走i=st.data[st.top].i;j=st.data[st.top].j+1;break;case 2://向下走i=st.data[st.top].i+1;j=st.data[st.top].j;break;case 3://向左走i=st.data[st.top].i;j=st.data[st.top].j-1;break;}if (mg[i][j]==0) find=1; //mg[i][j]==0說明:該點可以走--------------(該點為此時所在點的下一預判點)}if (find==1) //找到了下一個可走方塊{st.data[st.top].di=di; //修改原棧頂元素的di值st.top++; //下一個可走方塊進棧st.data[st.top].i=i;st.data[st.top].j=j;st.data[st.top].di=-1; //再次初始化方向數值mg[i][j]=-1; //避免重復走到該方塊-----------------------//讓每一個點都變成起點,因此,既滿足遞歸的條件,也避免重復走到該位置}else //沒有路徑可走,則退棧-----------???????????為什么要退棧?不是剛剛只判斷了一個方向嗎?{mg[st.data[st.top].i][st.data[st.top].j]=0;//讓該位置變為其他路徑可走方塊st.top--; //將該方塊退棧}}return(0); //表示沒有可走路徑,返回0 } int main() {int x,y,k,t;printf("終點坐標為:(8,8)\n");while(1){printf("請輸入起點坐標:\n");printf("(橫坐標范圍:0~9,縱坐標范圍:0~9)\n");scanf("%d %d",&x,&y);if(mg[x][y]==1){printf("輸入坐標有誤,該位置為墻,請重新輸入:\n");}else{break;}}mgpath(x,y,M,N);printf("\n\n圖像表示:\n");for(t=0;t<10;t++){printf("\t\t");for(k=0;k<10;k++){if(mg[t][k]==1){printf("#");}else if(mg[t][k]==0){printf(" ");}else{printf("o");}}if(k==10){printf("\n");}}printf("\n此時,o所代表的圖標為迷宮行走路徑!!!\n");return 0; }運行結果
以上全部代碼由vc++6.0調試成功
本次代碼,我已傳到github上------迷宮問題
總結
以上是生活随笔為你收集整理的数据结构-----迷宫问题(C语言)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 爬虫之邮箱混淆
- 下一篇: 我,32岁,动力机械专业研究生,转行到算