資料結構 第6章 樹狀結構.

Slides:



Advertisements
Similar presentations
1 第八章 深入探討樹狀結構. 2 目次 8.1 m-way 搜尋樹 8.2 B-tree 8.3 動動腦時間 8.4 練習題解答.
Advertisements

第7章 樹與二元樹 (Trees and Binary Trees)
資料結構 老師:李崇明 助教:楊斯竣.
Tree (2): heap, deap, 2-3 tree, 2-3-4tree
演算法 陣列 鏈結串列 堆疊與佇列 樹狀結構 搜尋
資料結構(計財系).
Chapter 6 樹狀結構.
新世代計算機概論 第15章 資料結構.
Chapter 5 樹狀結構.
第6章 二叉树和树 前面的章节主要讨论的是线性结构,二叉树和树属于非线性的结构。遍历非线性结构比线性结构要麻烦。
计算机软件技术基础 数据结构与算法(4).
数据结构——树和二叉树 1/96.
引入树 线性表、堆栈和队列都是线性结构,它们的共同特点:一对一; 计算机对弈中的一个格局可能有多个后继格局,用线性结构难以描述。
第六章 树和二叉树.
第5章 树( Tree )和二叉树 5.1 树的基本概念 5.2 二叉树 5.3 遍历二叉树和线索二叉树 5.4 树和森林
第八章 查找.
§4 Additional Binary Tree Operations
Chap4 Tree.
Tree(樹) 什麼是「樹」? 「樹」的範例 「樹」的定義 「樹」的表示法.
Chap5 Graph.
資料結構 第3章 鏈結串列.
Chapter8 Binary and Other Trees
第11章 資料結構 – 使用C語言的模組 11-1 資料結構的基礎 11-2 C語言的模組化程式設計 11-3 基本鏈結串列
講師:郭育倫 第3章 基本資料結構 講師:郭育倫
第7章 樹與二元樹 (Trees and Binary Trees)
樹狀結構 Trees.
Chapter 5 樹(Trees).
第12章 樹狀搜尋結構 (Search Trees)
資料結構與C++程式設計進階 鏈結串列 講師:林業峻 CSIE, NTU 6/ 10, 2010.
演算法與資料結構 製作單位: 高雄市立高雄中學.
(Circular Linked Lists)
第六章 树和二叉树.
第 七 章 樹狀結構 課程名稱:資料結構 授課老師:________ 2019/1/1.
資料結構–樹(Tree) 綠園.
教 师:曾晓东 电 话: E_mail: 计算机软件技术基础 教 师:曾晓东 电 话: E_mail:
4.1 單向鏈結串列 4.2 堆疊的加入與刪除 4.3 佇列的加入與刪除 4.4 其他型式的佇列
鄧姚文 資料結構 第六章:樹(Tree) 鄧姚文
Chapter 9 高度平衡二元搜尋樹 AVL Binary Search Tree
樹狀結構 Tree Structure chapter 7 德明科技大學資訊科技系.
親愛的老師您好 感謝您選用本書作為授課教材,博碩文化準備本書精選簡報檔,特別摘錄重點提供給您授課專用。 說明: 博碩文化:
Chap3 Linked List 鏈結串列.
Chapter 11 B-tree 11.1 m-way 搜尋樹 11.2 B-tree.
第六章 樹狀結構 T r e e 版權屬作者所有,非經作者 同意不得用於教學以外用途.
樹 2 Michael Tsai 2013/3/26.
感謝同學們在加分題建議. 我會好好研讀+反省~
Chap4 Tree.
Tree & Binary Tree.
資料結構 7-1 陣列 7-2 鏈結串列 7-3 堆疊和佇列 7-4 樹狀結構.
資料結構使用Java 樹(Tree).
第六章 树和二叉树 £6.1 树 £6.2 二叉树 £6. 3 二叉树的存储结构 £6.4 二叉树的遍历与线索化 £6.1.1 树的定义
Reference to FUNDAMENTALS OF DATA STRUCTURE IN C++
第六章 树和二叉树 学习要点 理解树的定义和基本术语,重点了解二叉树的定义、性质、存储结构; 掌握二叉树遍历的递归算法及它的典型运算;
第7章 樹與二元樹(Trees and Binary Trees)
挑戰C++程式語言 ──第8章 進一步談字元與字串
資料結構與C++程式設計進階 樹狀結構(Tree) 講師:林業峻 CSIE, NTU 11/ 12, 2009.
第 八 章 高等樹 課程名稱:資料結構 授課老師:________ 2019/4/28.
資料結構使用Java 第9章 樹(Tree).
C qsort.
树和二叉树(一).
講師:郭育倫 第3章 基本資料結構 講師:郭育倫
資料結構使用Java 第6章 鏈結串列(Linked List).
動畫演示 Node規範了一些基本的方法,像是增加節點、刪除節點、讓節點做一些事、取得第n個節點等等
6.1 樹狀結構的一些專有名詞 6.2 二元樹 6.3 二元樹的表示方法 6.4 二元樹的追蹤 6.5 引線二元樹 6.6 其它議題
第7章 資料結構 7-1 陣列 7-2 鏈結串列 7-3 堆疊和佇列 7-4 樹狀結構.
本教學投影片係屬教科書著作之延伸,亦受著作權法之保護。
堆積(Heap Tree) 授課老師:蕭志明.
String類別 在C語言中提供兩種支援字串的方式 可以使用傳統以null結尾的字元陣列 使用string類別
Trees 授課者:驕芸.
本节内容 1.二叉排序树的定义 2.二叉排序树的查找操作 3.二叉排序树的插入操作 4.二叉排序树的删除操作 5.二叉排序树的总结
JAVA 程式設計與資料結構 第十七章 Tree.
Presentation transcript:

資料結構 第6章 樹狀結構

6-1 認識樹 樹 (tree) 是由一或多個節點 所組成的有限集合,其特質如下: 有一個特殊節點,稱為樹根 。 6-1 認識樹 樹 (tree) 是由一或多個節點 所組成的有限集合,其特質如下: 有一個特殊節點,稱為樹根 。 其餘節點可以分為n個互斥集合T1、T2、…、Tn (n ≥ 0),而且每個集合也都是一棵樹 。

6-1-1 樹的相關名詞 分支度 (degree) 終端節點 (terminal node) 6-1-1 樹的相關名詞 分支度 (degree) 終端節點 (terminal node) 非終端節點 (nonterminal node) 階度 (level) 父節點 (parent) 子節點 (child) 兄弟 (sibling) 祖先 (ancestor) 子孫 (descendant) 高度 (height) 或深度 (depth) 樹林 (forest)

6-1-2 樹的表示方式 我們可以使用串列 表示樹,例如右圖 的樹可以表示成 (A(B(E, F(K)), C(G, H(L, M(N)), I), D(J))) 至於每個節點在記憶體的儲存方式,我們可以使用如下的結構 : data link1 link2 … linkn

6-2 二元樹 二元樹 (binary tree) 是每個節點最多有兩個子節點的樹,節點的左邊稱為左子樹 ,節點的右邊稱為右子樹 。

範例6.2:證明二元樹第i階的最多節點個數為2i-1,i ≥ 1。 解答: 當i = 1時,第1階最多只有樹根一個節點,故 2i-1 = 21-1 = 20 = 1成立。 假設當1 ≤ i < k時,第i階的最多節點個數為 2i-1成立,故第k - 1階的最多節點個數為2k-2。 證明當i = k時,第i階的最多節點個數為2i-1亦 成立。由於第k - 1階的最多節點個數為2k-2,而 二元樹的每個節點最多有兩個子節點,故第k階 的最多節點個數為2k-2 x 2 = 2k-1。

範例6.3:證明高度為h之二元樹的最多節點個數為2h - 1,h ≥ 1。 解答:由於二元樹第i階的最多節點個數為2i-1,因此,對高度為h的二元樹來說,全部存滿的話,總共有20 + 21 + … + 2h-1 = 2h - 1個節點。

6-2-1 完滿二元樹V.S. 完整二元樹 完滿二元樹 (full binary tree) 完整二元樹 (complete binary tree)

假設完整二元樹的節點個數為n且節點依照0 ~ n - 1的順序編號,則其任意節點i (0 ≤ i ≤ n - 1) 具有下列特質: 若i = 0,表示節點i為樹根,否則節點i的父節點為 (i - 1)/2 。 若2i + 1 ≥ n,表示節點i沒有左子節點,否則節點i的左子節點為2i + 1。 若2i + 2 ≥ n,表示節點i沒有右子節點,否則節點i的右子節點為2i + 2。

範例6.6:證明節點個數為n之完整二元樹的高度為 log2n + 1。

6-2-2 二元樹的表示方式 使用陣列實作二元樹 [0] [1] [2] [3] [4] [5] [6] [7] [8] [9] [10] 6-2-2 二元樹的表示方式 使用陣列實作二元樹 [0] [1] [2] [3] [4] [5] [6] [7] [8] [9] [10] [11] [12] A B C D E -- F G H I

使用鏈結串列實作二元樹 typedef struct node{ struct node *lchild; char data; struct node *rchild; }tree_node; typedef tree_node *tree_pointer;

6-2-3 將一般樹轉換為二元樹 範例6.7:將下面的一般樹轉換為二元樹。

6-3 二元樹的走訪 6-3-1 中序走訪 inorder(tree_pointer root) { if (root){ 6-3 二元樹的走訪 6-3-1 中序走訪 inorder(tree_pointer root) { if (root){ inorder(root->lchild); printf("%d ", root->data); inorder(root->rchild); } 右圖的中序走訪的結果為DBGEHACFI。

6-3-2 前序走訪 preorder(tree_pointer root) { if (root){ printf("%d ", root->data); preorder(root->lchild); preorder(root->rchild); } 右圖的前序走訪的結果為ABDEGHCFI。

6-3-3 後序走訪 postorder(tree_pointer root) { if (root){ postorder(root->lchild); postorder(root->rchild); printf("%d", root->data); } 右圖的後序走訪的結果為DGHEBIFCA。

6-3-4 決定唯一的二元樹 範例6.11:[決定唯一的二元樹] 假設二元樹的中序與前序走訪分別為DBEACGFH、ABDECFGH,試據此推算出該二元樹。

6-4 二元樹的其它運算 6-4-1 複製二元樹 範例6.13:撰寫一個函數實作複製二元樹運算。 6-4 二元樹的其它運算 6-4-1 複製二元樹 範例6.13:撰寫一個函數實作複製二元樹運算。 tree_pointer copy(tree_pointer source) { tree_pointer destination; if (source){ destination = (tree_pointer)malloc(sizeof(tree_node)); destination->lchild = copy(source->lchild); destination->rchild = copy(source->rchild); destination->data = source->data; return destination; } return NULL;

6-4-2 比較二元樹 範例6.14:撰寫一個函數實作比較二元樹運算。 6-4-2 比較二元樹 範例6.14:撰寫一個函數實作比較二元樹運算。 int equal(tree_pointer source, tree_pointer destination) { if ((!source && !destination) || (source && destination && (source->data == destination->data) && equal(source->lchild, destination->lchild) && equal(source->rchild, destination->rchild)) return 1; else return 0; }

6-5 運算式樹 運算式樹 (expression tree) 指的是滿足下列條件的二元樹: 6-5 運算式樹 運算式樹 (expression tree) 指的是滿足下列條件的二元樹: 終端節點為運算元 (operand),而非終端節點為運算子 (operator)。 子樹為子運算式且其樹根為運算子。

6-6 引線二元樹 引線二元樹 (threaded binary tree) 的左引線 (left thread) 指向節點本身的中序前行者 (inorder predecessor),右引線 (left thread) 指向節點本身的中序後繼者 (inorder successor) 。

6-6-1 節點結構 #define THRAED 1 #define POINTER 0 typedef struct thnode{ 6-6-1 節點結構 #define THRAED 1 #define POINTER 0 typedef struct thnode{ int lthread; struct threaded_node *lchild; char data; struct threaded_node *rchild; int rthread; }threaded_node; typedef threaded_node *threaded_pointer; lthread lchild data rchild rthread

空的引線二元樹 (只有包含首節點) 加入首節點的引線二元樹

6-6-2 中序走訪 範例6.15:撰寫一個函數在引線二元樹中找出任意節點的中序後繼者。 6-6-2 中序走訪 範例6.15:撰寫一個函數在引線二元樹中找出任意節點的中序後繼者。 threaded_pointer inorder_successor(threaded_pointer ptr) { threaded_pointer tmp; tmp = ptr->rchild; if (tmp == POINTER) while(tmp->lchild == POINTER) tmp = tmp->lchild; return tmp; }

範例6.16:利用範例6.15所撰寫的inorder_successor() 函數完成引線二元樹的中序走訪。 threaded_inorder (threaded_pointer head) { threaded_pointer tmp; for(;;){ tmp = inorder_successor(tmp); if (tmp == head) break; printf("%d ", tmp->data); }

6-6-3 插入節點 情況一: 將新節點T插入節點S的右兒子且新節點T是樹葉

將新節點T插入節點S的右兒子且新節點T不是樹葉 threaded_pointer tmp; T->rthread = S->rthread; T->rchild = S->rchild; T->lthread = THREAD; T->lchild = S; S->rthread = POINTER; S-rchild = T; if (T->rthread == POINTER){ tmp = T->rchild; while(tmp->lchild == POINTER) tmp = tmp->lchild; tmp->lchild = T; } (1) (2) (3) (4)

情況二: 將新節點T插入節點S的左兒子且新節點T是樹葉

將新節點T插入節點S的左兒子且新節點T不是樹葉 T->lthread = S->lthread; T->lchild = S->lchild; T->rthread = THREAD; T->rchild = S; S->lthread = POINTER; S-lchild = T; if (T->lthread == POINTER){ tmp = T->lchild; while(tmp->rchild == POINTER) tmp = tmp->rchild; tmp->rchild = T; } (1) (2) (3) (4)

6-7 二元搜尋樹 二元搜尋樹是滿足下列條件的二元樹: 每個節點包含唯一的鍵值 (key)。 左右子樹亦為二元搜尋樹。 6-7 二元搜尋樹 二元搜尋樹是滿足下列條件的二元樹: 每個節點包含唯一的鍵值 (key)。 左右子樹亦為二元搜尋樹。 左子樹的鍵值必須小於其樹根的鍵值 右子樹的鍵值必須大於其樹根的鍵值。

6-7-1 搜尋節點 先和樹根做比較,若指定的鍵值小於樹根,就以同樣的方式搜尋樹根的左子樹,若指定的鍵值大於樹根,就以同樣的方式搜尋樹根的右子樹,左右子樹均據此定義遞迴地搜尋下去。 寫出在右圖的二元搜尋樹搜尋70和35兩個鍵值的過程。

範例6.20:以遞迴的方式撰寫一個函數在二元搜尋樹搜尋節點。 tree_pointer search2(tree_pointer root, int key) { if (!root) return NULL; if (key == root->data) return root; if (key < root->data) return search2(root->lchild, key); else return search2(root->rchild, key); }

6-7-2 插入節點 先和樹根做比較,若新節點小於樹根,就以同樣的方式移往樹根的左子樹,若新節點大於樹根,就以同樣的方式移往樹根的右子樹,直到抵達子樹的尾端,再將新節點加入子樹的尾端。

範例6.21:[建構二元搜尋樹] 將數字串列 (25, 30, 24, 58, 45, 26, 12, 14) 建構為二元搜尋樹。

假設將數字串列 (25, 30, 24, 58, 45, 26, 12, 14) 變更為 (25, 30, 24, 58, 45, 26, 14, 12),後面兩個資料的順序交換,則建構出來的二元搜尋樹如下:

假設將數字串列 (25, 30, 24, 58, 45, 26, 12, 14) 變更為 (12, 14, 24, 25, 26, 30, 45, 58),資料由小到大排序,則建構出來的二元搜尋樹如下:

6-7-3 刪除節點 情況一:當欲刪除的節點是樹葉時,直接刪除該節點即可。

情況二:當欲刪除的節點有一棵子樹時,將其父節點的指標改指向其子節點,然後刪除該節點即可。

情況三:當欲刪除的節點有兩棵子樹時,以該節點的左子樹中最大節點或右子樹中最小節點填入其位置,然後刪除該節點即可。

6-8 霍夫曼樹 範例6.23:[建構霍夫曼樹] 假設A、B、C、D、E、F等六個符號的出現頻率為0.2、0.15、0.3、0.18、0.05、0.12,試據此建構霍夫曼樹並寫出各個符號的編碼。

範例6.24:[霍夫曼碼解碼] 根據範例6.23所設計的霍夫曼碼,將111110010000110進行解碼。 解答:由於A、B、C、D、E、F等六個符號分別被編碼為01、110、10、00、1110、1111,故將111110010000110解碼後會得到FCADDB。

6-9 樹林 樹林 (forest) 是由n棵互斥樹所組成的集合 (n ≥ 0),適合用來表示互斥集合 (disjoin set)。 6-9 樹林 樹林 (forest) 是由n棵互斥樹所組成的集合 (n ≥ 0),適合用來表示互斥集合 (disjoin set)。 樹去掉樹根後就會得到樹林 樹

範例6.26:將下面的樹林轉換為二元樹。

6-10 集合 集合 (set) 是一群相同類型、沒有順序之分的元素,而互斥集合 (disjoin set) 是沒有相同元素的集合 。

互斥集合常見的運算有下列兩種: 聯集 (union) 搜尋 (find) (a) S1 U S2 (b) S2 U S1

使用陣列存放互斥集合,以下圖的S1、S2、S3等三個集合為例,陣列的內容如下, i 1 2 3 4 5 6 7 8 parent[i] -1

呼叫聯集運算函數建立S1、S2、S3等三個集合和S1∪S2集合: 互斥集合的聯集運算函數 set_union(int i, int j) { parent[i] = j; } 呼叫聯集運算函數建立S1、S2、S3等三個集合和S1∪S2集合: set_union(0, 2); set_union(1, 2); set_union(3, 4); set_union(5, 8); set_union(6, 8); set_union(7, 8); set_union(4, 2);

互斥集合的搜尋運算函數 int find(int i) { while(parent[i] > 0 i = parent[i]; return i; }