二叉树

2 阅读1分钟

二叉树(Binary Tree)是计算机科学中一种非常基础且重要的树形数据结构。你可以把它想象成一棵倒着生长的树,它的根在最上面,叶子在最下面。

在二叉树中,每个节点最多只能有两个子节点,分别被称为**“左子节点”“右子节点”**。这两个子节点的次序是严格区分的,不能随意颠倒。

📏 核心性质

二叉树有几个非常经典的数学特性,掌握它们对理解算法很有帮助:

  • 层级节点数:二叉树的第 i 层上,至多有 2^(i-1) 个节点(根节点算第1层)。
  • 总节点数:深度为 k 的二叉树,至多有 2^k - 1 个节点。
  • 叶子节点公式:对于任何一棵二叉树,如果它的叶子节点(没有孩子的节点)数为 n₀,度为2(有两个孩子)的节点数为 n₂,那么永远满足 n₀ = n₂ + 1

🌟 两种特殊的二叉树

在实际应用中,我们经常遇到两种形态非常规整的二叉树:

  • 满二叉树 (Full Binary Tree)
    每一层的节点数都达到了最大值。也就是说,除了最底层的叶子节点外,每个节点都有左右两个孩子,且所有叶子都在同一层。
  • 完全二叉树 (Complete Binary Tree)
    除了最后一层外,其他各层的节点数都达到最大;最后一层的节点从左到右是连续排列的,中间不能有空缺。这种结构非常适合用数组来顺序存储(比如堆数据结构就是基于完全二叉树)。

🔄 二叉树的遍历方式

遍历是指按照某种规则,不重复地访问二叉树中的所有节点。常见的遍历方式有四种:

  • 前序遍历 (Pre-order):按照 “根 -> 左 -> 右” 的顺序访问。
  • 中序遍历 (In-order):按照 “左 -> 根 -> 右” 的顺序访问。
  • 后序遍历 (Post-order):按照 “左 -> 右 -> 根” 的顺序访问。
  • 层序遍历 (Level-order):从上到下、从左到右,一层一层地访问。

💡 常见的应用类型

除了基础形态,二叉树还有很多衍生出的高级形态,被广泛应用于各种场景中:

  • 二叉搜索树 (BST):左子树上所有节点的值都小于根节点,右子树上所有节点的值都大于根节点。这种特性让查找效率非常高。

  • 平衡二叉树 (AVL):左右两个子树的高度差绝对值不超过1,防止树变得“歪歪扭扭”,保证了操作的高效性。

  • 哈夫曼树:常用于数据压缩和编码。

💡 常见的应用类型

简单来说,二叉树是许多复杂算法和高级数据结构(如数据库索引、文件系统等)的基石

前序遍历算法:

/** * Definition for a binary tree node. 
* public class TreeNode { 
*     public var val: Int 
*     public var left: TreeNode? 
*     public var right: TreeNode? 
*     public init() { self.val = 0; self.left = nil; self.right = nil; } 
*     public init(_ val: Int) { self.val = val; self.left = nil; self.right = nil; } 
*     public init(_ val: Int, _ left: TreeNode?, _ right: TreeNode?) { 
*         self.val = val 
*         self.left = left 
*         self.right = right 
*     } 
* } 
*/

class Solution {
    func postorderTraversal(_ root: TreeNode?) -> [Int] {
        var ret: [Int] = []
        func postOrder(_ node: TreeNode?) {
            guard let node = node else { return }
            ret.append(node.val)
            postOrder(node.left)
            postOrder(node.right)
        }
        postOrder(root)
        return ret
    }
}