目錄:
- 概述
- 以二叉樹爲例,實現BFS和DFS遍歷
- 與深度優先算法和廣度優先算法相關的習題整理(參見下一篇博客)
第一部分:關於深度優先算法和廣度優先算法的概述
以二叉樹爲例,介紹BFS和DFS遍歷的過程
BFS:廣度優先算法(類似於水的漣漪)
對於廣度優先遍歷二叉樹,也就是按層次的去遍歷。依次遍歷根節點,然後是左孩子和右孩子。所以要遍歷完當前節點的所有孩子,這樣纔是層次遍歷嘛。此時我們就不能用棧這個數據結構了,因爲棧只能在棧頂操作。在這裏,我們需要根據左右孩子的順序來輸出,所以就是先進先出的原則,那麼我們當然就想到了隊列這個數據結構。可以在rear依次插入左右孩子,在front依次讀取並刪除左右孩子,這樣就保證了層次的輸出。
廣度優先遍歷:廣度優先遍歷是連通圖的一種遍歷策略,因爲它的思想是從一個頂點V0開始,輻射狀地優先遍歷其周圍較廣的區域故得名。
根據廣度優先遍歷的特點我們利用Java數據結構隊列Queue來實現。
廣度優先搜索的步驟爲:
(1)、節點1進隊,節點1出隊,訪問節點1
(2)、節點1的孩子節點2進隊,節點3進隊。
(3)、節點2出隊,訪問節點2,節點2的孩子節點4進隊,節點5進隊;
(4)、節點3出隊,訪問節點3,節點3的孩子節點6進隊,節點7進隊;
(5)、節點4出隊,訪問節點4,節點4沒有孩子節點。
(6)、節點5出隊,訪問節點5,節點5沒有孩子節點。
(7)、節點6出隊,訪問節點6,節點6沒有孩子節點。
(8)、節點7出隊,訪問節點7,節點7沒有孩子節點,結束。
習題:力扣102. 二叉樹的層次遍歷
給定一個二叉樹,返回其按層次遍歷的節點值。 (即逐層地,從左到右訪問所有節點)。
例如:
給定二叉樹: [3,9,20,null,null,15,7],
3
/ \
9 20
/ \
15 7
返回其層次遍歷結果:
[
[3],
[9,20],
[15,7]
]
解題思路:BFS
代碼實現:
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
class Solution {
public List<List<Integer>> levelOrder(TreeNode root) {
List<List<Integer>> list=new ArrayList<>();
if(root==null) {
return list;
}
Deque<TreeNode> deq=new LinkedList<TreeNode>();
deq.add(root);
while(!deq.isEmpty()) {
//每一層的節點值
List<Integer> al=new ArrayList<>();
int size=deq.size();
for(int i=0;i<size;i++) {
TreeNode node=deq.poll();
al.add(node.val);
if(node.left!=null) {
deq.add(node.left);
}
if(node.right!=null) {
deq.add(node.right);
}
}
list.add(al);
}
return list;
}
}
DFS:深度優先算法(類似於“一根筋”)
深度優先遍歷,也就深入的遍歷,沿着每一個分支直到走到最後,然後才返回來遍歷剩餘的節點。二叉樹不同於圖,圖需要標記節點是否已經訪問過,因爲可能會存在環,而二叉樹不會出現環,所以不需要標記。那麼,我們只需要一個棧空間,來壓棧就好了。因爲深度優先遍歷,遍歷了根節點後,就開始遍歷左子樹,所以右子樹肯定最後遍歷。我們利用棧的性質,先將右子樹壓棧,然後在對左子樹壓棧。此時,左子樹節點是在top上的,所以可以先去遍歷左子樹。
深度優先遍歷:深度優先遍歷是圖論中的經典算法。其利用了深度優先搜索算法可以產生目標圖的相應拓撲排序表,採用拓撲排序表可以解決很多相關的圖論問題,如最大路徑問題等等。
根據深度優先遍歷的特點我們利用Java集合類的棧Stack先進後出的特點來實現。我用二叉樹來進行深度優先搜索。
深度優先搜索的步驟爲:
(1)、首先節點 1 進棧,節點1在棧頂;
(2)、然後節點1出棧,訪問節點1,節點1的孩子節點3進棧,節點2進棧;
(3)、節點2在棧頂,然後節點2出棧,訪問節點2
(4)、節點2的孩子節點5進棧,節點4進棧
(5)、節點4在棧頂,節點4出棧,訪問節點4,
(6)、節點4左右孩子爲空,然後節點5在棧頂,節點5出棧,訪問節點5;
(7)、節點5左右孩子爲空,然後節點3在站頂,節點3出棧,訪問節點3;
(8)、節點3的孩子節點7進棧,節點6進棧
(9)、節點6在棧頂,節點6出棧,訪問節點6;
(10)、節點6的孩子爲空,這個時候節點7在棧頂,節點7出棧,訪問節點7
(11)、節點7的左右孩子爲空,此時棧爲空,遍歷結束。
習題:力扣257. 二叉樹的所有路徑
給定一個二叉樹,返回所有從根節點到葉子節點的路徑。
說明: 葉子節點是指沒有子節點的節點。
示例:
輸入:
1
/ \
2 3
\
5
輸出: [“1->2->5”, “1->3”]
解釋: 所有根節點到葉子節點的路徑爲: 1->2->5, 1->3
解題思路:DFS
實現代碼:
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
class Solution {
public List<String> binaryTreePaths(TreeNode root) {
List<String> res=new ArrayList<>();
String path="";
//代碼的魯棒性判斷
if(root==null) {
return res;
}
dfs_bin(path,root,res);
return res;
}
private void dfs_bin(String path, TreeNode root, List<String> res) {
if(root==null) {
return;
}
if(root.left==null && root.right==null) {
path+=root.val;
res.add(path);
return;
}else {
dfs_bin(path+root.val+"->",root.left,res);
dfs_bin(path+root.val+"->",root.right,res);
}
}
}
參考:
(1) https://blog.csdn.net/kuailekemi/article/details/9234269
(2)https://blog.csdn.net/weixin_42289193/article/details/81741756