算法(6)深度优先搜索和广度优先搜索
一、深度優先搜索(DFS)
主要思路: 從圖中一個未訪問的頂點 V 開始,沿著一條路一直走到底,然后從這條路盡頭的節點回退到上一個節點,再從另一條路開始走到底,不斷遞歸重復此過程,直到所有的頂點都遍歷完成,它的特點是“不撞南墻不回頭”,先走完一條路,再換一條路繼續走。
例子: 用深度優先搜索遍歷下面的樹
1、我們從根節點1開始遍歷,它相鄰的節點有2,3,4,先遍歷節點2,再遍歷2 的子節點5,然后再遍歷5的子節點9。
2、上圖中一條路已經走到底了,此時就從9回退到上一個節點5,看下節點5是否還有除9以外的節點,沒有繼續回退到2,2 也沒有除5以外的節點,回退到1,1 有除2以外的節點3,所以從節點3開始進行深度優先遍歷,如下:
3、同理從10開始往上回溯到6, 6 沒有除10以外的子節點,再往上回溯,發現3有除6以外的子點7,所以此時會遍歷7。從 7 往上回溯到3,1,發現1還有節點4未遍歷,所以此時沿著4,8進行遍歷,這樣就遍歷完成了。完整的節點的遍歷順序如下:
代碼實現:
(1)遞歸實現
遞歸實現比較簡單,由于是前序遍歷,所以我們依次遍歷當前節點,左節點,右節點即可,對于左右節點來說,依次遍歷它們的左右節點即可,依此不斷遞歸下去,直到葉節點(遞歸終止條件),遞歸的表達性很好,也很容易理解,不過如果層級過深,很容易導致棧溢出。
(2)非遞歸實現
仔細觀察深度優先遍歷的特點,對二叉樹來說,由于是先序遍歷,所以我們有如下思路:對于每個節點來說,先遍歷當前節點,然后把右節點壓棧,再壓左節點(這樣彈棧的時候會先拿到左節點遍歷,符合深度優先遍歷要求)。彈棧,拿到棧頂的節點,如果節點不為空,重復步驟 1, 如果為空,結束遍歷。
我們以二叉樹為例來看下如何用棧來實現 DFS。使用棧來將要遍歷的節點壓棧,然后出棧后檢查此節點是否還有未遍歷的節點,有的話壓棧,沒有的話不斷回溯(出棧)。
二、廣度優先搜索(BFS)
廣度優先遍歷,指的是從圖的一個未遍歷的節點出發,先遍歷這個節點的相鄰節點,再依次遍歷每個相鄰節點的相鄰節點。上文所述樹的廣度優先遍歷動圖如下,每個節點的值即為它們的遍歷順序。所以廣度優先遍歷也叫層序遍歷,先遍歷第一層(節點 1),再遍歷第二層(節點 2,3,4),第三層(5,6,7,8),第四層(9,10)。
深度優先遍歷用的是棧,而廣度優先遍歷要用隊列來實現,我們以下圖二叉樹為例來看看如何用隊列來實現廣度優先遍歷。
總結
以上是生活随笔為你收集整理的算法(6)深度优先搜索和广度优先搜索的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Unity - 手动创建 ditheri
- 下一篇: java 解释器与JIT编译器