版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡介
1、1,第 六 章 樹 和 二 叉 樹,2,1.熟練掌握二叉樹的結(jié)構(gòu)特性,了解相應(yīng)的證明方法。 2. 熟悉二叉樹的各種存儲(chǔ)結(jié)構(gòu)的特點(diǎn)及適用范圍。 3. 遍歷二叉樹是二叉樹各種操作的基礎(chǔ)。掌握各種遍歷策略的遞歸算法,靈活運(yùn)用遍歷算法實(shí)現(xiàn)二叉樹的其它操作。 4.理解二叉樹線索化的實(shí)質(zhì).熟練掌握二叉樹的線索化過程以及在中序線索化樹上找給定結(jié)點(diǎn)的前驅(qū)和后繼的方法。,本章重點(diǎn),3,5. 熟悉樹的各種存儲(chǔ)結(jié)構(gòu)及其特點(diǎn),掌握樹、森林與二叉樹的轉(zhuǎn)換方法。 6. 學(xué)會(huì)編寫實(shí)現(xiàn)樹的各種操作的算法。7. 了解最優(yōu)樹的特性,掌握建立最優(yōu)樹和哈夫曼編碼的方法。,4,6.1 樹的類型定義,5,數(shù)據(jù)對象 D:,D是具有相同特性
2、的數(shù)據(jù)元素的集合。,若D為空集,則稱為空樹 。 否則: (1) 在D中存在唯一的稱為根的數(shù)據(jù)元素root; (2) 當(dāng)n1時(shí),其余結(jié)點(diǎn)可分為m (m0)個(gè)互 不相交的有限集T1, T2, , Tm,其中每一 個(gè)子集本身又是一棵符合本定義的樹, 稱為根root的子樹。,數(shù)據(jù)關(guān)系 R:,6,基本操作:,查 找 類,插 入 類,刪 除 類,7,Root(T) / 求樹T的根結(jié)點(diǎn),查找類:,Value(T, cur_e) / 求cur_e結(jié)點(diǎn)的元素值,Parent(T, cur_e) / 求cur_e結(jié)點(diǎn)的雙親結(jié)點(diǎn),LeftChild(T, cur_e)/求cur_e結(jié)點(diǎn)的最左孩子,RightSibl
3、ing(T, cur_e)/ 求cur_e結(jié)點(diǎn)的右兄弟,TreeEmpty(T) / 判定樹是否為空樹,TreeDepth(T) / 求樹的深度,TraverseTree( T, Visit() ) / 遍歷,8,InitTree( Value(T, e); Parent(T, e); LeftChild(T, e); RightChild(T, e); LeftSibling(T, e); RightSibling(T, e); BiTreeEmpty(T); BiTreeDepth(T); PreOrderTraverse(T, Visit(); InOrderTraverse(T, Vi
4、sit(); PostOrderTraverse(T, Visit(); LevelOrderTraverse(T, Visit();,查找類:,25,InitBiTree(,插入類:,26,ClearBiTree(,刪除類:,27,二叉樹的重要 特 性,28,性質(zhì)1: 在二叉樹的第i 層上至多有2i-1 個(gè)結(jié)點(diǎn)。 (i1),用歸納法證明: 歸納基: 歸納假設(shè): 歸納證明:,i = 1 層時(shí),只有一個(gè)根結(jié)點(diǎn): 2i-1 = 20 = 1;,假設(shè)對所有的 j,1 j i,命題成立; 當(dāng)j=i-1時(shí), 命題成立最多有2i-2 個(gè)結(jié)點(diǎn),二叉樹上每個(gè)結(jié)點(diǎn)至多有兩棵子樹, 則第 i 層的結(jié)點(diǎn)數(shù) = 2i
5、-2 2 = 2i-1 。,29,性質(zhì) 2 : 深度為 k 的二叉樹上至多含 2k-1個(gè)結(jié)點(diǎn)(k1)。,證明:,基于上一條性質(zhì),深度為 k 的二叉樹上的結(jié)點(diǎn)數(shù)至多為 20+21+ +2k-1 = 2k-1 。 (等比數(shù)列求和),30,性質(zhì) 3 對任何一棵二叉樹,若它含有n0 個(gè)葉子結(jié)點(diǎn)(0度結(jié)點(diǎn))、n2 個(gè)度為 2的結(jié)點(diǎn),則必存在關(guān)系式:n0 = n2+1。,證明:,設(shè) 二叉樹上結(jié)點(diǎn)總數(shù) n = n0 + n1 + n2 又 二叉樹上分支總數(shù) b = n1+2n2 而 b = n-1 = n0 + n1 + n2 - 1 由此, n0 = n2 + 1 。,31,兩類特殊的二叉樹:,滿二叉樹:
6、指的是深度為k且含有2k-1個(gè)結(jié)點(diǎn)的二叉樹。,完全二叉樹:樹中所含的 n 個(gè)結(jié)點(diǎn)和滿二叉樹中編號(hào)為 1 至 n 的結(jié)點(diǎn)一一對應(yīng)。(編號(hào)的規(guī)則為,由上到下,從左到右。),1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,a,b,c,d,e,f,g,h,i,j,特點(diǎn): 1.葉子節(jié)點(diǎn)出現(xiàn)在最后2層 2.對于任意結(jié)點(diǎn),若其右分支下的子孫的最大層次為L,則左分支下的子孫的最大層次為L或L+1,32,證明:,設(shè)完全二叉樹的深度為 k 則根據(jù)第二條性質(zhì)得 2k-1 n 2k 即 k-1 log2 n k 因?yàn)?k 只能是整數(shù), 因此, k =log2n + 1 。,性質(zhì) 4 : 具有
7、n 個(gè)結(jié)點(diǎn)的完全二叉樹的深度為 log2n +1 。,33,性質(zhì) 5 :,若對含 n 個(gè)結(jié)點(diǎn)的完全二叉樹從上到下且從左至右進(jìn)行 1 至 n 的編號(hào),則對完全二叉樹中任意一個(gè)編號(hào)為 i 的結(jié)點(diǎn):(1) 若 i=1,則該結(jié)點(diǎn)是二叉樹的根,無雙親,否則,編號(hào)為 i/2 的結(jié)點(diǎn)為其雙親結(jié)點(diǎn);(2) 若 2in,則該結(jié)點(diǎn)無左孩子,否則,編號(hào)為 2i 的結(jié)點(diǎn)為其左孩子結(jié)點(diǎn);(3) 若 2i+1n,則該結(jié)點(diǎn)無右孩子結(jié)點(diǎn),否則,編號(hào)為2i+1 的結(jié)點(diǎn)為其右孩子結(jié)點(diǎn)。,34,二、二叉樹的鏈?zhǔn)?存儲(chǔ)表示,一、 二叉樹的順序 存儲(chǔ)表示,6.3 二叉樹的存儲(chǔ)結(jié)構(gòu),35,#define MAX_TREE_SIZE 10
8、0 / 二叉樹的最大結(jié)點(diǎn)數(shù) typedef TElemType SqBiTreeMAX _TREE_SIZE; / 0號(hào)單元存儲(chǔ)根結(jié)點(diǎn) SqBiTree bt;,一、 二叉樹的順序存儲(chǔ)表示,36,例如:,A,B,C,D,E,F,A B D 0 C 0 E 0 0 0 0 0 0 F,0 1 2 3 4 5 6 7 8 9 10 11 12 13,1,4,0,13,2,6,一般樹按完全二叉的方式存儲(chǔ),非常浪費(fèi)空間!深度為K的單支樹,需要2k-1個(gè)空間 (k=20 , 1M的空間),37,二、二叉樹的鏈?zhǔn)酱鎯?chǔ)表示,1. 二叉鏈表,2三叉鏈表,3雙親鏈表,4線索鏈表,38,A,D,E,B,C,F,r
9、oot,lchild data rchild,結(jié)點(diǎn)結(jié)構(gòu):,1. 二叉鏈表,39,typedef struct BiTNode / 結(jié)點(diǎn)結(jié)構(gòu) TElemType data; struct BiTNode *lchild, *rchild; / 左右孩子指針 BiTNode, *BiTree;,結(jié)點(diǎn)結(jié)構(gòu):,C 語言的類型描述如下:,40,A,D,E,B,C,F,root,2三叉鏈表,parent lchild data rchild,結(jié)點(diǎn)結(jié)構(gòu):,41,typedef struct TriTNode / 結(jié)點(diǎn)結(jié)構(gòu) struct TriTNode *parent; /雙親指針 TElemType da
10、ta; struct TriTNode *lchild, *rchild; / 左右孩子指針 TriTNode, *TriTree;,parent lchild data rchild,結(jié)點(diǎn)結(jié)構(gòu):,C 語言的類型描述如下:,42,0 1 2 3 4 5 6,data parent,結(jié)點(diǎn)結(jié)構(gòu):,3雙親鏈表,LRTag,L R R R L,A,B,C,D,E,F,1,4,0,13,2,6,43,typedef struct BPTNode / 結(jié)點(diǎn)結(jié)構(gòu) TElemType data; int parent; / 指向雙親的指針 char LRTag; / 左、右孩子標(biāo)志域 BPTNode type
11、def struct BPTree / 樹結(jié)構(gòu) BPTNode nodesMAX_TREE_SIZE; int num_node; / 結(jié)點(diǎn)數(shù)目 int root; / 根結(jié)點(diǎn)的位置 BPTree,44,typedef int Status; typedef char TElemType; typedef struct BiTNode TElemType data; struct BiTNode *lchild, *rchild; BiTNode, *BiTree; / 含有頭結(jié)點(diǎn),頭結(jié)點(diǎn)的左兒子指向樹的根結(jié)點(diǎn) Status InitBiTree(BiTree T) if (!(T=mallo
12、c(sizeof(BiTNode) return ERROR; T-lchild=NULL; T-rchild=NULL; return OK; ,45,DestroyBiTree(BiTree T) /T為樹根結(jié)點(diǎn)的指針 if (p-lchild=NULL ,46,BiTree Root (BiTree T) if T-lchild=NULL return ERROR; return T-lchild; Void ClearBiTree (BiTree T) BiTree p; p=T-lchild; if( p-lchild=NULL /其它的基本操作需要用到樹的遍歷,47,6.4 二叉樹
13、的遍歷,48,一、問題的提出,二、先左后右的遍歷算法,三、算法的遞歸描述,四、中序遍歷算法的非遞歸描述,五、遍歷算法的應(yīng)用舉例,49,順著某一條搜索路徑巡訪二叉樹中的結(jié)點(diǎn),使得每個(gè)結(jié)點(diǎn)均被訪問一次,而且僅被訪問一次。(將樹線性化),一、問題的提出(尋找某個(gè)結(jié)點(diǎn)),“訪問”的含義可以很廣,如:輸出結(jié)點(diǎn)的信息或判定節(jié)點(diǎn)滿足某些條件等。,50,“遍歷”是任何類型均有的操作, 對線性結(jié)構(gòu)而言,只有一條搜索路 徑(因?yàn)槊總€(gè)結(jié)點(diǎn)均只有一個(gè)后繼), 故不需要另加討論。而二叉樹是樹型結(jié)構(gòu),每個(gè)結(jié)點(diǎn)有兩個(gè)后繼,則存在如何遍歷,即按什么樣的搜索 路徑遍歷的問題。,51,對“二叉樹”而言,可以有三條搜索路徑:,1先
14、上后下的按層次遍歷; 2先左(子樹)后右(子樹) 的遍歷; 3先右(子樹)后左(子樹) 的遍歷。,52,二、先左后右的遍歷算法,先(根)序的遍歷算法,中(根)序的遍歷算法,后(根)序的遍歷算法,53,例:將如下表達(dá)式 a+b* ( c-d)-e/ f 存入一個(gè)樹結(jié)構(gòu)。 葉子結(jié)點(diǎn)為操作數(shù) 中間結(jié)點(diǎn)為運(yùn)算符,f,/,e,-,d,c,-,a,b,*,+,54,若二叉樹為空樹,則空操作; 否則 (1)訪問根結(jié)點(diǎn); (2)先序遍歷左子樹; (3)先序遍歷右子樹。,先(根)序的遍歷算法:,順序:-+a*b-cd/ef 正好是前綴表達(dá)式,55,若二叉樹為空樹,則空操作; 否則 (1)中序遍歷左子樹; (2)
15、訪問根結(jié)點(diǎn); (3)中序遍歷右子樹。,中(根)序的遍歷算法:,順序:a+b*c-d-e/f 正好是中綴表達(dá)式,56,若二叉樹為空樹,則空操作; 否則 (1)后序遍歷左子樹; (2)后序遍歷右子樹; (3)訪問根結(jié)點(diǎn)。,后(根)序的遍歷算法:,順序:abcd-*+ef/- 正好是后綴表達(dá)式,57,三、算法的遞歸描述,void PreOrderTraverse (BiTree T, void( *visit)(TElemType/遍歷右子樹 ,A,D,B,T,58,void InOrderTraverse (BiTree T, void( *visit)(TElemType / 遍歷右子樹 ,59
16、,void PostOrderTraverse (BiTree T, void( *visit)(TElemType / 訪問結(jié)點(diǎn) ,60,A,B,1,2,3,總結(jié):無論先序、中序、后序遍歷二叉樹,遍歷時(shí)的搜索路線是相同的:從根節(jié)點(diǎn)出發(fā),逆時(shí)針延二叉樹外緣移動(dòng),對每個(gè)節(jié)點(diǎn)均途經(jīng)三次。 先序遍歷:第一次經(jīng)過節(jié)點(diǎn)時(shí)訪問。 中序遍歷:第二次經(jīng)過節(jié)點(diǎn)時(shí)訪問。 后序遍歷:第三次經(jīng)過節(jié)點(diǎn)時(shí)訪問。,61,四、中序遍歷算法的非遞歸描述,BiTNode *GoFarLeft(BiTree T,Stack *S) / T為樹根結(jié)點(diǎn)的指針 if (!T ) return NULL; while (T-lchild
17、) Push(S, T); T = T-lchild; return T; /得到樹T最左葉子結(jié)點(diǎn)的指針,62,void InorderTree(BiTree T, void (*visit) (TelemType /??毡砻鞅闅v結(jié)束 / while / InorderTree,63,五、遍歷算法的應(yīng)用舉例,1、統(tǒng)計(jì)二叉樹中葉子結(jié)點(diǎn)的個(gè)數(shù) (先序遍歷),2、求二叉樹的深度(后序遍歷),3、復(fù)制二叉樹(后序遍歷),4、建立二叉樹的存儲(chǔ)結(jié)構(gòu),64,1、統(tǒng)計(jì)二叉樹中葉子結(jié)點(diǎn)的個(gè)數(shù),算法基本思想:,先序(或中序或后序)遍歷二叉樹,在 遍歷過程中查找葉子結(jié)點(diǎn),并計(jì)數(shù)。由此,需在遍歷算法中增添一個(gè)“計(jì)數(shù)”
18、 的參數(shù),并將算法中“訪問結(jié)點(diǎn)”的操 作改為:若是葉子,則計(jì)數(shù)器增1。,65,void CountLeaf (BiTree T, int* count) / 求葉子節(jié)點(diǎn)的個(gè)數(shù),T為根節(jié)點(diǎn)的指針 if (T) if (!T-lchild) / if / CountLeaf,(方法1),66,int LeafCount_BiTree(Bitree T) /求二叉樹中葉子結(jié)點(diǎn)的數(shù)目 if(!T) return 0; /空樹沒有葉子 else if(!T-lchild /左子樹的葉子數(shù)加上右子樹的葉子數(shù) /LeafCount_BiTree,方法2,67,2、求二叉樹的深度(后序遍歷),算法基本思想:,
19、從二叉樹深度的定義可知,二叉樹 的深度應(yīng)為其左、右子樹深度的最大值 加1。由此,需先分別求得左、右子樹 的深度,算法中“訪問結(jié)點(diǎn)”的操作為 :求得左、右子樹深度的最大值,然后 加 1 。,首先分析二叉樹的深度和它的左、右子樹深度之間的關(guān)系。,68,int BiTreeDepth (BiTree T ) / 返回二叉樹的深度, T為樹根的指針 if ( !T ) depthval = 0; else depthLeft = BiTreeDepth( T-lchild ); depthRight= BiTreeDepth( T-rchild ); depthval = 1 + (depthLeft
20、 depthRight ? depthLeft : depthRight); return depthval; ,69,3、復(fù)制二叉樹,其基本操作為:生成一個(gè)結(jié)點(diǎn)。,根元素,T,左子樹,右子樹,根元素,NEWT,左子樹,右子樹,(后序遍歷),70,BiTNode *GetTreeNode(TElemType item, BiTNode *lptr , BiTNode *rptr ) if (!(T = (BiTNode*) malloc(sizeof(BiTNode) exit(1); T- data = item; T- lchild = lptr; T- rchild = rptr; re
21、turn T; ,生成一個(gè)二叉樹的結(jié)點(diǎn) (其數(shù)據(jù)域?yàn)閕tem,左指針域?yàn)閘ptr,右指針域?yàn)閞ptr),71,BiTNode *CopyTree(BiTNode *T) if (!T ) return NULL; if (T-lchild ) newlptr = CopyTree(T-lchild);/復(fù)制左子樹 else newlptr = NULL; if (T-rchild ) newrptr = CopyTree(T-rchild);/復(fù)制右子樹 else newrptr = NULL; newT = GetTreeNode(T-data, newlptr, newrptr); ret
22、urn newT; / 返回樹根的指針,72,A,B,C,D,E,F,G,H,K, D ,C , B, H , K ,G, F ,E ,A,例如:下列二叉樹的復(fù)制過程如下:,NodeT,73,4、建立二叉樹的存儲(chǔ)結(jié)構(gòu),不同的定義方法相應(yīng)有不同的存儲(chǔ)結(jié)構(gòu)的建立算法,74,以字符串的形式 根 左子樹 右子 樹定義一棵二叉樹,例如:,A,B,C,D,以空白字符“ ”表示,A(B( ,C( , ),D( , ),空樹,只含一個(gè)根結(jié)點(diǎn)的二叉樹,A,以字符串“A ”表示,以下列字符串表示,75,Status CreateBiTree(BiTree *T) /按前序次序輸入結(jié)點(diǎn)信息 scanf( / Cre
23、ateBiTree ,無頭結(jié)點(diǎn),76,A B C D,A,B,C,D,上頁算法執(zhí)行過程舉例如下:,A,T,B,C,D,77,按給定的表達(dá)式建相應(yīng)二叉樹, 由先綴表示式建樹 例如:已知表達(dá)式的先綴表示式 -+ a b c / d e, 由原表達(dá)式建樹 例如:已知表達(dá)式 (a+b)c d/e,78,對應(yīng)先綴表達(dá)式 -+ a b c / d e的二叉樹,a,b,c,d,e,-,+,/,特點(diǎn): 操作數(shù)為葉子結(jié)點(diǎn) 運(yùn)算符為分支結(jié)點(diǎn),79,scanf( ,由先綴表示式建樹的算法的基本操作:,80,由后綴表示式建樹的算法的基本操作:,scanf( ,81,a+b,(a+b)c d/e,a+bc,分析表達(dá)式和
24、二叉樹的關(guān)系:,a,b,+,a,b,c,+,a,b,c,+,(a+b)c,a,b,c,d,e,-,+,/,82,基本操作:,scanf( ,83,對于一個(gè)完全二叉樹來說,利用先序序列、 中序序列和后序序列可以確定此樹。然而,對 于一個(gè)一般的二叉樹,僅知二叉樹的先序序 列“abcdefg” 不能唯一確定一棵二叉樹。 如果同時(shí)已知二叉樹的中序序列“cbdaegf” ,則會(huì)如何?,由二叉樹的先序和中序序列建樹,二叉樹的先序序列,二叉樹的中序序列,左子樹,左子樹,右子樹,右子樹,根,根,84,a b c d e f g,c b d a e g f,例如:,a,a,b,b,c,c,d,d,e,e,f,f
25、,g,g,a,b,c,d,e,f,g,先序序列中序序列,85,例1. 已知樹的前序次序?yàn)?abdcegf 中序次序?yàn)?bdaegcf 則樹為?,a,b,d,c,f,e,g,例2. 已知樹的后序次序?yàn)?dbgefca 中序次序?yàn)?bdaegcf 則樹為?,我們可以利用前序次序和中序次序、后序次序和中序次序 來確定一棵二叉樹。,86,何謂線索二叉樹? 線索鏈表的遍歷算法 如何建立線索鏈表?,6.5線索二叉樹,87,一、何謂線索二叉樹?,遍歷二叉樹的結(jié)果是, 求得結(jié)點(diǎn)的一個(gè)線性序列。,A,B,C,D,E,F,G,H,K,例如:,先序序列: A B C D E F G H K,中序序列: B D C
26、A H G K F E,后序序列: D C B H K G F E A,88,指向該線性序列中的“前驅(qū)”和 “后繼” 的指針,稱作“線索”,與其相應(yīng)的二叉樹,稱作 “線索二叉樹”,包含 “線索” 的存儲(chǔ)結(jié)構(gòu),稱作 “線索鏈表”,A B C D E F G H K, D ,C , B,E ,89,例 求如下二叉樹的前序線索樹、中序線索樹 和后序線索樹。,A,B,C,D,A,B,C,D,A,B,C,D,A,B,C,D,前序線索樹 中序線索樹 后序線索樹,abcd bcad cbda,NIL,NIL,NIL,NIL,90,如何保存這種在遍歷過程中得到的信息?最簡單的方法是在每個(gè)結(jié)點(diǎn)上增加二個(gè)指針域:
27、fwd和bkwd用來指示此結(jié)點(diǎn)在遍歷中的前驅(qū)和后繼結(jié)點(diǎn)。 這樣,使結(jié)點(diǎn)的存儲(chǔ)密度大大降低。我們知道在n個(gè)結(jié)點(diǎn)的二叉樹中,有n+1個(gè)空鏈域。 (空鏈域的個(gè)數(shù)=結(jié)點(diǎn)數(shù)*2 分支個(gè)數(shù)) n結(jié)點(diǎn)二叉樹的空鏈域=2*n- (n-1)=n+1 我們可以利用這n+1個(gè)空鏈域來存儲(chǔ)線索。,91,對線索鏈表中結(jié)點(diǎn)的約定:,在二叉鏈表的結(jié)點(diǎn)中增加兩個(gè)標(biāo)志域,并作如下規(guī)定:,若該結(jié)點(diǎn)的左子樹不空, 則Lchild域的指針指向其左子樹, 且左標(biāo)志域的值為“Link(指針)”; 否則,Lchild域的指針指向其“前驅(qū)”, 且左標(biāo)志的值為“Thread(線索) ” 。,92,若該結(jié)點(diǎn)的右子樹不空,則rchild域的指針指
28、向其右子樹,且右標(biāo)志域的值為 “Link(指針)”;否則,rchild域的指針指向其“后繼”,且右標(biāo)志的值為“Thread(線索) ”。,如此定義的二叉樹的存儲(chǔ)結(jié)構(gòu)稱作 “線索鏈表”。,93,typedef struct BiThrNod TElemType data; struct BiThrNode *lchild, *rchild; / 左右指針 PointerThr LTag, RTag; / 左右標(biāo)志 BiThrNode, *BiThrTree;,線索鏈表的類型描述:,#define Link 0 /指針 #define Thread 1 /線索 typedef enum Link,
29、 Thread PointerThr;,94,要求:已知一個(gè)二叉樹,我們要會(huì)畫出它的各種線 索樹。,A,B,C,D,E,F,G,H,K,畫出它的前序線索樹、中序線索樹、后序線索樹?,95,A,B,C,D,E,F,G,H,K,前序線索樹,A B C D E F G H K,NIL,96,A,B,C,D,E,F,G,H,K,后序線索樹,D C B H K G F E A,NIL,97,A,B,C,D,E,F,G,H,K,中序線索樹,B D C A H G K F E,NIL,NIL,98,二、線索鏈表的遍歷算法:,對于增加二個(gè)指針域的結(jié)構(gòu): for ( p = firstNode(T); p; p
30、 = Succ(p) ) Visit (p);,由于在線索鏈表中添加了遍歷中得到的“前驅(qū)”和“后繼”的信息,從而簡化了遍歷的算法。,99,例如:(對于利用空指針域的結(jié)構(gòu)) /中序線索化鏈表的遍歷算法, 中序遍歷的第一個(gè)結(jié)點(diǎn) ?,在中序線索化鏈表中結(jié)點(diǎn)的后繼,左子樹上處于“最左下”(沒有左子樹)的結(jié)點(diǎn)。,若無右子樹,則為后繼線索所指結(jié)點(diǎn);,否則為對其右子樹進(jìn)行中序遍歷時(shí)訪問的第一個(gè)結(jié)點(diǎn)。,100,void InOrderTraverse_Thr(BiThrTree T, void (*Visit)(TElemType e) p = T-lchild; / p指向根結(jié)點(diǎn) while (p != T
31、) / 空樹或遍歷結(jié)束時(shí),p=T while (p-LTag=Link) p = p-lchild; / 第一個(gè)結(jié)點(diǎn) if (!visit(p-data) return ERROR; while(p-RTag=Thread / p進(jìn)至其右子樹根 / InOrderTraverse_Thr,101,在中序遍歷過程中修改結(jié)點(diǎn)的 左、右指針域,以保存當(dāng)前訪問結(jié) 點(diǎn)的“前驅(qū)”和“后繼”信息。遍歷過 程中,附設(shè)指針pre, 并始終保持指 針pre指向當(dāng)前訪問的、指針p所指 結(jié)點(diǎn)的前驅(qū)。,三、如何建立線索鏈表?,102,/ 已知一棵二叉樹,將其線索化 / pre指向 p 的前驅(qū),第一次值為NULL voi
32、d InThreading(BiThrTree p) if (p) / 對以p為根的非空二叉樹進(jìn)行線索化 InThreading(p-lchild); / 左子樹線索化 if (!p-lchild) / 建前驅(qū)線索 p-LTag = Thread; p-lchild = pre; if (!pre-rchild) / 建后繼線索 pre-RTag = Thread; pre-rchild = p; pre = p; / 保持 pre 指向 p 的前驅(qū) InThreading(p-rchild); / 右子樹線索化 / if / InThreading,103,A,B,C,D,if (A) /I
33、nThreading(A) ,pre=NULL InThreading(A-lchild); / 左子樹線索化 if (!A-lchild) / 建前驅(qū)線索 ,pre=C A-LTag = Thread; A-lchild = pre; if (!pre-rchild) / 建后繼線索 pre-RTag = Thread; pre-rchild = A; pre = A; / 保持 pre 指向 p 的前驅(qū) InThreading(A-rchild); ,if (B) /InThreading(B) ,pre=NULL InThreading(B-lchild); / 左子樹線索化 if (!
34、B-lchild) / 建前驅(qū)線索 B-LTag = Thread; B-lchild = pre; if (!pre-rchild) / 建后繼線索 pre-RTag = Thread; pre-rchild = B; pre = B; / 保持 pre 指向 p 的前驅(qū) InThreading(B-rchild); ,A,B,C,D,NULL,104,if (C) /InThreading(C) ,pre=B InThreading(C-lchild); / 左子樹線索化 if (!C-lchild) / 建前驅(qū)線索 C-LTag = Thread; C-lchild = B; if (!
35、B-rchild) / 建后繼線索 B-RTag = Thread; B-rchild = C; pre = C; / 保持 pre 指向 p 的前驅(qū) InThreading(C-rchild); /pre=C,if (D) /InThreading(D) ,pre=A InThreading(D-lchild); / 左子樹線索化 if (!D-lchild) / 建前驅(qū)線索 D-LTag = Thread; D-lchild = A; if (!A-rchild) / 建后繼線索 A-RTag = Thread; A-rchild = D; pre = D; / 保持 pre 指向 p 的
36、前驅(qū) InThreading(D-rchild); ,A,B,C,D,A,B,C,D,105,Status InOrderThreading(BiThrTree Thrt, BiThrTree T) / 構(gòu)建中序線索鏈表 if (!(Thrt = (BiThrTree)malloc( sizeof( BiThrNode) exit (OVERFLOW); Thrt-LTag = Link; Thrt-RTag =Thread; Thrt-rchild = Thrt; / 添加頭結(jié)點(diǎn) return OK; / InOrderThreading, ,106,if (!T) Thrt-lchild
37、= Thrt; else Thrt-lchild = T; pre = Thrt; InThreading(T); /見書上 pre-rchild = Thrt;/處理最后一個(gè)結(jié)點(diǎn) pre-RTag = Thread; ,107,6.6 樹和森林 的表示方法,108,樹的三種存儲(chǔ)結(jié)構(gòu),一、雙親表示法,二、孩子鏈表表示法,三、樹的二叉鏈表(孩子-兄弟) 存儲(chǔ)表示法,109,A,B,C,D,E,F,G,0 A -1 1 B 0 2 C 0 3 D 0 4 E 2 5 F 2 6 G 5,r=0 n=7,data parent,一、雙親表示法:,110,typedef struct PTNode E
38、lem data; int parent; / 雙親位置域 PTNode;,data parent,#define MAX_TREE_SIZE 100,結(jié)點(diǎn)結(jié)構(gòu):,C語言的類型描述:,111,typedef struct PTNode nodes MAX_TREE_SIZE; int r, n; / 根結(jié)點(diǎn)的位置和結(jié)點(diǎn)個(gè)數(shù) PTree;,樹結(jié)構(gòu):,112,A,B,C,D,E,F,G,0 A -1 1 B 0 2 C 0 3 D 0 4 E 2 5 F 2 6 G 5,r=0 n=7,data firstchild,1 2 3,4 5,6,二、孩子鏈表表示法:,-1 0 0 0 2 2 4,11
39、3,typedef struct CTNode int child; struct CTNode *next; *ChildPtr;,孩子結(jié)點(diǎn)結(jié)構(gòu):,child next,C語言的類型描述:,114,typedef struct Elem data; int parent; ChildPtr firstchild; / 孩子鏈的頭指針 CTBox;,雙親結(jié)點(diǎn)結(jié)構(gòu),data firstchild,115,typedef struct CTBox nodesMAX_TREE_SIZE; int n, r; / 結(jié)點(diǎn)數(shù)和根結(jié)點(diǎn)的位置 CTree;,樹結(jié)構(gòu):,116,A,B,C,D,E,F,G,A B
40、 C E D F G,root,A B C E D F G,三、樹的二叉鏈表 (孩子-兄弟) 存儲(chǔ)表示法,117,要求 1. 掌握將一棵樹轉(zhuǎn)化為二叉樹 2. 將一個(gè)森林轉(zhuǎn)化為二叉樹,A,B,C,D,E,F,G,H,I,J,K,L,A,B,C,D,E,F,K,L,G,H,I,J,118,B,C,D,E,F,G,H,I,J,K,L,B,C,D,E,F,K,L,G,H,I,J,119,typedef struct CSNode Elem data; struct CSNode *firstchild, *nextsibling; CSNode, *CSTree;,C語言的類型描述:,結(jié)點(diǎn)結(jié)構(gòu):,fi
41、rstchild data nextsibling,120,森林和二叉樹的對應(yīng)關(guān)系,設(shè)森林 F = ( T1, T2, , Tn ); T1 = (root,t11, t12, , t1m);,二叉樹 B =( LBT, Node(root), RBT );,121,。,T1,T2,T3,T4,Tn,T1,T11,T12,T1m,。,T1,T11,T12,T1m,。,T2,T3,Tn,。,122,由森林轉(zhuǎn)換成二叉樹的轉(zhuǎn)換規(guī)則為:,若 F = ,則 B = ; 否則, 由ROOT( T1 )對應(yīng)得到 Node(root); 由 (t11, t12, , t1m ) 對應(yīng)得到 LBT; 由 (T2
42、, T3, Tn ) 對應(yīng)得到 RBT。,123,由二叉樹轉(zhuǎn)換為森林的轉(zhuǎn)換規(guī)則為:,若 B = , 則 F = ; 否則, 由Node(root) 對應(yīng)得到 ROOT( T1 ); 由LBT 對應(yīng)得到 ( t11, t12, ,t1m); 由RBT 對應(yīng)得到 (T2, T3, , Tn)。,124,由此,樹的各種操作均可對應(yīng)二叉樹的操作來完成。,應(yīng)當(dāng)注意的是,和樹對應(yīng)的二叉樹,其左、右子樹的概念已改變?yōu)椋?左是孩子,右是兄弟。,125,6.7 樹和森林的遍歷,126,一、樹的遍歷,二、森林的遍歷,三、樹的遍歷的應(yīng)用,127,樹的遍歷可有三條搜索路徑:,按層次遍歷:,先根(次序)遍歷:,后根(次
43、序)遍歷:,若樹不空,則先訪問根結(jié)點(diǎn),然后依次先根遍歷各棵子樹。,若樹不空,則先依次后根遍歷各棵子樹,然后訪問根結(jié)點(diǎn)。,若樹不空,則自上而下自左至右訪問樹中每個(gè)結(jié)點(diǎn)。,128,A B C D E F G H I J K,先根遍歷時(shí)頂點(diǎn)的訪問次序:,A B E F C D G H I J K,后根遍歷時(shí)頂點(diǎn)的 訪問次序:,E F B C I J K H G D A,層次遍歷時(shí)頂點(diǎn)的訪問次序:,A B C D E F G H I J K,129,B C D E F G H I J K,1森林中第一棵樹 的根結(jié)點(diǎn);,2森林中第一棵樹 的子樹森林;,3森林中其它樹構(gòu) 成的森林。,森林由三部分構(gòu)成:,1
44、30,1. 先序遍歷,森林的遍歷,若森林不空,則訪問森林中第一棵樹的根結(jié)點(diǎn);先序遍歷森林中第一棵樹的子樹森林;先序遍歷森林中(除第一棵樹之外)其余樹構(gòu)成的森林。,即:依次從左至右對森林中的每一棵樹進(jìn)行先根遍歷。,131,中序遍歷,若森林不空,則中序遍歷森林中第一棵樹的子樹森林;訪問森林中第一棵樹的根結(jié)點(diǎn);中序遍歷森林中(除第一棵樹之外)其余樹構(gòu)成的森林。,即:依次從左至右對森林中的每一棵樹進(jìn)行后根遍歷。,132,先根遍歷,后根遍歷,樹,二叉樹,森林,先序遍歷,先序遍歷,中序遍歷,中序遍歷,樹的遍歷和二叉樹遍歷的對應(yīng)關(guān)系 ?,133,設(shè)樹的存儲(chǔ)結(jié)構(gòu)為孩子兄弟鏈表,typedef struct C
45、SNode Elem data; struct CSNode *firstchild; struct CSNode *nextsibling; CSNode, *CSTree;,134,int TreeDepth(CSTree T) 1 if(!T) return 0; 2 else 3 h1 = TreeDepth( T-firstchild ); 4 h2 = TreeDepth( T-nextsibling); 5 6 7 / TreeDepth,return(max(h1+1, h2);,求樹的深度的算法:,135,6.8 哈 夫 曼 樹 與 哈 夫 曼 編 碼,最優(yōu)樹的定義 如何構(gòu)造
46、最優(yōu)樹 前綴編碼,136,一、最優(yōu)樹的定義,樹的路徑長度定義為: 樹中每個(gè)結(jié)點(diǎn)的路徑長度之 和。,結(jié)點(diǎn)的路徑長度定義為: 從根結(jié)點(diǎn)到該結(jié)點(diǎn)的路徑上 分支的數(shù)目。,137,樹的帶權(quán)路徑長度定義為: 樹中所有葉子結(jié)點(diǎn)的帶權(quán)路徑長度之和WPL(T) = wklk (對所有葉子結(jié)點(diǎn))。,在所有含 n 個(gè)葉子結(jié)點(diǎn)、并帶相同權(quán)值的 m 叉樹中,必存在一棵其帶權(quán)路徑長度取最小值的樹,稱為“最優(yōu)樹”。,例如:,138,2,2 4,7,5,4,9,9,WPL(T)= 72+52+23+43+92 =60,WPL(T)= 72+91+53+24+44 =62,5,7,139,2,4,5,7,9,WPL(T)= 9
47、 2+7 2+5 2+ 2 3+4 3 =60,140,根據(jù)給定的n個(gè)權(quán)值w1, w2, , wn, 構(gòu)造n棵二叉樹的集合: F = T1, T2, , Tn, 其中每棵二叉樹中均只含一個(gè)帶權(quán)值為wi的根結(jié)點(diǎn),其左、右子樹為空樹;,二、如何構(gòu)造最優(yōu)樹,(1),(赫夫曼算法) 以二叉樹為例:,141,在 F 中選取其根結(jié)點(diǎn)的權(quán)值為最小的兩棵二叉樹,分別作為左、右子樹構(gòu)造一棵新的二叉樹,并置這棵新的二叉樹根結(jié)點(diǎn)的權(quán)值為其左、右子樹根結(jié)點(diǎn)的權(quán)值之和;,(2),142,從F中刪去這兩棵樹,同時(shí)加入剛生成的新樹;,重復(fù)(2)和(3)兩步,直至F 中只含一棵樹為止。,(3),(4),143,9,例如: 已
48、知權(quán)值 W= 5, 6, 2, 9, 7 ,5,6,2,7,5,2,7,6,9,7,6,7,13,9,5,2,7,144,6,7,13,9,5,2,7,9,5,2,7,16,6,7,13,29,0,0,0,0,1,1,1,1,00,01,10,110,111,145,赫夫曼編碼 假設(shè)我們發(fā)送的電文為“ABACCD”,它只有 四個(gè)字符,只需要2位二進(jìn)制編碼 A - 00 B - 01 C - 10 D - 11 發(fā)送電文的序列為 000100101011 在傳送電文時(shí),希望總長度盡量短,因此出 現(xiàn)次數(shù)多的字符適用短的編碼。 A - 0 B - 00 C - 1 D - 11 發(fā)送電文的序列為 00001111 可以解釋為AAAACCCC,AABDD,BBCCCC.) 我們必須使用前綴編碼,146,指的是,任何一個(gè)字符的編碼都不是同一字符集中另一個(gè)字符的編碼的前綴。 如A B C D 四個(gè)字符的使用率由高到低,編碼為 A - 0 B - 10 C - 110 D
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲(chǔ)空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 2026北京市電科國際校園招聘考試參考題庫及答案解析
- 2026南京大學(xué)YJ20260252醫(yī)學(xué)院博士后招聘1人筆試參考題庫及答案解析
- 2026天津市口腔醫(yī)院度專業(yè)技術(shù)崗位工作人員(人事代理制)招聘27人考試備考試題及答案解析
- 2026廣東廣州大學(xué)招聘醫(yī)生崗位1人(第一次)考試備考試題及答案解析
- 久治縣醫(yī)共體2026年面向社會(huì)公開招聘編外臨聘人員16人考試備考試題及答案解析
- 2026廣東佛山市順德區(qū)樂從鎮(zhèn)覺培幼兒園招聘帶班教師及后勤人員6人考試參考試題及答案解析
- 2026江蘇無錫市江南大學(xué)人才招聘考試備考題庫及答案解析
- 2026年武義縣應(yīng)急管理局招聘備考題庫及完整答案詳解一套
- 2026年藍(lán)星(北京)化工機(jī)械有限公司招聘備考題庫及一套參考答案詳解
- 2025年網(wǎng)紅孵化基地合作合同協(xié)議
- 2025年城市更新的城市更新技術(shù)
- 2025年第五人格聽力試卷及答案
- 藥店三七活動(dòng)方案
- 聚焦2025年:電商物流“最后一公里”配送冷鏈運(yùn)輸解決方案研究
- 工商用戶燃?xì)獍踩嘤?xùn)課件
- 冬季代維安全培訓(xùn)課件
- 資產(chǎn)盡職調(diào)查管理辦法
- 閥體生產(chǎn)工藝流程及設(shè)備工裝設(shè)計(jì)
- DBJT15-192-2020 平板動(dòng)力載荷試驗(yàn)技術(shù)標(biāo)準(zhǔn)
- (試題)兩江新區(qū)2024-2025學(xué)年上期小學(xué)期末質(zhì)量監(jiān)測六年級(jí)英語
- 鐵路用地管理辦法
評論
0/150
提交評論