Binary Tree 二元樹
定義
binary tree 的每一個 node 最多只有兩個 subnode (子節點)
Complete Binary Tree(完全二元樹)
- 最後一層以外的層全部都是滿的
- 最後一層的節點全部向左靠
Binary Search Tree
\begin{align}
& \forall \text{ internal node } n \text{:} \\
& \text{1. } \forall l \in (n \text{‘s left subtree}), n \text{.key} > l \text{.key} \\
& \text{2. } \forall r \in (n \text{‘s right subtree}), n \text{.key} < r \text{.key}
\end{align}
Template of Searching
curr = root
while ...condition_about_curr...:
curr = curr.right if {curr.val is too small} else curr.left
return curr
相關例題
- Leetcode # 235. Lowest Common Ancestor of a Binary Search Tree
- Leetcode # 270. Closest Binary Search Tree Value
- Leetcode # 701. Insert into a Binary Search Tree
相關文章
Traversal 遍歷
總覽
| 方法 | Complexity |
| 深度優先搜尋(Depth-First Search; use stack) 廣度優先搜尋(Breadth-First Search; use queue) |
Time Complexity: O(N) Space Complexity: O(N) |
| Recursive | Time Complexity: O(N) Space Complexity: O(N) |
| Morris Traversal | Time Complexity: O(N) Space Complexity: O(1) |
DFS
stack = [root]
while stack:
cur = stack:pop()
if cur is leaf:
...do some operation ...
if cur.left:
stack.attend(cur.left)
if cur.right:
stack.attend(cur.right)
BFS (Level Order Traversal)
queue = collections.deque(root)
while queue:
cur = queue.popleft()
if cur is leaf:
...do some operation ...
if cur.left:
queue.attend(cur.left)
if cur.right:
queue.attend(cur.right)
前序/中序/後序 (Preorder / Inorder / Postorder) Traversal

- 前序:根節點 → 左子樹 → 右子樹
(1 2 4 7 8 5 3 6 9 10) - 中序:左子樹 → 根節點 → 右子樹
(7 4 8 2 5 1 3 9 6 10) - 後序:左子樹 → 右子樹 → 根節點
(7 8 4 5 2 9 10 6 3 1)
Predecessor/Successor (上一個/下一個 node)
- Predecessor: 上一個 node
- Successor: 下一個 node
Pre-order/In-order/Post-order Traversal in Recursive
def traversal(root, order):
if root is None:
return []
if order = "pre":
return [cur] + traversal(cur.left) + traversal(cur.right)
if order = "in":
return traversal(cur.left) + [cur] + traversal(cur.right)
if order = "post
return traversal(cur.left) + traversal(cur.right) + [cur]
Expression Tree

- 前序 (Prefix) 或 波蘭表示法 (Polish notation)
[× ÷ + 7 8 5 + 4 – 9 3] - 中序 (Infix) :一般習慣的四則運算表示法
[((7 + 8) ÷ 5) × (4 + 9 – 3)] - 後序 (Postfix) 或 逆波蘭表示法 (Reverse Polish notation)
[7 8 + 5 ÷ 4 9 3 – + ×]
Threaded Binary Tree
將未使用的 left/right subtree pointer
作為指向此 node 的 in-order predecessor/successor 的thread
Morris Traversal
和 Threaded Binary Tree 相同
使用未使用的 left/right subtree pointer
在移動前,先將現在位置 current
借用 predecessor.right 來記錄 (step 2.1)
這是我們第一次來到這個節點,之後向左移動
將來走到這個被修改過的 predecessor 後
利用現在的紀錄移動至 current 即當下的 seccessor 後 (step 1.)
再將該 predecessor.right 回復為空 (step 2.2)
這是我們再次回到這個節點,
並且已經遍歷完成左子樹,之後向左移動
Morris Traversal 的優點是
space complexity 為 O(1)
並且最終會將樹恢復為原狀
In-order Traversal
中序:左子樹 → 根節點 → 右子樹
輸出 current 的條件
- 沒有左子樹
- predecessor.right 不為空
⇒ 表示我們已遍歷完左子樹
流程
- 如果 current.left 為空,則輸出 current,
且將 current 設為 current.right - 如果 current.left 不為空,
則找到 current 的 predecessor (左子樹的 most right node )- 如果 predecessor.right 為空,
則將 predecessor.right 設為 current ,
將 current 設為 current.left - 如果 predecessor.right 不為空,
則將 predecessor.right 設為空(將樹恢復原狀)。
輸出 current ,將 current 設為 current.right
- 如果 predecessor.right 為空,
- 直到 current 為空停止

LeetCode # 94. Binary Tree Inorder Traversal
class Solution:
def inorderTraversal(self, root: Optional[TreeNode]) -> List[int]:
if not root: return []
return (self.inorderTraversal(root.left) if root.left else []) \
+ [root.val] \
+ (self.inorderTraversal(root.right) if root.right else [])
Pre-order Traversal
前序:根節點 → 左子樹 → 右子樹
輸出 current 的條件
- 沒有左子樹
- 去左子樹之前
也就是我們尚未變更 predecessor.right
predecessor.right 尚為空的時候
流程
- 如果 current.left 為空,則輸出 current,
且將 current 設為 current.right - 如果 current.left 不為空,
則找到 current 的 predecessor (左子樹的 most right node )- 如果 predecessor.right 為空,輸出 current
並將 predecessor.right 設為 current ,
將 current 設為 current.left - 如果 predecessor.right 不為空,
則將 predecessor.right 設為空(將樹恢復原狀)。
將 current 設為 current.right
- 如果 predecessor.right 為空,輸出 current
- 直到 current 為空停止

Post-order Traversal
後序:左子樹 → 右子樹 → 根節點
流程
前置作業:
令 dump = Node(0, root, 空)
current = dump
- 如果 current.left 為空,
將 current 設為 current.right - 如果 current.left 不為空,
則找到 current 的 predecessor (左子樹的 most right node )- 如果 predecessor.right 為空
並將 predecessor.right 設為 current ,
將 current 設為 current.left - 如果 predecessor.right 不為空,
則將 predecessor.right 設為空(將樹恢復原狀)。
從 predecessor 輸出至 current.left (from current.left to predecessor 的逆向輸出),
將 current 設為 current.right
- 如果 predecessor.right 為空
- 直到 current 為空停止

逆向輸出
# Reverse the tree nodes 'from' -> 'to'.
# You should can arrive 'to' from 'from'
# by each passed node's right subtree pointer.
def reverse(_from, to):
if _from == to: return
x, y = _from, _from.right
while True:
y, y.right, x = y.right, x, y
if x == to: break
# Print the reversed tree nodes 'from' -> 'to'.
def print_reverse(_from, to):
reverse(_from, to);
p = to
while True:
print(p.val)
if p == _from: break
p = p->right
reverse(to, _from)
相關例題
Others
Definition for a Binary Tree Node in LeetCode
Python
class TreeNode:
def __init__(self, val=0, left=None, right=None):
self.val = val
self.left = left
self.right = right
[Python] Binary Tree to List
def binary_tree_to_list(root, level=0):
if root is None:
return []
btree_in_list = []
curr_level = [root]
has_next_level = True
while has_next_level:
has_next_level = False
next_level = []
val_this_level = []
for node in curr_level:
if node:
has_next_level = True
next_level += [node.left, node.right]
val_this_level.append(node.val)
else:
next_level += [None] * 2
val_this_level.append(None)
btree_in_list += val_this_level if has_next_level else []
curr_level = next_level
for i in range(len(btree_in_list) - 1, -1, -1):
if btree_in_list[i]:
return btree_in_list[:i + 1]
Last Updated on 2024/04/27 by A1go