深度優先搜索和廣度優先搜索_java

目錄:

  1. 概述
  2. 以二叉樹爲例,實現BFS和DFS遍歷
  3. 與深度優先算法和廣度優先算法相關的習題整理(參見下一篇博客)
    第一部分:關於深度優先算法和廣度優先算法的概述
    以二叉樹爲例,介紹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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章