《戀上數據結構第1季》二叉樹基礎知識(性質、真二叉樹、滿二叉樹、完全二叉樹、遍歷...)

數據結構與算法筆記目錄《戀上數據結構》 筆記目錄

想加深 Java 基礎推薦看這個Java 強化筆記目錄

簡單的看一下樹形結構:
在這裏插入圖片描述
生活中的樹形結構:
在這裏插入圖片描述
在這裏插入圖片描述

  • 使用樹形結構可以大大提高效率;
  • 樹形結構是算法面試的重點;

樹(Tree)的基本概念

在這裏插入圖片描述
節點、根節點、父節點、子節點、兄弟節點

  • 一棵樹可以沒有任何節點,稱爲空樹
  • 一棵樹可以只有 1 個節點,也就是隻有根節點

子樹、左子樹、右子樹

節點的度(degree):子樹的個數;

樹的度:所有節點度中的最大值;

葉子節點(leaf):度爲 0 的節點;

非葉子節點:度不爲 0 的節點;

層數(level):根節點在第 1 層,根節點的子節點在第 2 層,以此類推(有些教程也從第 0 層開始計算)

節點的深度(depth):從根節點到當前節點的唯一路徑上的節點總數;

節點的高度(height):從當前節點到最遠葉子節點的路徑上的節點總數;

樹的深度:所有節點深度中的最大值;
樹的高度:所有節點高度中的最大值;
數的深度 等於 樹的高度

有序樹、無序樹、森林

有序樹:樹中任意節點的子節點之間有順序關係;

無序樹:樹中任意節點的子節點之間沒有順序關係,也稱爲 “自由樹”;

森林:由 m(m ≥ 0)棵互不相交的樹組成的集合;

二叉樹(Binary Tree)

在這裏插入圖片描述

二叉樹的特點:

  • 每個節點的度最大爲 2(最多擁有 2 棵子樹)
  • 左子樹和右子樹是有順序的,二叉樹是有序樹
  • 即使某節點只有一棵子樹,也要區分左右子樹
    在這裏插入圖片描述

二叉樹的性質

在這裏插入圖片描述
非空二叉樹的第 i 層,最多有 2i−1 個節點( i ≥ 1 )

在高度爲 h 的二叉樹上最多有 2h-1 個結點( h ≥ 1 )

對於任何一棵非空二叉樹,如果葉子節點個數爲 n0,度爲 2 的節點個數爲 n2,則有:n0 = n2 + 1

  • 假設度爲 1 的節點個數爲 n1,那麼二叉樹的節點總數 n = n0 + n1 + n2
  • 二叉樹的邊數 T = n1 + 2 * n2 = n – 1 = n0 + n1 + n2 – 1
  • 因此 n0 = n2 + 1

真二叉樹(Proper Binary Tree)

真二叉樹:所有節點的度都要麼爲 0,要麼爲 2

在這裏插入圖片描述
下圖不是真二叉樹:
在這裏插入圖片描述

滿二叉樹(Full Binary Tree)

滿二叉樹:最後一層節點的度都爲 0,其他節點的度都爲 2
在這裏插入圖片描述
假設滿二叉樹的高度爲 h( h ≥ 1 ),那麼

  • 第 i 層的節點數量: 2i−1
  • 葉子節點數量: 2h−1
  • 總節點數量 n
    • n = 2h − 1 = 20 + 21 + 22 + ⋯ + 2h−1
  • 樹高度與總節點的關係:h = log2(n + 1)

在同樣高度的二叉樹中,滿二叉樹的葉子節點數量最多、總節點數量最多;
滿二叉樹一定是真二叉樹,真二叉樹不一定是滿二叉樹

完全二叉樹(Complete Binary Tree)

完全二叉樹:對節點從上至下、左至右開始編號,其所有編號都能與相同高度的滿二叉樹中的編號對應
在這裏插入圖片描述
完全二叉樹的性質

  • 度爲 1 的節點只有左子樹
  • 度爲 1 的節點要麼是 1 個,要麼是 0 個
  • 同樣節點數量的二叉樹,完全二叉樹的高度最小
  • 假設完全二叉樹的高度爲 h( h ≥ 1 ),那麼:
    • 至少有 2h−1 個節點 ( 20 + 21 + 22 + ⋯ + 2h−2 + 1 )
    • 最多有 2h − 1 個節點( 20 + 21 + 22 + ⋯ + 2h−1,即 滿二叉樹
    • 總節點數量爲 n
      2h−1 ≤ n < 2h
      h − 1 ≤ log2n < h
      h = floor( log2n ) + 1
      floor 是向下取整,ceiling 是向上取整 )

在這裏插入圖片描述
在這裏插入圖片描述
下圖不是完全二叉樹
在這裏插入圖片描述

面試題(完全二叉樹)

在這裏插入圖片描述
國外教材的說法:瞭解一下
在這裏插入圖片描述

二叉樹的遍歷 + 練習題

遍歷是數據結構中的常見操作:把所有元素都訪問一遍;

線性數據結構的遍歷比較簡單:

  • 正序遍歷
  • 逆序遍歷

根據節點訪問順序的不同,二叉樹的常見遍歷方式有 4 種:

  • 前序遍歷(Preorder Traversal)
  • 中序遍歷(Inorder Traversal)
  • 後序遍歷(Postorder Traversal)
  • 層序遍歷(Level Order Traversal)

遍歷的應用

  • 前序遍歷:樹狀結構展示(注意左右子樹的順序)
  • 中序遍歷:二叉搜索樹的中序遍歷按升序或者降序處理節點
  • 後序遍歷:適用於一些先子後父的操作
  • 層序遍歷:計算二叉樹的高度、判斷一棵樹是否爲完全二叉樹

前序遍歷(Preorder Traversal)

訪問順序:節點、前序遍歷子樹、前序遍歷子樹

下圖前序遍歷的結果是:7、4、2、1、3、5、9、8、11、10、12
在這裏插入圖片描述
二叉樹的前序遍歷:https://leetcode-cn.com/problems/binary-tree-preorder-traversal/

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
	List<Integer> list = new ArrayList<>();
	public List<Integer> preorderTraversal(TreeNode root) {
        if(root == null) return list;
        
        list.add(root.val);
        preorderTraversal(root.left);
        preorderTraversal(root.right);
        
        return list;
    }
}

中序遍歷(Inorder Traversal)

訪問順序:中序遍歷子樹、節點、中序遍歷子樹
下圖中序遍歷的結果是:1、2、3、4、5、7、8、9、10、11、12

另一種中序遍歷訪問順序:中序遍歷子樹、節點、中序遍歷子樹
則下圖的中序遍歷的結果是:12、11、10、9、8 、7、5、4、3、2、1
在這裏插入圖片描述
二叉搜索樹的中序遍歷結果是升序或者降序的

二叉樹的中序遍歷: https://leetcode-cn.com/problems/binary-tree-inorder-traversal/

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
	List<Integer> list = new ArrayList<>();
    public List<Integer> inorderTraversal(TreeNode root) {
    	if(root == null) return list;
    	inorderTraversal(root.left);
    	list.add(root.val);
    	inorderTraversal(root.right);
    	return list;
    }
}

後序遍歷(Postorder Traversal)

訪問順序:後序遍歷子樹、後序遍歷子樹、節點
下圖的後序遍歷的結果是:1、3、2、5、4、8、10、12、11、9、7
在這裏插入圖片描述

二叉樹的後序遍歷: https://leetcode-cn.com/problems/binary-tree-postorder-traversal/

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
	List<Integer> list = new ArrayList<Integer>();
    public List<Integer> postorderTraversal(TreeNode root) {
        if(root == null) return list;
        postorderTraversal(root.left);
        postorderTraversal(root.right);
        list.add(root.val);
        return list;
    }
}

層序遍歷(Level Order Traversal)

訪問順序:從上到下、從左到右依次訪問每一個節點
下圖的層序遍歷的結果是:7、4、9、2、5、8、11、1、3、10、12
在這裏插入圖片描述
二叉樹的層次遍歷: https://leetcode-cn.com/problems/binary-tree-level-order-traversal/

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
	List<List<Integer>> resList = new ArrayList<>();
    public List<List<Integer>> levelOrder(TreeNode root) {
    	if(root == null) return resList;
    	
    	Queue<TreeNode> queue = new LinkedList<>();
    	int levelSize = 1;
    	queue.offer(root);
    
    	
    	List<Integer> list = new ArrayList<>(); ;
    	while(!queue.isEmpty()){
    		TreeNode node = queue.poll();
    		list.add(node.val);
    		levelSize--;
    		
    		if(node.left != null){
    			queue.offer(node.left);
    		}
    		if(node.right != null){
    			queue.offer(node.right);
    		}

    		if(levelSize == 0){
    			resList.add(list);
                levelSize = queue.size();
    			list = new ArrayList<>();
    		}
    	}
    	return resList;
    }
}

根據遍歷結果重構二叉樹

以下結果可以保證重構出唯一的一棵二叉樹:

  • 前序遍歷 + 序遍歷
  • 後序遍歷 + 序遍歷

前序遍歷 + 後序遍歷:

  • 如果它是一棵真二叉樹(Proper Binary Tree),結果是唯一的
  • 不然結果不唯一

前序遍歷+中序遍歷 重構二叉樹

在這裏插入圖片描述

前驅節點(predecessor)

在這裏插入圖片描述

後繼節點(successor)

在這裏插入圖片描述

四則運算

四則運算的表達式可以分爲3種:

  • 前綴表達式(prefix expression),又稱爲波蘭表達式
  • 中綴表達式(infix expression)
  • 後綴表達式(postfix expression),又稱爲逆波蘭表達式

在這裏插入圖片描述

表達式樹

在這裏插入圖片描述

練習

翻轉二叉樹

226_翻轉二叉樹:https://leetcode-cn.com/problems/invert-binary-tree/
在這裏插入圖片描述
在這裏插入圖片描述

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
	public TreeNode invertTree(TreeNode root) {
		if(root == null) return root;
		
		Queue<TreeNode> queue = new LinkedList<>();
		queue.offer(root);
		while(!queue.isEmpty()){
			TreeNode node = queue.poll();
			
			TreeNode treeNode = node.left;
			node.left = node.right;
			node.right = treeNode;
			
			if(node.left != null){
				queue.offer(node.left);
			}
			if(node.right != null){
				queue.offer(node.right);
			}
		}
		return root;
	}
}

二叉樹的最大深度

104_二叉樹的最大深度:https://leetcode-cn.com/problems/maximum-depth-of-binary-tree/

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    public int maxDepth(TreeNode root) {
    	if(root == null) return 0;
    	return 1 + Math.max(maxDepth(root.left), maxDepth(root.right));
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章