在電腦科學中，樹是一種抽象資料型別（ADT）或是實作這種抽象資料型別的資料結構，用來模擬具有樹狀結構性質的資料集合。它是由 n（n0）個有限節點組成一個具有層次關係的集合。把它叫做 樹 是因為它看起來像一棵倒掛的樹，也就是說它是根朝上，而葉朝下的。它具有以下的特點： 每個節點都只有有限個子節點或無子節點； 沒有父節點的節點稱為根節點； 每一個非根節點有且只有一個父節點； 除了根節點外，每個子節點可以分為多個不相交的子樹； 樹裡面沒有環路 cycle 術語 節點的度：一個節點含有的子樹的個數稱為該節點的度； 樹的度：一棵樹中，最大的節點度稱為樹的度； 葉節點或終端節點：度為零的節點； 非終端節點或分支節點：度不為零的節點； 父親節點或父節點：若一個節點含有子節點，則這個節點稱為其子節點的父節點； 孩子節點或子節點：一個節點含有的子樹的根節點稱為該節點的子節點； 兄弟節點：具有相同父節點的節點互稱為兄弟節點； 節點的層次：從根開始定義起，根為第 1 層，根的子節點為第 2 層，以此類推； 深度：對於任意節點 nn 的深度為從根到 n 的唯一路徑長，根的深度為 0； 高度：對於任意節點 nn 的高度為從 n 到一片樹葉的最長路徑長，所有樹葉的高度為 0； 堂兄弟節點：父節點在同一層的節點互為堂兄弟； 節點的祖先：從根到該節點所經分支上的所有節點； 子孫：以某節點為根的子樹中任一節點都稱為該節點的子孫。 森林：由 m（m0）棵互不相交的樹的集合稱為森林； 樹的種類 有序 無序： 無序樹：樹中任意節點的子節點之間沒有順序關係，這種樹稱為無序樹，也稱為自由樹。 有序樹 搜尋樹 查詢樹：樹中任意節點的子節點之間有順序關係，這種樹稱為有序樹。即樹的所有節點按照一定的順序排列，這樣進行插入、刪除、查詢時效率就會非常高 平衡 不平衡： 平衡樹 絕對平衡樹：所有葉節點在同一層 非絕對平衡樹 不平衡樹 節點的分叉情況： 等叉樹：是每個節點的鍵值個數都相同、子節點個數也都相同 二叉樹：每個節點最多含有兩個子樹的樹稱為二叉樹； 完全二叉樹：對於一棵二叉樹，假設其深度為 d（d1）。除了第 d 層外，其它各層的節點數目均已達最大值，且第 d 層所有節點從左向右連續地緊密排列，這樣的二叉樹被稱為完全二叉樹； 滿二叉樹：所有葉節點都在最底層的完全二叉樹； 平衡二叉樹（AVL 樹）：當且僅當任何節點的兩棵子樹的高度差不大於 1 的二叉樹； 排序二叉樹：也稱二叉查詢樹、二叉搜尋樹、有序二叉樹； 霍夫曼樹：帶權路徑最短的二叉樹稱為哈夫曼樹或最優二叉樹； 不等叉樹：每個節點的鍵值個數不一定相同、子節點個數也不一定相同 B 樹：對不等叉樹的節點鍵值數和插入、刪除邏輯新增一些特殊的要求，使其能達到絕對平衡的效果。B 樹全稱 Balance Tree。如果某個 B 樹上所有節點的分叉數最大值是 m，則把這個 B 數叫做 m 階 B 樹。 儲存 父節點表示法 儲存結構 樹節點的定義 define MAX_TREE_SIZE 100 typedef struct TElemType data int parent 父節點位置域 PTNode typedef struct PTNode nodes MAX_TREE_SIZE int n 節點數 PTree 基本操作 設已有鏈佇列型別 LinkQueue 的定義及基本操作（參見佇列）。 構造空樹 清空或銷燬一個樹也是同樣的操作 void ClearTree PTree T Tn 0 構造樹 void CreateTree PTree T LinkQueue q QElemType pqq int i1jl char c MAX_TREE_SIZE 臨時存放孩子節點陣列 InitQueue q 初始化佇列 printf 請輸入根節點 字元型，空格為空 scanf ccTnodes 0data 根節點序號為 0，c 吃掉回車符 if Tnodes 0dataNil 非空樹 Tnodes 0parent1 根節點無父節點 qqnameTnodes 0data qqnum0 EnQueue qqq 入隊此節點 while iMAX_TREE_SIZEQueueEmpty q 陣列未滿且隊不空 DeQueue qqq 節點加入佇列 printf 請按長幼順序輸入節點 c 的所有孩子qqname gets c lstrlen c for j0jlj Tnodes idatac j Tnodes iparentqqnum pnamec j pnumi EnQueue qp 入隊此節點 i if iMAX_TREE_SIZE printf 節點數超過陣列容量 n exit OVERFLOW Tni else Tn0 判斷樹是否為空 Status TreeEmpty PTree T 初始條件：樹 T 存在。操作結果：若 T 為空樹，則返回 TRUE，否則返回 FALSE return Tn0 獲取樹的深度 int TreeDepth PTree T 初始條件：樹 T 存在。操作結果：返回 T 的深度 int kmdefmax0 for k0kTnk def1 初始化本節點的深度 mTnodes kparent while m1 mTnodes mparent def if maxdef maxdef return max 最大深度 獲取根節點 TElemType Root PTree T 初始條件：樹 T 存在。操作結果：返回 T 的根 int i for i0iTni if Tnodes iparent0 return Tnodes idata return Nil 獲取第 i 個節點的值 TElemType Value PTree Tint i 初始條件：樹 T 存在，i 是樹 T 中節點的序號。操作結果：返回第 i 個節點的值 if iTn return Tnodes idata else return Nil 改變節點的值 Status Assign PTree TTElemType cur_eTElemType value 初始條件：樹 T 存在，cur_e 是樹 T 中節點的值。操作結果：改 cur_e 為 value int j for j0jTnj if Tnodes jdatacur_e Tnodes jdatavalue return OK return ERROR 獲取節點的父節點 TElemType Parent PTree TTElemType cur_e 初始條件：樹 T 存在，cur_e 是 T 中某個節點 操作結果：若 cur_e 是 T 的非根節點，則返回它的父節點，否則函式值為＂空＂ int j for j1jTnj 根節點序號為 0 if Tnodes jdatacur_e return Tnodes Tnodes jparentdata return Nil 獲取節點的最左孩子節點 TElemType LeftChild PTree TTElemType cur_e 初始條件：樹 T 存在，cur_e 是 T 中某個節點 操作結果：若 cur_e 是 T 的非葉子節點，則返回它的最左孩子，否則返回＂空＂ int ij for i0iTni if Tnodes idatacur_e 找到 cur_e，其序號為 i break for ji1jTnj 根據樹的建構函式，孩子的序號＞其父節點的序號 if Tnodes jparenti 根據樹的建構函式，最左孩子 長子 的序號＜其它孩子的序號 return Tnodes jdata return Nil 獲取節點的右兄弟節點 TElemType RightSibling PTree TTElemType cur_e 初始條件：樹 T 存在，cur_e 是 T 中某個節點 操作結果：若 cur_e 有右 下一個 兄弟，則返回它的右兄弟，否則返回＂空＂ int i for i0iTni if Tnodes idatacur_e 找到 cur_e，其序號為 i break if Tnodes i1parentTnodes iparent 根據樹的建構函式，若 cur_e 有右兄弟的話則右兄弟緊接其後 return Tnodes i1data return Nil 輸出樹 void Print PTree T 輸出樹 T。加 int i printf 節點個數 dnTn printf 節點 父節點 n for i0iTni printf cValue Ti 節點 if Tnodes iparent0 有父節點 printf cValue TTnodes iparent 父節點 printf n 向樹中插入另一棵樹 Status InsertChild PTree TTElemType pint iPTree c 初始條件：樹 T 存在，p 是 T 中某個節點，1ip 所指節點的度 1，非空樹 c 與 T 不相交 操作結果：插入 c 為 T 中 p 節點的第 i 棵子樹 int jklf1n0 設交換標誌 f 的初值為 1，p 的孩子數 n 的初值為 0 PTNode t if TreeEmpty T T 不空 for j0jTnj 在 T 中找 p 的序號 if Tnodes jdatap p 的序號為 j break lj1 如果 c 是 p 的第 1 棵子樹，則插在 j1 處 if i1 c 不是 p 的第 1 棵子樹 for kj1kTnk 從 j1 開始找 p 的前 i1 個孩子 if Tnodes kparentj 當前節點是 p 的孩子 n 孩子數加 1 if ni1 找到 p 的第 i1 個孩子，其序號為 k1 break lk1 c 插在 k1 處 p 的序號為 j，c 插在 l 處 if lTn 插入點 l 不在最後 for kTn1klk 依次將序號 l 以後的節點向後移 cn 個位置 Tnodes kcnTnodes k if Tnodes kparentl Tnodes kcnparentcn for k0kcnk Tnodes lkdatacnodes kdata 依次將樹 c 的所有節點插於此處 Tnodes lkparentcnodes kparentl Tnodes lparentj 樹 c 的根節點的父節點為 p Tncn 樹 T 的節點數加 cn 個 while f 從插入點之後，將節點仍按層序排列 f0 交換標誌置 0 for jljTn1j if Tnodes jparentTnodes j1parent 如果節點 j 的父節點排在節點 j1 的父節點之後（樹沒有按層序排列），交換兩節點 tTnodes j Tnodes jTnodes j1 Tnodes j1t f1 交換標誌置 1 for kjkTnk 改變父節點序號 if Tnodes kparentj Tnodes kparent 父節點序號改為 j1 else if Tnodes kparentj1 Tnodes kparent 父節點序號改為 j return OK else 樹 T 不存在 return ERROR 刪除子樹 Status deleted MAX_TREE_SIZE1 刪除標誌陣列 全域性量 void DeleteChild PTree TTElemType pint i 初始條件：樹 T 存在，p 是 T 中某個節點，1ip 所指節點的度 操作結果：刪除 T 中節點 p 的第 i 棵子樹 int jkn0 LinkQueue q QElemType pqqq for j0jTnj deleted j0 置初值為 0 不刪除標記 pqnamea 此成員不用 InitQueue q 初始化佇列 for j0jTnj if Tnodes jdatap break j 為節點 p 的序號 for kj1kTnk if Tnodes kparentj n if ni break k 為 p 的第 i 棵子樹節點的序號 if kTn p 的第 i 棵子樹節點存在 n0 pqnumk deleted k1 置刪除標記 n EnQueue qpq while QueueEmpty q DeQueue qqq for jqqnum1jTnj if Tnodes jparentqqnum pqnumj deleted j1 置刪除標記 n EnQueue qpq for j0jTnj if deleted j1 for kj1kTnk deleted k1deleted k Tnodes k1Tnodes k if Tnodes kparentj Tnodes k1parent j Tnn n 為待刪除節點數 層序遍歷樹 void TraverseTree PTree Tvoid VisitTElemType 初始條件：二叉樹 T 存在，Visit 是對節點操作的應用函式 操作結果：層序遍歷樹 T 對每個節點呼叫函式 Visit 一次且僅一次 int i for i0iTni Visit Tnodes idata printf n 孩子連結串列表示法 儲存結構 樹的孩子連結串列儲存表示 typedef struct CTNode 孩子節點 int child struct CTNode next ChildPtr typedef struct ElemType data； 節點的資料元素 ChildPtr firstchild； 孩子連結串列頭指標 CTBox typedef struct CTBox nodes MAX_TREE_SIZE； int n r； 節點數和根節點的位置 CTree 森林、樹與二叉樹的轉換 見二叉樹相應章節 外部連結 樹 資料結構 Python by EINDEX Data Structures and Algorithm Analysis in C 2nd edition 參考文獻 S deDatenstrukturBaum