基於迴圈佇列的BFS的原理及實現

2021-10-17 19:38:28 字數 2278 閱讀 6394

1.故事起源

有乙隻螞蟻出去尋找食物,無意中進入了乙個迷宮。螞蟻只能向上、下、左、右4個方向走,迷宮中有牆和水的地方都無法通行。這時螞蟻犯難了,怎樣才能找出到食物的最短路徑呢?

2.思考

螞蟻在起點時,有4個選擇,可以向上、下、左、右某乙個方向走1步。

如果螞蟻走過了一段距離,此時也依然只有4個選擇。

當然要排除之前走過的地方(不走回頭路,走了也只會更長)和無法通過的牆和水。

螞蟻想,還好我會影分身。如果每一步都分身成4個螞蟻,向4個方向各走1步,這樣最先找到食物的肯定就是最短的路徑了(因為每一步都把能走的地方都走完了,肯定找不出更短的路徑了)。

而且還能看出,第1步會到達所有到起點距離為1的地方,第2步也會到達所有距離為2的地方。

如此類推,第n步會覆蓋所有到起點最短距離為n的地方。

3.問題建模

把迷宮地圖放在二維陣列中,能通行的地方為0,牆和水的地方為負數。

每一步向4個方向走,可以通過當前座標(x,y)加上乙個方向向量。

這個其實就是寬度優先搜尋(bfs)的思想。

4.寬度優先搜尋(bfs)

又稱廣度優先搜尋,優先向四周擴充套件子節點,是最簡便的圖的搜尋演算法之一,一般通過佇列來實現。

4.1 佇列

是一種特殊的線性表,它只允許在表的前端進行刪除操作,而在表的後端進行插入操作,即先進先出。

佇列一般通過陣列實現,對該陣列增加一些操作上的限制。

但上面的實現有一些缺陷,當佇列滿時,也就是tail指標移動到隊尾,這時就無法再插入資料,但前面的元素已經出隊了,可能還有空缺的位置。

為了能高效利用空間,對該佇列增加一點改進,也就是迴圈佇列的產生。

4.2 迴圈佇列

把佇列想象成乙個首尾相接的環形。

陣列實現,需要多預留乙個空間。如果head=tail時,無法判斷是隊空還是隊滿,所以占用乙個空間,通過tail+1與head的關係來判斷是否隊滿。

4.3 佇列實現bfs

實現步驟如下:

將起點加入佇列。

從隊首取出乙個節點,通過該節點向4個方向擴充套件子節點,並依次加入隊尾。

重複以上步驟,直至隊空或已找到目標位置。

回歸迷宮問題,到起點的距離為1,2,3…的點會依次入隊。

當head指標遍歷到距離為2的點時,向4周擴充套件距離為3的節點,並繼續入隊。

5.**實現

5.1 變數定義

// 方向向量

const int direction[4][2] = ,,,

};const int maxm = 100, maxn = 100, queue_length = 5;

// 佇列中的節點

struct node

node(int xx, int yy, int d) : x(xx), y(yy), distance(d) {}

};int n, m, step = 0, map[maxm][maxn], visit[maxm][maxn];

node start, target;

5.2 bfs標準模板

void bfs()

if ((tail + 1) % queue_length == head)

// 新座標入隊

queue[tail] = node(dx, dy, distance + 1);

tail = (tail + 1) % (queue_length);}}

}}5.3 路徑回溯

void printpath() ;

for (int i = 0; i < m; ++i)

}x = target.x;

y = target.y;

path[start.x][start.y] = 0;

// 路徑回溯

while (!(x == start.x && y == start.y))

// 路徑列印

for (int i = 0; i < m; ++i) else

}cout << endl;}}

5.4 資料輸入

int main()

}cin >> start.x >> start.y >> target.x >> target.y;

bfs();

if (step > 0) printpath();

return 0;

}5.5 測試結果

輸入資料:

5 50 0 -1 0 0

0 0 0 0 -2

-1 0 -2 0 0

0 0 0 -1 0

0 -2 0 0 0

1 1 4 3

迴圈佇列的原理及例子

何謂迴圈佇列?首先我們要說明的是迴圈佇列仍然是基於陣列實現的。但是為了形象化的說明問題,我們如下圖所示 1.圖中有兩個指標 其實就是兩個整數型變數,因為在這裡有指示作用,所以這裡理解為指標 front rear,乙個指示隊頭,乙個指示隊尾。2.rear和front互相追趕著,這個追趕過程就是佇列新增...

佇列 基於迴圈陣列的實現

description 請完成以下佇列類的實現 請注意陣列實現應該為迴圈陣列 enum errorcode success,underflow,overflow const int maxqueue 100 template class myqueue public myqueue bool emp...

迴圈佇列的定義及操作

include include define maxsize 50 typedef struct seqqueue void initqueue seqqueue q 初始化操作,將q初始化為乙個空的迴圈佇列 bool enterqueue seqqueue q,int x 入隊,將元素x入隊 bo...