一、採用隊列求解迷宮問題
使用一個隊列qu記錄走過的方塊,該隊列的結構如下:
typedef struct
{ int i,j; //方塊的位置
int pre; //本路徑中上一方塊在隊列中的下標
} Box; //方塊類型
typedef struct
{ Box data[MaxSize];
int front,rear; //隊頭指針和隊尾指針
} QuType; //定義順序隊類型
這裏使用的隊列qu不是環形隊列(因爲要利用出隊的元素找路徑),因此在出隊時,不會將出隊元素真正從隊列中刪除,因爲要利用它輸出路徑。
搜索從(1,1)到(M,N)的路徑
(1)首先將(1,1)入隊;
(2)在隊列qu不爲空時循環:出隊一次(由於不是環形隊列,該出隊元素仍在隊列中),稱該出隊的方塊爲當前方塊,front爲該方塊在qu中的下標。
①如果當前方塊是出口,則輸出路徑並結束。
②否則按順時針方向找出當前方塊的四個方位中可走的相鄰方塊(對應的mg數組值爲0),將這些可走的相鄰方塊均插入到隊列qu中,其pre設置爲本搜索路徑中上一方塊在qu中的下標值,也就是當前方塊的front值,並將相鄰方塊對應的mg數組值置爲-1,以避免回過來重複搜索。
(3) 若隊列爲空仍未找到出口,即不存在路徑。
bool mgpath1(int xi,int yi,int xe,int ye)
//搜索路徑爲:(xi,yi)->(xe,ye)
{ int i,j,find=0,di;
QuType qu; //定義順序隊
qu.front=qu.rear=-1;
qu.rear++;
qu.data[qu.rear].i=xi; qu.data[qu.rear].j=yi;
//(xi,yi)進隊
qu.data[qu.rear].pre=-1;
mg[xi][yi]=-1; //將其賦值-1,以避免回過來重複搜索
while (qu.front!=qu.rear && !find) //循環
{ qu.front++; //出隊
i=qu.data[qu.front].i; j=qu.data[qu.front].j;
if (i==xe && j==ye) //找到了出口,輸出路徑
{ find=1; print(qu,qu.front); return true; }
for (di=0;di<4;di++) //把每個可走的方塊插入隊列中
{ switch(di)
{
case 0:i=qu.data[qu.front].i-1;
j=qu.data[qu.front].j; break;
case 1:i=qu.data[qu.front].i;
j=qu.data[qu.front].j+1; break;
case 2:i=qu.data[qu.front].i+1;
j=qu.data[qu.front].j; break;
case 3:i=qu.data[qu.front].i;
j=qu.data[qu.front].j-1; break;
}
if (mg[i][j]==0)
{ qu.rear++; //將該相鄰方塊插入到隊列中
qu.data[qu.rear].i=i; qu.data[qu.rear].j=j;
qu.data[qu.rear].pre=qu.front;
mg[i][j]=-1;
}
}
}
return false; //未找到一條路徑時返回false
}
二、雙端隊列
所謂雙端隊列是指兩端都可以進行進隊和出隊操作的隊列,如下圖所示,將隊列的兩端分別稱爲前端和後端,兩端都可以入隊和出隊。其元素的邏輯結構仍是線性結構。
還有一種輸出受限的雙端隊列,即一個端點允許插入和刪除,另一個端點只允許插入或刪除的雙端隊列 。
例1,某隊列允許在兩端進行入隊操作,但僅允許在一端進行出隊操作,若a、b、c、d、e元素進隊,則以下不可能得到的順序有哪些?
(1)bacde (2)dbace (3)dbcae (4)ecbad
解:本題的隊列實際上是一個輸出受限的雙端隊列。
(1)a後端進,b前端進,c後端進,d後端進,e後端進,全出隊。
(2)a後端進,b前端進,c後端進,d前端進,e後端進,全出隊。
(3)a後端進,b前端進,因d未出,此時只能進隊,c怎麼進都不可能在b、a之間。
(4)a後端進,b前端進,c前端進,d後端進,e前端進,全出隊。
所以不可能得到的順序爲(3)。