軟體工程師面試必備:深入淺出樹狀結構(Tree)與演算法

更新於 發佈於 閱讀時間約 12 分鐘

軟體工程師職涯升級計畫啟動!立即預約職涯諮詢、履歷健檢或模擬面試👈,為您的加薪做好準備!

樹(Tree)是一種常見且重要的非線性資料結構,經常出現在程式設計面試題目中。你可以將它想像成一個倒置的家族族譜,用來組織與儲存層級化資料。它的核心特徵如下:

  • 唯一的根節點 (Root):整棵樹的起點,且只存在一個。
  • 單一父節點 (Single Parent):除了根節點外,每個節點都僅有一個父節點。
  • 無環結構 (No Cycles):任意兩節點間只有一條唯一路徑,不會形成循環。

以下這兩種資料並不屬於 tree

raw-image

常見術語

在面試中,樹的相關術語經常被問到,以下是基本概念:

  • 節點 (Node):樹中的每個資料元素。
  • 根 (Root):位於最上層的節點。
  • 葉節點 (Leaf):沒有子節點的節點,代表分支的終點。
  • 父節點 (Parent) 與 子節點 (Child):層級關係中,指向下層的為父節點,被指向的為子節點。
  • 深度 (Depth):從根節點到某一節點的邊數,根節點深度為 0。
  • 高度 (Height):從某一節點到最遠葉節點的邊數,葉節點高度為 0。
raw-image



樹的建構:程式中的表示方式

在程式設計中,樹的節點通常以**類別(Class)或物件(Object)**來定義。以下是 JavaScript 的簡單實作範例:

class TreeNode {
constructor(val) {
this.val = val;
this.left = null; // 左子節點
this.right = null; // 右子節點
}
}

在面試中,最常遇到的樹種類包含:

  • 二元樹 (Binary Tree):每個節點最多有兩個子節點(左、右)。
  • 二元搜尋樹 (Binary Search Tree, BST):在二元樹的基礎上增加排序規則:
    • 左子節點值 < 父節點值
    • 右子節點值 > 父節點值
      這個特性讓搜尋、插入與刪除的效率大幅提升。

樹的遍歷(Traversal)

遍歷樹是面試常見的必考題,主要分為兩大類:


1. 深度優先搜尋(DFS, Depth-First Search)

DFS 的思路是「一路走到底,再回頭」,可以透過遞迴堆疊 (Stack) 來實作。

常見的三種走訪方式:

  • 前序遍歷 (Pre-order):中 → 左 → 右
  • 中序遍歷 (In-order):左 → 中 → 右

    對 BST 進行中序遍歷,可得到排序後的數列。

  • 後序遍歷 (Post-order):左 → 右 → 中

遞迴版本

function preorder(root) {
if (!root) return [];
return [root.val, ...preorder(root.left), ...preorder(root.right)];
}

function inorder(root) {
if (!root) return [];
return [...inorder(root.left), root.val, ...inorder(root.right)];
}

function postorder(root) {
if (!root) return [];
return [...postorder(root.left), ...postorder(root.right), root.val];
}

迭代版本

// 前序遍歷 (Pre-order)
function preorderIter(root) {
if (!root) return [];
const stack = [root], result = [];
while (stack.length > 0) {
const node = stack.pop();
result.push(node.val);
if (node.right) stack.push(node.right);
if (node.left) stack.push(node.left);
}
return result;
}

// 中序遍歷 (In-order)
function inorderIter(root) {
const stack = [], result = [];
let current = root;
while (current || stack.length > 0) {
while (current) {
stack.push(current);
current = current.left;
}
current = stack.pop();
result.push(current.val);
current = current.right;
}
return result;
}

// 後序遍歷 (Post-order)
function postorderIter(root) {
if (!root) return [];
const stack = [root], result = [];
while (stack.length > 0) {
const node = stack.pop();
result.push(node.val);
if (node.left) stack.push(node.left);
if (node.right) stack.push(node.right);
}
return result.reverse();
}

複雜度分析

  • 時間複雜度:O(n),每個節點僅訪問一次。
  • 空間複雜度:O(h),其中 h 為樹的高度。最壞情況 O(n),最佳情況(平衡樹) O(log n)。

2. 廣度優先搜尋(BFS, Breadth-First Search)

BFS 的思路是「逐層遍歷」,通常透過佇列 (Queue) 來實現。

JavaScript 實作

function bfs(root) {
if (!root) return [];
const queue = [root], result = [];
while (queue.length > 0) {
const node = queue.shift();
result.push(node.val);
if (node.left) queue.push(node.left);
if (node.right) queue.push(node.right);
}
return result;
}

複雜度分析

  • 時間複雜度:O(n),每個節點訪問一次。
  • 空間複雜度:O(w),其中 w 為樹的最大寬度。最壞情況 O(n)。

二元樹(Binary Tree)

二元樹是一種特殊的樹狀結構,其中每個節點最多只能有兩個子節點,分別稱為左子節點(Left Child)與右子節點(Right Child)。這也是面試中最常出現的樹類型之一。

二元樹的種類

  1. 滿二元樹(Full Binary Tree)
    每個節點要嘛沒有子節點,要嘛剛好有兩個子節點。
  2. 完全二元樹(Complete Binary Tree)
    除了最後一層外,其他層的節點都是滿的,最後一層的節點集中在左側。
  3. 完美二元樹(Perfect Binary Tree)
    一棵同時滿足「滿二元樹」與「完全二元樹」條件的二元樹,所有葉節點位於同一層。
  4. 二元搜尋樹(Binary Search Tree, BST)
    在二元樹的基礎上增加排序規則:
    • 左子節點的值 < 父節點
    • 右子節點的值 > 父節點
      這讓 BST 在搜尋、插入與刪除時的效率更高。

二元樹的應用

  • 搜尋與排序:BST 可在平均 O(log n) 的時間內完成搜尋。
  • 堆積樹(Heap):用於實作優先佇列(Priority Queue)。
  • 表達式樹(Expression Tree):常見於編譯器與運算解析。

範例程式碼(建構簡單的二元樹)

// 建立節點
const root = new TreeNode(1);
root.left = new TreeNode(2);
root.right = new TreeNode(3);
root.left.left = new TreeNode(4);
root.left.right = new TreeNode(5);

/*
樹的結構:
1
/ \
2 3
/ \
4 5
*/


經典題目:Validate Binary Search Tree(LeetCode 98)

題目說明:判斷給定的二元樹是否為有效的 BST。

核心思路:在遍歷過程中,為每個節點設定「有效值範圍」。若節點值超出範圍,則違反 BST 規則。

JavaScript 解法

/**
* @param {TreeNode} root
* @return {boolean}
*/
var isValidBST = function(root) {
function validate(node, min, max) {
if (!node) return true;
if ((min !== null && node.val <= min) || (max !== null && node.val >= max)) {
return false;
}
return validate(node.left, min, node.val) &&
validate(node.right, node.val, max);
}
return validate(root, null, null);
};

總結

  • DFS 適合需要完整遍歷樹結構或進行遞迴處理的情境。
  • BFS 適合需要按層級搜尋、找最短路徑或最淺解答的情境。
  • 時間複雜度:DFS 與 BFS 都是 O(n)。
  • 空間複雜度:DFS 為 O(h),BFS 為 O(w)。

👉 熟悉這些基本概念與程式碼實作,能幫助你在演算法面試中更快進入狀況,應對各種樹的題目。

留言
avatar-img
留言分享你的想法!
avatar-img
跨越國界的程式人生
2會員
35內容數
自學程式,現為網頁開發工程師,同時擔任線上課程講師,專注於幫助自學程式的開發者找到理想工作。熱愛技術與分享,致力於將複雜的概念轉化為實用知識,讓更多人踏入軟體開發的世界。
2025/07/29
什麼是雜湊表?—— 鍵值對的抽象資料型態 想像一下,你有一本非常厚的通訊錄。如果這本通訊錄是按照每個人的姓名首字母排序的,當你想找「王小明」的電話時,你可以迅速翻到「W」的開頭,然後快速找到他。雜湊表就
Thumbnail
2025/07/29
什麼是雜湊表?—— 鍵值對的抽象資料型態 想像一下,你有一本非常厚的通訊錄。如果這本通訊錄是按照每個人的姓名首字母排序的,當你想找「王小明」的電話時,你可以迅速翻到「W」的開頭,然後快速找到他。雜湊表就
Thumbnail
2025/07/22
如果你正在規劃出國工作,那麼今天的這篇文章,絕對能給你一些扎實的參考資訊。我們要來聊聊一個近年來在台灣人圈子裡越來越受歡迎的歐洲工作目的地——愛爾蘭!🇮🇪
Thumbnail
2025/07/22
如果你正在規劃出國工作,那麼今天的這篇文章,絕對能給你一些扎實的參考資訊。我們要來聊聊一個近年來在台灣人圈子裡越來越受歡迎的歐洲工作目的地——愛爾蘭!🇮🇪
Thumbnail
2025/07/22
在資料結構中,除了後進先出的 Stack,另一個常見且實用的就是 Queue(佇列)。它是許多系統背後默默運作的重要機制,例如排程器、印表機佇列、網路封包、事件處理機制等。 這篇筆記將帶你從零理解 Que
Thumbnail
2025/07/22
在資料結構中,除了後進先出的 Stack,另一個常見且實用的就是 Queue(佇列)。它是許多系統背後默默運作的重要機制,例如排程器、印表機佇列、網路封包、事件處理機制等。 這篇筆記將帶你從零理解 Que
Thumbnail
看更多
你可能也想看
Thumbnail
2025 vocus 推出最受矚目的活動之一——《開箱你的美好生活》,我們跟著創作者一起「開箱」各種故事、景點、餐廳、超值好物⋯⋯甚至那些讓人會心一笑的生活小廢物;這次活動不僅送出了許多獎勵,也反映了「內容有價」——創作不只是分享、紀錄,也能用各種不同形式變現、帶來實際收入。
Thumbnail
2025 vocus 推出最受矚目的活動之一——《開箱你的美好生活》,我們跟著創作者一起「開箱」各種故事、景點、餐廳、超值好物⋯⋯甚至那些讓人會心一笑的生活小廢物;這次活動不僅送出了許多獎勵,也反映了「內容有價」——創作不只是分享、紀錄,也能用各種不同形式變現、帶來實際收入。
Thumbnail
嗨!歡迎來到 vocus vocus 方格子是台灣最大的內容創作與知識變現平台,並且計畫持續拓展東南亞等等國際市場。我們致力於打造讓創作者能夠自由發表、累積影響力並獲得實質收益的創作生態圈!「創作至上」是我們的核心價值,我們致力於透過平台功能與服務,賦予創作者更多的可能。 vocus 平台匯聚了
Thumbnail
嗨!歡迎來到 vocus vocus 方格子是台灣最大的內容創作與知識變現平台,並且計畫持續拓展東南亞等等國際市場。我們致力於打造讓創作者能夠自由發表、累積影響力並獲得實質收益的創作生態圈!「創作至上」是我們的核心價值,我們致力於透過平台功能與服務,賦予創作者更多的可能。 vocus 平台匯聚了
Thumbnail
給定一個輸入陣列,每一個tuple代表節點之間了從屬關係。 請從從屬關係重建整顆二元樹,並且返回整顆二元樹的根結點。
Thumbnail
給定一個輸入陣列,每一個tuple代表節點之間了從屬關係。 請從從屬關係重建整顆二元樹,並且返回整顆二元樹的根結點。
Thumbnail
題目給定一個布林代數的二元樹,要求我們計算最後的結果。 葉子節點都是真假值 非葉子節點都是布林運算子
Thumbnail
題目給定一個布林代數的二元樹,要求我們計算最後的結果。 葉子節點都是真假值 非葉子節點都是布林運算子
Thumbnail
題目敘述 題目會給定一顆二元樹的根結點, 要求我們在指定的層樹d,插入新的一層,節點值為v。 原本的左、右子樹,就成為新的那一層的左子樹、右子樹。 題目的原文敘述 測試範例 Example 1: Input: root = [4,2,6,3,1,5], val = 1, depth =
Thumbnail
題目敘述 題目會給定一顆二元樹的根結點, 要求我們在指定的層樹d,插入新的一層,節點值為v。 原本的左、右子樹,就成為新的那一層的左子樹、右子樹。 題目的原文敘述 測試範例 Example 1: Input: root = [4,2,6,3,1,5], val = 1, depth =
Thumbnail
這篇文章,會帶著大家複習以前學過的二元搜尋樹(Binary Search Tree)框架, 並且以二分搜尋樹的概念與定義為核心, 貫穿一些相關聯的題目,透過框架複現來幫助讀者理解這個演算法框架。 二元搜尋樹(Binary Search Tree)的定義
Thumbnail
這篇文章,會帶著大家複習以前學過的二元搜尋樹(Binary Search Tree)框架, 並且以二分搜尋樹的概念與定義為核心, 貫穿一些相關聯的題目,透過框架複現來幫助讀者理解這個演算法框架。 二元搜尋樹(Binary Search Tree)的定義
Thumbnail
題目敘述 題目會給定一棵二元樹的根結點,要求我們判定這是否為一顆合法的奇偶二元樹? 奇偶二元樹的定義: 從上到下依序是第0層、第一層、...、第n層 偶數層裡面的節點值都必須是奇數,而且由左到右嚴格遞增。 奇數層裡面的節點值都必須是偶數,而且由左到右嚴格遞減。 題目的原文敘述 測試
Thumbnail
題目敘述 題目會給定一棵二元樹的根結點,要求我們判定這是否為一顆合法的奇偶二元樹? 奇偶二元樹的定義: 從上到下依序是第0層、第一層、...、第n層 偶數層裡面的節點值都必須是奇數,而且由左到右嚴格遞增。 奇數層裡面的節點值都必須是偶數,而且由左到右嚴格遞減。 題目的原文敘述 測試
Thumbnail
題目敘述 題目會給定一棵二元樹的根結點,要求我們找出這棵二元樹最後一層最左邊的值。 題目的原文敘述 測試範例 Example 1: Input: root = [2,1,3] Output: 1 Example 2: Input: root = [1,2,3,4,null,5,6
Thumbnail
題目敘述 題目會給定一棵二元樹的根結點,要求我們找出這棵二元樹最後一層最左邊的值。 題目的原文敘述 測試範例 Example 1: Input: root = [2,1,3] Output: 1 Example 2: Input: root = [1,2,3,4,null,5,6
Thumbnail
題目敘述 題目已經給定一個Trie前綴樹的類別和相關的函式介面interface, 要求我們把功能實作出來。 Trie() 建構子,初始化一個空的Trie。 void insert(String word) 插入一個新的單字word到Trie裡面。 boolean search(Strin
Thumbnail
題目敘述 題目已經給定一個Trie前綴樹的類別和相關的函式介面interface, 要求我們把功能實作出來。 Trie() 建構子,初始化一個空的Trie。 void insert(String word) 插入一個新的單字word到Trie裡面。 boolean search(Strin
Thumbnail
題目敘述 題目會給定兩顆二元樹的根結點,要求我們判斷這兩顆二元樹是否為 葉子相似樹? 葉子相似樹的定義 兩顆二元樹,從左到右看的葉子結點的序列完全相同。 例如下圖中的這兩顆二元樹,從左到右看的葉子結點的序列 = [6, 7, 4, 9, 8] 完全相同。 題目的原文敘述 測試範例
Thumbnail
題目敘述 題目會給定兩顆二元樹的根結點,要求我們判斷這兩顆二元樹是否為 葉子相似樹? 葉子相似樹的定義 兩顆二元樹,從左到右看的葉子結點的序列完全相同。 例如下圖中的這兩顆二元樹,從左到右看的葉子結點的序列 = [6, 7, 4, 9, 8] 完全相同。 題目的原文敘述 測試範例
Thumbnail
題目敘述 題目會給我們一顆二元樹的根結點,請我們列出每一層最右邊的節點值,以陣列的形式返回答案。 題目的原文敘述 測試範例 Example 1: Input: root = [1,2,3,null,5,null,4] Output: [1,3,4] 每一層最右邊的節點值分別是1, 3,
Thumbnail
題目敘述 題目會給我們一顆二元樹的根結點,請我們列出每一層最右邊的節點值,以陣列的形式返回答案。 題目的原文敘述 測試範例 Example 1: Input: root = [1,2,3,null,5,null,4] Output: [1,3,4] 每一層最右邊的節點值分別是1, 3,
Thumbnail
題目會給定一顆二元樹的根結點,要求我們驗證這一顆樹是否為合法的二元搜索樹, 也就是所謂的Binary search tree, aka BST?
Thumbnail
題目會給定一顆二元樹的根結點,要求我們驗證這一顆樹是否為合法的二元搜索樹, 也就是所謂的Binary search tree, aka BST?
追蹤感興趣的內容從 Google News 追蹤更多 vocus 的最新精選內容追蹤 Google News