電腦的「族譜」:為什麼「樹」是資訊世界的完美金字塔?

更新 發佈閱讀 15 分鐘

在過去的旅程中,我們一直在「一維」的世界中戰鬥。我們的主角是「陣列」(Array),它像是一排座位「緊密相連」的電影院,優點是你能「跳」到任何座位,缺點是若有人想「插入」到中間,全排的人都得尷尬地挪動。我們的另一個主角是「鏈結串列」(Linked List),它像是「隨機散落」各處、僅靠「鎖鏈」相連的島嶼,插入新島嶼輕而易舉,但要「找到」某座島,卻是一場「逐島遠征」的惡夢。這兩種「線性」結構,都無法同時滿足我們對「快速搜尋」與「快速增刪」的貪婪。

今天,我們將迎來一場維度的革命。我們將從「線」的思考,躍升到「面」與「空間」的思考。這篇文章我們介紹的全新武器,是「樹 (Tree)」。這不是你家後院的樹,而是一種「概念」的樹。它的本質,是關於「層次 (Hierarchy)」與「關係 (Relationship)」。它不再是 1 號後面跟著 2 號、2 號後面跟著 3 號的單一路徑;它是一個 1 號「分岔」出 2 號和 3 號,而 2 號又「再分岔」出 4 號和 5 號的、一個擁有無限可能性的「分岔結構」。

這種結構,其實深深地根植於我們的直覺中。你電腦中的「資料夾」就是一種樹狀結構:一個資料夾可以包含好幾個「子資料夾」,而子資料夾又可以再包含下去。而這堂課的教授給了我們一個最完美的比喻:族譜 (Family Tree)。族譜就是一種樹狀結構,它完美地展示了「一個祖先,開枝散葉」的層級關係。這個比喻,就是我們理解這項偉大發明的鑰匙。

揭開「樹」的神秘面紗:電腦如何定義「關係」?

當電腦科學家談論「樹」時,他們使用的是一套從「族譜」借來的語言。在族譜中,每個人都是一個「成員」;在電腦的樹中,每個成員被稱為一個「節點 (Node)」。這個節點可以儲存任何東西:一個數字、一個名字、一筆學生資料。接著,最重要的定義來了:整棵樹的「最高祖先」,那個沒有「父母」的節點,被稱為「根 (Root)」。從「根」開始,整棵樹向下「分岔」生長。

族譜中的「親子關係」也原封不動地被搬了過來。如果節點 A「分岔」出節點 B,我們就稱 A 是 B 的「父節點 (Parent)」,而 B 是 A 的「子節點 (Child)」。一個父親可以有多個孩子,這就構成了「分支」。所有在你「上方」的節點(父母、父母的父母...)統稱為你的「祖先 (Ancestor)」;所有在你「下方」的節點(孩子、孩子的孩子...)統稱為你的「子孫 (Descendant)」。

最後,族譜中有「還沒有生小孩」的最新一代,在樹中,這些「沒有子節點」的節點被稱為「樹葉 (Leaf)」。而那些「不是樹葉」的節點(即,它們至少有一個孩子),則被稱為「內部節點 (Internal Node)」。透過這套術語,電腦科學家得以精確地描述一個龐大、複雜的層級結構中,任何一個節點的確切位置和它的所有「親戚關係」。

樹的「二孩政策」:為什麼「二元樹」是天選之子?

族譜(或你電腦的資料夾)可以很複雜,一個「父親」節點,可能「分岔」出十幾個「孩子」節點。這對電腦來說,在實作和分析上都過於混亂。因此,電腦科學家們很快就聚焦於一種「特化」的、更簡潔的樹,它被稱為「二元樹 (Binary Tree)」。

「二元樹」的規則極其嚴苛,但也極其優雅:「每一個節點,最多只能有『兩個』子節點。」這就是樹的「二孩政策」。這兩個孩子節點,甚至還有固定的「名份」:一個被稱為「左子節點 (Left Child)」,另一個被稱為「右子節點 (Right Child)」。這不僅僅是個名字,它代表了兩個截然不同的「方向」或「選擇」。

為什麼這個「二孩政策」如此重要?因為「二」是電腦世界中最神奇的數字。「二元」代表了「是/否」、「真/假」、「0/1」... 它代表了「決策 (Decision)」。一個二元樹節點,就像是一個「岔路口」,它只提供你「往左」或「往右」兩種選擇。這種簡潔的二元性,讓演算法的設計與分析變得無比清晰,也讓我們即將看到的「搜尋」魔法成為可能。

聖杯的化身:二元搜尋樹 (BST) 的「黃金法則」

現在,我們終於要組裝我們的「終極武器」了。光有「二元樹」的「形狀」還不夠,那只是一個最多有兩條分岔的族譜。我們要賦予它「靈魂」和「秩序」,讓它從一個單純的「結構」,進化成一把強大的「搜尋」利器。這,就是「二元搜尋樹 (Binary Search Tree, BST)」。

BST 的靈魂,就是一條必須被「整棵樹」上上下下、所有節點都嚴格遵守的「黃金法則 (BST Property)」[00:13:30]。這條法則,正是這堂課教授所強調的核心中的核心。它規定:對於樹中的「任何一個」節點 X:

  1. 其「左子樹 (Left Subtree)」中「所有」節點的值,都必須小於 X 的值。
  2. 其「右子樹 (Right Subtree)」中「所有」節點的值,都必須大於 X 的值。

這條法則,為混亂的「分岔」帶來了絕對的「秩序」。它就像是在族譜中規定:「所有『左邊』生的孩子,體重都必須比我輕;所有『右邊』生的孩子,體重都必須比我重。」這聽起來很荒謬,但在資訊世界中,這條法則創造了奇蹟。

我們來看看這條法則如何「蓋」出一棵樹。假設我們要依序插入 15, 6, 18, 7。第一筆資料 15 成為「根」。下一筆 6 進來,6 比 15 小,所以它必須被放到 15 的「左邊」。下一筆 18 進來,18 比 15 大,所以它必須被放到 15 的「右邊」。下一筆 7 進來,它比 15 小(往左走,來到 6),但 7 比 6 大,所以它必須被放到 6 的「右邊」。這棵樹是「自動」生長出來的,而它的形狀,完全由這條「黃金法則」所決定。

O(log n) 的閃電搜尋:樹如何「自動」玩猜數字遊戲?

這條「黃金法則」到底帶來什麼好處?它讓我們實現了夢寐以求的「O(log n) 閃電搜尋」!想像一下,你要在這棵樹裡尋找 7。你從「根」15 開始。7 比 15 小嗎?是。根據「黃金法則」,7 如果存在,它「必定」在左子樹。於是,你「往左走」,並且「立刻拋棄」了 15 右邊那整片(可能包含數百萬個節點的)右子樹。

你來到 6。7 比 6 小嗎?否。它比 6 大。根據「黃金法則」,7 如果存在,它「必定」在 6 的右子樹。於是你「往右走」,又「拋棄」了 6 的左子樹(如果有的話)。你來到了 7。7 等於 7 嗎?是!你找到了!這個過程,是不是很眼熟? 這,就是「二分搜尋法」(Binary Search)!

在「排序陣列」中,我們是「計算」出中間位置;在「二元搜尋樹」中,我們是「跟隨」著結構,從根節點開始,每一次「往左」或「往右」的決策,都等同於「拋棄」了樹中「將近一半」的資料。如果這棵樹長得「又寬又矮」(我們稱之為「平衡」),它的「高度 (Height)」h 就會是 O(log n)。而你的搜尋時間,就等於你最多需要往下走幾層,也就是 O(h),即 O(log n)。我們在一個「動態」的結構上,重現了「二分搜尋」的威力!

「搜尋」即「新增」:樹的優雅生長

如果說 O(log n) 的搜尋已經夠驚人了,那麼 BST 的「新增 (Insert)」操作,更是將這份優雅推向了極致。「新增」一個節點的演算法,和「搜尋」的演算法,是「一模一樣」的! 唯一的差別,只在於「找不到」時的反應。

假設我們要新增 13 到我們 (15, 6, 18, 7) 的樹中。我們「假裝」要「搜尋」13。從根 15 開始:13 < 15,往左走。來到 6:13 > 6,往右走。來到 7:13 > 7,往右走。來到 7 的右子節點,你發現... 它是個「空位」(NULL)![00:29:43] 在「搜尋」模式下,這代表「查無此資料」。但在「新增」模式下,這代表「太好了!這就是 13 該待的地方!」

你不需要移動任何其他節點。你不需要像「陣列」一樣搞得人仰馬翻。你只需要在那個「空位」上,接上 13 這個「新樹葉」即可。這個操作,同樣是從根節點往下走一遍,直到找到空位為止,所以它的效率,也和樹的高度 h 成正比,達到了 O(h)。如果樹是「平衡」的,這就是一次 O(log n) 的新增!我們似乎已經找到了那個「搜尋」和「新增」都是 O(log n) 的夢幻結構!

完美金字塔的「阿基里斯之踵」

在我們開香檳慶祝之前,最關鍵的「但是...」來了。我們所有的美好想像,都建立在一個「如果」之上:「如果,這棵樹長得『又寬又矮』、長得像一座『平衡』的金字塔。」萬一,它不這樣長呢?

最壞情況 (Worst Case):如果,我們不是插入 15, 6, 18 這種「隨機」的順序,而是依序插入「已經排好序」的資料,例如:1, 2, 3, 4, 5... 會發生什麼事?1 成為根。2 進來,2 > 1,往右走。3 進來,3 > 1 往右,3 > 2 往右。4 進來,4 > 1 往右,4 > 2 往右,4 > 3 往右...

這棵樹,完全沒有「左子樹」!它沒有長成一座「金字塔」,而是長成了一根「傾斜的竹竿」。這就是「退化樹 (Degenerate Tree)」。它在結構上,根本就是我們一開始想逃離的「鏈結串列」!在這根「竹竿」上,樹的高度 h 不再是 O(log n),而是 O(n)。這意味著,你所有的 Search 和 Insert 操作,全部都會退化成 O(n) 的「線性爬行」。

這就是「二元搜尋樹」的阿基里斯之踵:它的效率,完全取決於「資料插入的順序」。如果運氣好,它就是 O(log n) 的神;如果運氣不好(例如資料剛好是排序過的),它就退化成 O(n) 的蟲。這種「不穩定」的效能,對於需要「保證」效率的真實世界系統(例如資料庫或作業系統)來說,是不可接受的。

最棘手的難題:如何在樹上「移除」一個節點?

BST 的脆弱性,在「刪除 (Delete)」操作上,更是展露無遺。Delete 是 BST 中最複雜的操作,因為你必須在「移除」一個節點後,依然「維持」那條神聖的「黃金法則」。教授將其分為三種情況:

情況一:刪除「樹葉」。這是最簡單的。樹葉沒有孩子,你直接「剪掉」它(把它從父節點的指標中移除)就好,不會影響任何人。

情況二:刪除「只有一個孩子」的節點。這也還算簡單。你只需要「繞過 (Bypass)」這個節點。你讓它的「父節點」,直接「跳過」它,去「牽住」它的「子節點」(也就是讓「阿公」直接牽「孫子」)。這個被跳過的節點,就自然地被「孤立」並移除了。

情況三:刪除「有兩個孩子」的節點。這,就是真正的難題。這個節點是「承上啟下」的關鍵樞紐,你不能隨便刪除它。標準的、優雅的解法:你必須找到一個「繼承者 (Successor)」。這個繼承者,就是它「右子樹中,最小的那個節點」(演算法是:往右走一步,然後一路向左衝到底)。

你找到這個「繼承者」後(例如 S),你並「不是」把它移上來,而是更聰明:你只是把 S 的「資料」,「複製」到你要刪除的那個節點 X 上,覆蓋掉 X 的舊資料。然後,你再「回頭去刪除那個原始的 S 節點」。因為 S 是「一路向左衝到底」找到的,它自己最多只會有一個「右孩子」(不可能有左孩子),所以刪除 S 的問題,就自動「降級」成了簡單的「情況一」或「情況二」。這個「狸貓換太子」的精妙手法,在不破壞結構的前提下,完美地維護了「黃金法則」。

樹的「三種」觀看之道:藏在順序裡的秘密

我們學會了如何「搜尋」特定節點,但如果我們想「拜訪 (Visit)」這棵樹上的「每一個」節點呢?這不像「陣列」可以從頭走到尾。樹是分岔的,你該「先往左,還是先往右?」這就催生了三種「遍歷 (Traversal)」演算法,它們唯一的區別,在於「你什麼時候拜訪『自己』(根節點)」:

前序 (Pre-Order):「自己」 -> 左 -> 右。這是一種「先處理長官,再處理下屬」的模式 (Root -> Left -> Right)。它常用於「複製」一棵樹,因為你先複製了根節點,才能把左右子樹接上去。

後序 (Post-Order):左 -> 右 -> 「自己」。這是一種「先處理完下屬,再回報給長官」的模式 (Left -> Right -> Root)。它最經典的應用是「刪除」整棵樹。你必須先刪除左右孩子,才能回過頭來刪除你自己。

中序 (In-Order):左 -> 「自己」 -> 右。這,就是 BST 中最神奇的遍歷。當你嚴格遵守 (Left -> Root -> Right) 的順序去拜訪這棵「二元搜尋樹」,你猜會發生什麼?你會「完美地」按照「由小到大」的順序,讀出樹中的所有資料! 這個「中序遍歷」,等於是「免費」贈送了你一個「排序」功能。它深刻地揭示了,BST 的「結構」本身,就已經「儲存」了資料的「順序」。

不穩定的天才,與「平衡」的永恆追求

這堂課,我們從「族譜」出發,打造出了「二元搜尋樹」這個「不穩定的天才」。它基於一條簡單的「黃金法則」,就奇蹟似地將「二分搜尋」的 O(log n) 威力,賦予了一個「動態」的結構。我們學會了它優雅的「搜尋即新增」邏輯,也拆解了它「狸貓換太子」的複雜刪除術,更在中序遍歷中,窺見了它「結構即順序」的內在美。

然而,這個天才的「不穩定性」是它的致命傷。那根 O(n) 的「退化竹竿」,像是一把達摩克利斯之劍,懸在所有 BST 的頭上,讓我們無法在真實世界中,放心地依賴它。這堂課在 Skip List(隨機平衡)和 BST(不保證平衡)的對比中結束,並為我們指出了下一條、也是最關鍵的道路。

我們的 O(log n) 聖杯近在咫尺。我們已經擁有了 BST 的「黃金法則」。現在,我們只剩下最後一里路:我們需要一個「機制」,一個能在「新增」和「刪除」之後,自動「檢查」這棵樹,如果它開始「傾斜」,就自動「扶正」它的機制。這,就是「自平衡二元搜尋樹 (Self-Balancing BST)」的世界。諸如「AVL 樹」或「紅黑樹」這些聽起來很酷的名字,它們的偉大,不在於發明了新法則,而在於它們發明了「維護法則」的紀律。這,將是我們下一趟旅程的終極目標。


留言
avatar-img
留言分享你的想法!
avatar-img
政大雜學筆記
0會員
26內容數
我在政大的一些紀錄
政大雜學筆記的其他內容
2025/11/05
探索電腦科學中「順序」的核心挑戰,從「堆疊 (Stack)」和「佇列 (Queue)」這兩種基礎的 FIFO/LIFO 模型,到結合排序陣列與鏈結串列優勢的「跳躍串列 (Skip List)」。本文將以生動的例子,解析資料結構如何支撐數位生活的運作,並引導讀者理解「機率性」資料結構的威力。
2025/11/05
探索電腦科學中「順序」的核心挑戰,從「堆疊 (Stack)」和「佇列 (Queue)」這兩種基礎的 FIFO/LIFO 模型,到結合排序陣列與鏈結串列優勢的「跳躍串列 (Skip List)」。本文將以生動的例子,解析資料結構如何支撐數位生活的運作,並引導讀者理解「機率性」資料結構的威力。
2025/11/05
本文深入探討了電腦科學中兩種核心資料結構:陣列(Array)與鏈結串列(Linked List),並從大O符號(Big-O Notation)的角度分析其效率。
2025/11/05
本文深入探討了電腦科學中兩種核心資料結構:陣列(Array)與鏈結串列(Linked List),並從大O符號(Big-O Notation)的角度分析其效率。
2025/11/05
從混亂的房間到 Google 的搜尋引擎,本文透過經營圖書館的比喻,深入淺出地介紹了資料結構的核心概念:資料儲存(資料結構)的選擇,如何在「新增」與「搜尋」之間取得效率上的平衡。
2025/11/05
從混亂的房間到 Google 的搜尋引擎,本文透過經營圖書館的比喻,深入淺出地介紹了資料結構的核心概念:資料儲存(資料結構)的選擇,如何在「新增」與「搜尋」之間取得效率上的平衡。
看更多
你可能也想看
Thumbnail
去歐洲真的是又興奮又緊張。網路上常說歐洲治安不好,行前說明會時領隊也提醒:「不要背後背包,隨身物要放在前面比較安全!」 但出國玩總是想打扮得美美的啊~而且隨身總得帶些實用小物:雨傘、濕紙巾、小瓶水、萬用藥膏……體積雖小,但零零總總裝起來也不少。我在蝦皮購買了這4樣超實用旅遊好物!減緩我的焦慮感。
Thumbnail
去歐洲真的是又興奮又緊張。網路上常說歐洲治安不好,行前說明會時領隊也提醒:「不要背後背包,隨身物要放在前面比較安全!」 但出國玩總是想打扮得美美的啊~而且隨身總得帶些實用小物:雨傘、濕紙巾、小瓶水、萬用藥膏……體積雖小,但零零總總裝起來也不少。我在蝦皮購買了這4樣超實用旅遊好物!減緩我的焦慮感。
Thumbnail
開箱 3 套深受 0-6 歲寶寶喜愛的互動式童書,包含 Bizzy Bear 推拉書、小小音樂大師有聲書、Poke A Dot 泡泡書,有效提升寶寶閱讀興趣與親子共讀時光。搭配蝦皮雙 11 購物攻略,教你如何鎖定免運、折價券、高額回饋,並透過蝦皮分潤計畫,將日常購物開銷轉化為穩定育兒基金,聰明消費。
Thumbnail
開箱 3 套深受 0-6 歲寶寶喜愛的互動式童書,包含 Bizzy Bear 推拉書、小小音樂大師有聲書、Poke A Dot 泡泡書,有效提升寶寶閱讀興趣與親子共讀時光。搭配蝦皮雙 11 購物攻略,教你如何鎖定免運、折價券、高額回饋,並透過蝦皮分潤計畫,將日常購物開銷轉化為穩定育兒基金,聰明消費。
Thumbnail
軟體工程師職涯升級計畫啟動!本文深入探討陣列與串列這兩種基礎資料結構,比較其特性、優缺點與常見操作,並輔以JavaScript範例程式碼及時間複雜度分析,幫助讀者學習如何根據不同情境選擇合適的資料結構,寫出更高效的程式。
Thumbnail
軟體工程師職涯升級計畫啟動!本文深入探討陣列與串列這兩種基礎資料結構,比較其特性、優缺點與常見操作,並輔以JavaScript範例程式碼及時間複雜度分析,幫助讀者學習如何根據不同情境選擇合適的資料結構,寫出更高效的程式。
Thumbnail
假設設計以下系統: 「政府可控制後端系統」  「商家可控制前端系統」 「客戶可互動介面系統」
Thumbnail
假設設計以下系統: 「政府可控制後端系統」  「商家可控制前端系統」 「客戶可互動介面系統」
Thumbnail
原型與基因組有其心理及生理能量運作模式,有啟動的指令與記憶體的資料,隨著輸入資訊不同,演算出不一樣的行為結果,而其結果又可因原型及基因組的封裝記憶體限制,使其相關輸出內容維持在一定範圍當中。
Thumbnail
原型與基因組有其心理及生理能量運作模式,有啟動的指令與記憶體的資料,隨著輸入資訊不同,演算出不一樣的行為結果,而其結果又可因原型及基因組的封裝記憶體限制,使其相關輸出內容維持在一定範圍當中。
Thumbnail
肖恩·克納特於實驗中意外觸發異常能量,導致空間結構扭曲並召喚出不明生物體。此事件涉及克納特的背景、魔法理論研究、實驗過程、召喚體特性以及後續處理等,突顯了能量來源、魔法理論與現實交疊以及不明生物體來源等謎團。
Thumbnail
肖恩·克納特於實驗中意外觸發異常能量,導致空間結構扭曲並召喚出不明生物體。此事件涉及克納特的背景、魔法理論研究、實驗過程、召喚體特性以及後續處理等,突顯了能量來源、魔法理論與現實交疊以及不明生物體來源等謎團。
Thumbnail
第 1 題 題目 設有一三維陣列(three dimensional matrix) A[1...u₁, 1...u₂, 1...u₃],請問其中一元素(element)A[i,j,k] 之儲存位置為何?其中 1 ≤ i ≤ u₁,1 ≤ j ≤ u₂,1 ≤ k ≤ u₃,請列出推導過程。
Thumbnail
第 1 題 題目 設有一三維陣列(three dimensional matrix) A[1...u₁, 1...u₂, 1...u₃],請問其中一元素(element)A[i,j,k] 之儲存位置為何?其中 1 ≤ i ≤ u₁,1 ≤ j ≤ u₂,1 ≤ k ≤ u₃,請列出推導過程。
追蹤感興趣的內容從 Google News 追蹤更多 vocus 的最新精選內容追蹤 Google News