二叉树(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
}
}