




版權(quán)說(shuō)明:本文檔由用戶(hù)提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
1、6.1 樹(shù)的定義和基本術(shù)語(yǔ)6.2 二叉樹(shù)6.3 遍歷二叉樹(shù)和線(xiàn)索二叉樹(shù)6.4 樹(shù)和森林6.6 哈夫曼樹(shù)與哈夫曼編碼第六章 樹(shù)和二叉樹(shù)6.1 樹(shù)的類(lèi)型定義數(shù)據(jù)對(duì)象 D:D是具有相同特性的數(shù)據(jù)元素的集合。 若D為空集,則稱(chēng)為空樹(shù) 。否則: (1) 在D中存在唯一的稱(chēng)為根的數(shù)據(jù)元素root; (2) 當(dāng)n1時(shí),其余結(jié)點(diǎn)可分為m (m0)個(gè)互 不相交的有限集T1, T2, , Tm,其中每一 棵子集本身又是一棵符合本定義的樹(shù)(遞歸), 稱(chēng)為根root的子樹(shù)。 數(shù)據(jù)關(guān)系 R:ABCDEFGHIJMKLA( B(E, F(K, L), C(G), D(H, I, J(M) )T1T3T2樹(shù)根例如: 基本操
2、作:查 找 類(lèi)插 入 類(lèi)刪 除 類(lèi) Root(T) / 求樹(shù)的根結(jié)點(diǎn) 查找類(lèi):Value(T, cur_e) / 求當(dāng)前結(jié)點(diǎn)的元素值 Parent(T, cur_e) / 求當(dāng)前結(jié)點(diǎn)的雙親結(jié)點(diǎn)LeftChild(T, cur_e) / 求當(dāng)前結(jié)點(diǎn)的最左孩子 RightSibling(T, cur_e) / 求當(dāng)前結(jié)點(diǎn)的右兄弟TreeEmpty(T) / 判定樹(shù)是否為空樹(shù) TreeDepth(T) / 求樹(shù)的深度TraverseTree( T, Visit() ) / 遍歷InitTree(&T) / 初始化置空樹(shù) 插入類(lèi):CreateTree(&T, definition) / 按定義構(gòu)造樹(shù)A
3、ssign(T, cur_e, value) / 給當(dāng)前結(jié)點(diǎn)賦值InsertChild(&T, &p, i, c) / 將以c為根的樹(shù)插入為結(jié)點(diǎn)p的第i棵子樹(shù) ClearTree(&T) / 將樹(shù)清空 刪除類(lèi):DestroyTree(&T) / 銷(xiāo)毀樹(shù)的結(jié)構(gòu)DeleteChild(&T, &p, i) / 刪除結(jié)點(diǎn)p的第i棵子樹(shù)ABCDEFGHIJMKLA( B(E, F(K, L), C(G), D(H, I, J(M) )T1T3T2樹(shù)根例如:樹(shù)形圖表示的例子ABKELFDHMJICG嵌套集合表示法ABCDEKLFGHIJM凹入表示法(A(B(E(K,L),F),C(G),D(H(M),I
4、,J)廣義表表示法ABCDEFGHIJMKL對(duì)比樹(shù)型結(jié)構(gòu)和線(xiàn)性結(jié)構(gòu)的結(jié)構(gòu)特點(diǎn)線(xiàn)性結(jié)構(gòu)樹(shù)型結(jié)構(gòu)第一個(gè)數(shù)據(jù)元素 (無(wú)前驅(qū)) 根結(jié)點(diǎn) (無(wú)前驅(qū))最后一個(gè)數(shù)據(jù)元素 (無(wú)后繼)多個(gè)葉子結(jié)點(diǎn) (無(wú)后繼)其它數(shù)據(jù)元素(一個(gè)前驅(qū)、 一個(gè)后繼)其它數(shù)據(jù)元素(一個(gè)前驅(qū)、 多個(gè)后繼)基 本 術(shù) 語(yǔ)結(jié)點(diǎn):結(jié)點(diǎn)的度:樹(shù)的度:葉子結(jié)點(diǎn):分支結(jié)點(diǎn):數(shù)據(jù)元素 + 若干指向子樹(shù)的分支分支的個(gè)數(shù)樹(shù)中所有結(jié)點(diǎn)的度的最大值度為零的結(jié)點(diǎn)度大于零的結(jié)點(diǎn)DHIJM(從根到結(jié)點(diǎn)的)路徑:孩子結(jié)點(diǎn)、雙親結(jié)點(diǎn)兄弟結(jié)點(diǎn)、堂兄弟祖先結(jié)點(diǎn)、子孫結(jié)點(diǎn)結(jié)點(diǎn)的層次:樹(shù)的深度: 由從根到該結(jié)點(diǎn)所經(jīng)分支和結(jié)點(diǎn)構(gòu)成ABCDEFGHIJMKL假設(shè)根結(jié)點(diǎn)的層次為1,
5、第l 層的結(jié)點(diǎn)的子樹(shù)根結(jié)點(diǎn)的層次為l+1樹(shù)中葉子結(jié)點(diǎn)所在的最大層次() 有確定的根;() 樹(shù)根和子樹(shù)根之間為有向關(guān)系。有向樹(shù):有序樹(shù):子樹(shù)之間存在確定的次序關(guān)系。無(wú)序樹(shù):子樹(shù)之間不存在確定的次序關(guān)系。任何一棵非空樹(shù)是一個(gè)二元組 Tree = (root,F(xiàn))其中:root 被稱(chēng)為根結(jié)點(diǎn) F 被稱(chēng)為子樹(shù)森林森林:是m(m0)棵互不相交的樹(shù)的集合ArootBCDEFGHIJMKLF6.2 二叉樹(shù)6.2.1 二叉樹(shù)的定義6.2.2 二叉樹(shù)的性質(zhì)6.2.3 二叉樹(shù)的存儲(chǔ)結(jié)構(gòu) 6.2.1 二叉樹(shù)的定義 二叉樹(shù)或?yàn)榭諛?shù),或是由一個(gè)根結(jié)點(diǎn)加上兩棵分別稱(chēng)為左子樹(shù)和右子樹(shù)的、互不交的二叉樹(shù)組成。(遞歸定義)AB
6、CDEFGHK根結(jié)點(diǎn)左子樹(shù)右子樹(shù)二叉樹(shù)的五種基本形態(tài):N空樹(shù)只含根結(jié)點(diǎn)NNNLRR右子樹(shù)為空樹(shù)L左子樹(shù)為空樹(shù)左右子樹(shù)均不為空樹(shù)二叉樹(shù)的主要基本操作:查 找 類(lèi)插 入 類(lèi)刪 除 類(lèi) Root(T); 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, Visit(); PostOrderTr
7、averse(T, Visit(); LevelOrderTraverse(T, Visit(); InitBiTree(&T); Assign(T, &e, value); CreateBiTree(&T, definition); InsertChild(T, p, LR, c);ClearBiTree(&T); DestroyBiTree(&T);DeleteChild(T, p, LR);6.2.2 二叉樹(shù)的重要特性性質(zhì)1 : 在二叉樹(shù)的第 i 層上至多有2i-1 個(gè)結(jié)點(diǎn)。 (i1)用歸納法證明: 歸納基: 歸納假設(shè): 歸納證明:i = 1 層時(shí),只有一個(gè)根結(jié)點(diǎn): 2i-1 = 20
8、= 1;假設(shè)對(duì)所有的 j,1 j i,命題成立;二叉樹(shù)上每個(gè)結(jié)點(diǎn)至多有兩棵子樹(shù),則第 i 層的結(jié)點(diǎn)數(shù) = 2i-2 2 = 2i-1 。性質(zhì) 2 : 深度為 k 的二叉樹(shù)上至多含 2k-1 個(gè)結(jié)點(diǎn)(k1)。證明: 基于上一條性質(zhì),深度為 k 的二叉樹(shù)上的結(jié)點(diǎn)數(shù)至多為 20+21+ +2k-1 = 2k-1 。性質(zhì) 3 : 對(duì)任何一棵二叉樹(shù),若它含有n0 個(gè)葉子結(jié)點(diǎn)、n2 個(gè)度為 2 的結(jié)點(diǎn),則必存在關(guān)系式:n0 = n2+1。證明:設(shè) 二叉樹(shù)上結(jié)點(diǎn)總數(shù) n = n0 + n1 + n2又 二叉樹(shù)上分支總數(shù) b = n1+2n2 而 b = n-1 = n0 + n1 + n2 - 1由此, n
9、0 = n2 + 1 。兩類(lèi)特殊的二叉樹(shù):滿(mǎn)二叉樹(shù):指的是深度為k且含有2k-1個(gè)結(jié)點(diǎn)的二叉樹(shù)。完全二叉樹(shù):樹(shù)中所含的 n 個(gè)結(jié)點(diǎn)和滿(mǎn)二叉樹(shù)中編號(hào)為 1 至 n 的結(jié)點(diǎn)一一對(duì)應(yīng)。123456789101112131415abcdefghij 性質(zhì) 4 : 具有 n 個(gè)結(jié)點(diǎn)的完全二叉樹(shù)的深度為 log2n +1 。證明:設(shè)完全二叉樹(shù)的深度為 k 則根據(jù)第二條性質(zhì)得 2k-1 n 2k 即 k-1 log2 n n,則該結(jié)點(diǎn)無(wú)左孩子, 否則,編號(hào)為 2i 的結(jié)點(diǎn)為其左孩子結(jié)點(diǎn);(3) 若 2i+1n,則該結(jié)點(diǎn)無(wú)右孩子結(jié)點(diǎn), 否則,編號(hào)為2i+1 的結(jié)點(diǎn)為其右孩子結(jié)點(diǎn)。有一n 個(gè)結(jié)點(diǎn)的完全二叉樹(shù) 1
10、. ? 求n0 和最后一個(gè)非終端結(jié)點(diǎn)的編號(hào). 2. ? n為奇數(shù)或偶數(shù)時(shí)n1,n2 3. ? 不用對(duì)數(shù)如何求樹(shù)的深度.任一結(jié)點(diǎn)層次 4. ? 哪種形態(tài)樹(shù)的層次最小或最大6.2.3 二叉樹(shù)的存儲(chǔ)結(jié)構(gòu)二、二叉樹(shù)的鏈?zhǔn)?存儲(chǔ)表示一、 二叉樹(shù)的順序 存儲(chǔ)表示#define MAX_TREE_SIZE 100 / 二叉樹(shù)的最大結(jié)點(diǎn)數(shù)typedef TElemType SqBiTreeMAX_ TREE_SIZE; / 0號(hào)單元存儲(chǔ)根結(jié)點(diǎn)SqBiTree bt;一、 二叉樹(shù)的順序存儲(chǔ)表示可利用完全二叉樹(shù)的概念,將一般二叉樹(shù)按完全二叉樹(shù)對(duì)應(yīng)位置進(jìn)行編號(hào),其編號(hào)為 i 的結(jié)點(diǎn)存入一維數(shù)組下標(biāo)為 i-1 分量中
11、.例如:ABCDEF A B D C E F 0 1 2 3 4 5 6 7 8 9 10 11 12 1314013261235714 1 2 3 4 5 6 7 8 9 10 11 12 13 14 編號(hào) 下標(biāo)? MAX_TREE_SIZE 如何確定(數(shù)組 長(zhǎng)度) ? 每一層的結(jié)點(diǎn)編號(hào)如何求,范圍 如何確定 二、二叉樹(shù)的鏈?zhǔn)酱鎯?chǔ)表示1. 二叉鏈表2三叉鏈表ADEBCFrootlchild data rchild結(jié)點(diǎn)結(jié)構(gòu):1. 二叉鏈表Typedef struct BiTNode / 結(jié)點(diǎn)結(jié)構(gòu) TElemType data; struct BiTNode *lchild, *rchild;
12、/ 左右孩子指針 BiTNode, *BiTree;lchild data rchild結(jié)點(diǎn)結(jié)構(gòu):C 語(yǔ)言的類(lèi)型描述如下:ADEBCFroot2三叉鏈表parent lchild data rchild結(jié)點(diǎn)結(jié)構(gòu): typedef struct TriTNode / 結(jié)點(diǎn)結(jié)構(gòu) TElemType data; struct TriTNode *lchild , *rchild ; / 左右孩子指針 struct TriTNode *parent; /雙親指針 TriTNode, *TriTree;parent lchild data rchild結(jié)點(diǎn)結(jié)構(gòu):C 語(yǔ)言的類(lèi)型描述如下:? n 個(gè)結(jié)點(diǎn)的二
13、叉樹(shù)哪種形態(tài)最好 (存儲(chǔ)密度最大), 哪種形態(tài)最壞 (存儲(chǔ)密度最小).6.3 二叉樹(shù)的遍歷 和線(xiàn)索二叉樹(shù)一、問(wèn)題的提出三、先左后右的遍歷算法四、中序遍歷算法的非遞歸描述五、遍歷算法的應(yīng)用舉例二、按層次遍歷二叉樹(shù) 按某一條搜索路徑(某種規(guī)則) 訪(fǎng)問(wèn)二叉樹(shù)中的結(jié)點(diǎn),使得每個(gè)結(jié)點(diǎn)均被訪(fǎng)問(wèn)一次,而且僅被訪(fǎng)問(wèn)一次。一、問(wèn)題的提出“訪(fǎng)問(wèn)”的含義可以很廣,如:輸出結(jié)點(diǎn)的信息等。因此遍歷算法在很多情況下是核心算法,將訪(fǎng)問(wèn)看成的不同的函數(shù),可實(shí)現(xiàn)不同的操作. “遍歷”是任何類(lèi)型均有的操作,對(duì)線(xiàn)性結(jié)構(gòu)而言,只有一條搜索路徑(因?yàn)槊總€(gè)結(jié)點(diǎn)均只有一個(gè)后繼),故不需要另加討論。而二叉樹(shù)是非線(xiàn)性結(jié)構(gòu), 每個(gè)結(jié)點(diǎn)有兩個(gè)后繼
14、,則存在如何遍歷即按什么樣的搜索路徑遍歷的問(wèn)題。 對(duì)“二叉樹(shù)”而言,可以有三條搜索路徑:1先上后下的按層次遍歷;2.先左(子樹(shù))后右(子樹(shù))的遍歷,若D為訪(fǎng)問(wèn)根結(jié)點(diǎn)有DLR,LDR,LRD3先右(子樹(shù))后左(子樹(shù))的遍歷。有DRL,RDL, RLD二、按層次遍歷二叉樹(shù) 實(shí)現(xiàn)方法:從上層到下層,每層中從左側(cè)到右側(cè)依次訪(fǎng)問(wèn)每個(gè)結(jié)點(diǎn)。下面我們將給出一棵二叉樹(shù)及其按層次順序訪(fǎng)問(wèn)其中每個(gè)結(jié)點(diǎn)的遍歷序列。按層次遍歷該二叉樹(shù)的序列為: A B E C F D G HABCDEFGH二叉樹(shù)的順序存儲(chǔ)表示時(shí)的層次遍歷實(shí)現(xiàn)上例的物理結(jié)構(gòu)邏輯圖為:A B C D E F G H1. ? 按層次遍歷的算法思想和核心語(yǔ)
15、句2. ? 求每一層結(jié)點(diǎn)的個(gè)數(shù)和樹(shù)的深度3. ? 統(tǒng)計(jì)n0,n1,n2結(jié)點(diǎn)的個(gè)數(shù)4. ? 求樹(shù)的最左邊結(jié)點(diǎn)或最右邊結(jié)點(diǎn)二叉樹(shù)的鏈?zhǔn)酱鎯?chǔ)表示時(shí)的層次遍歷實(shí)現(xiàn)上例的物理結(jié)構(gòu)邏輯圖為: A1. ? 求每一層結(jié)點(diǎn)的個(gè)數(shù)和樹(shù)的深度2. ? 統(tǒng)計(jì)n0,n1,n2結(jié)點(diǎn)的個(gè)數(shù) B C D E F G HT按層次遍歷的算法思想: 可借助于一隊(duì)列,根結(jié)點(diǎn)入隊(duì),隊(duì)列元素出隊(duì)時(shí)訪(fǎng)問(wèn),同時(shí)若存在孩子結(jié)點(diǎn)則孩子結(jié)點(diǎn)入隊(duì), 循環(huán)到隊(duì)空結(jié)束.三、先左后右的遍歷算法先(根)序的遍歷算法中(根)序的遍歷算法后(根)序的遍歷算法 若二叉樹(shù)為空樹(shù),則空操作;否則,(1)訪(fǎng)問(wèn)根結(jié)點(diǎn);(2)先序遍歷左子樹(shù);(3)先序遍歷右子樹(shù)。先(根)
16、序的遍歷算法:遞歸算法的函數(shù)(二叉鏈表為存儲(chǔ)結(jié)構(gòu))void Preorder (BiTree T, void( *visit)(TElemType& e) / 先序遍歷二叉樹(shù) 1 if (T) 2 visit(T-data); / 訪(fǎng)問(wèn)根結(jié)點(diǎn)3 Preorder(T-lchild, visit); / 遍歷左子樹(shù)4 Preorder(T-rchild, visit);/ 遍歷右子樹(shù)5 6 ABCDEFGD L RTD L RD L RABED L RD L RDLRDLRCFDG先序遍歷結(jié)果:ABCDEFGT 若二叉樹(shù)為空樹(shù),則空操作;否則,(1)中序遍歷左子樹(shù);(2)訪(fǎng)問(wèn)根結(jié)點(diǎn);(3)中序遍
17、歷右子樹(shù)。中(根)序的遍歷算法:void Inorder (BiTree T, void( *visit)(TElemType& e) / 中序遍歷二叉樹(shù) 1 if (T) 2 Inreorder(T-lchild, visit); / 遍歷左子樹(shù)3 visit(T-data); / 訪(fǎng)問(wèn)根結(jié)點(diǎn)4 Inreorder(T-rchild, visit);/ 遍歷右子樹(shù)5 6 ABCDEFGL D RTL D RL D RABEL D RL D RLDRLDRCFDG中序遍歷結(jié)果:BDCAGFET 若二叉樹(shù)為空樹(shù),則空操作;否則,(1)后序遍歷左子樹(shù);(2)后序遍歷右子樹(shù);(3)訪(fǎng)問(wèn)根結(jié)點(diǎn)。后(根
18、)序的遍歷算法:void Postorder (BiTree T, void( *visit)(TElemType& e) / 后序遍歷二叉樹(shù) if (T) Postreorder(T-lchild, visit); / 遍歷左子樹(shù) Postreorder(T-rchild, visit);/ 遍歷右子樹(shù) visit(T-data); / 訪(fǎng)問(wèn)根結(jié)點(diǎn) ABCDEFGHK例如:先序序列: A B C D E F G H K中序序列: B D C A H G K F E后序序列: D C B H K G F E A 注意: 教材中的遞歸算法(算法6.1)與 本課件算法略有區(qū)別,請(qǐng)注意以下幾 點(diǎn):
19、1. 函數(shù)類(lèi)型(void 和int) 2. if (PreOrderTraverse(T-Lchild,Visit) 斷點(diǎn)在擴(kuò)弧內(nèi) 3. 結(jié)果完全相同有關(guān)樹(shù)的遍歷算法的幾個(gè)問(wèn)題:1. 有關(guān)二叉樹(shù)的很多操作(如查找某個(gè)結(jié)點(diǎn)等)都可以將遍歷算 法作為核心算法,只需修改Visit函數(shù).2.遍歷算法的原操作為訪(fǎng)問(wèn)結(jié)點(diǎn),因此遍歷n個(gè)結(jié)點(diǎn)的二叉樹(shù),其時(shí)間復(fù)雜度為O(n)3. 所需輔助空間為棧的最大容量,即為樹(shù)的深度,最好情況為完全二叉樹(shù) log2n +1,而最壞情況為單支樹(shù) n ,因此時(shí)間復(fù)雜度為O(n).4. 遍歷結(jié)果都是線(xiàn)性序列有關(guān)樹(shù)的計(jì)數(shù)問(wèn)題:1. 例: 已知結(jié)點(diǎn)的二遍歷序列 前序序列: A B C
20、 D E F G 中序序列: C B E D A F G 畫(huà)出二叉樹(shù) 2. ?已知中序和后序序列,畫(huà)出二叉樹(shù)四.中序非遞歸遍歷算法(棧的應(yīng)用)中序遍歷示意圖算法一:Status InorderTraverse(Bitree T,Status(*Visit)(TElemType e) InitStack(S); Push(S,T); while(!StackEmpty(S) while(GetTop(S,p) & p) Push(S,p-lchild);Pop(S,p);if (!StackEmpty(S) Pop(S,p); if(!Visit(p-data) return ERROR; Pu
21、sh(S,p-rchild); return OK;Status InorderTraverse(Bitree T,Status(*Visit)(TElemType e) InitStack(S); p=T; while(p|!StackEmpty(S) if(p) Push(S,p); p=p-lchild; else Pop(S,p); if(!Visit(p-data) return ERROR; p=p-rchild; return OK;算法二:五、遍歷算法的應(yīng)用舉例2、統(tǒng)計(jì)二叉樹(shù)中葉子結(jié)點(diǎn)的個(gè)數(shù)(先序遍歷)3、求二叉樹(shù)的深度(后序遍歷)1、輸入結(jié)點(diǎn)值,構(gòu)造二叉樹(shù) (先序遍歷)1、輸
22、入結(jié)點(diǎn)值,構(gòu)造二叉樹(shù)算法基本思想: 先序(或中序或后序)遍歷二叉樹(shù),讀入一個(gè)字符,若讀入字符為空,則二叉樹(shù)為空,若讀入字符非空,則生成一個(gè)結(jié)點(diǎn)。將算法中“訪(fǎng)問(wèn)結(jié)點(diǎn)”的操作改為:生成一個(gè)結(jié)點(diǎn),輸入結(jié)點(diǎn)的值。Status CreateBiTree (BiTree &T) scanf( &ch ) ; if (ch) T=NULL; else if(!(T=(BiTNode *)malloc(sizeof(BiTNode) exit(OVERFLOW); T-data=ch; /生成根結(jié)點(diǎn) CreateBiTree( T-lchild); /構(gòu)造左子樹(shù) CreateBiTree( T-rchild)
23、; /構(gòu)造右子樹(shù) return(OK); / CreateBiTree2、統(tǒng)計(jì)二叉樹(shù)中葉子結(jié)點(diǎn)的個(gè)數(shù)算法基本思想: 先序(或中序或后序)遍歷二叉樹(shù),在遍歷過(guò)程中查找葉子結(jié)點(diǎn),并計(jì)數(shù)。由此,需在遍歷算法中增添一個(gè)“計(jì)數(shù)”的參數(shù),并將算法中“訪(fǎng)問(wèn)結(jié)點(diǎn)”的操作改為:若是葉子,則計(jì)數(shù)器增1。void CountLeaf (BiTree T, int& count) if ( T ) if (!T-lchild)& (!T-rchild) count+; / 對(duì)葉子結(jié)點(diǎn)計(jì)數(shù) CountLeaf( T-lchild, count); CountLeaf( T-rchild, count); / if /
24、CountLeaf3、求二叉樹(shù)的深度(后序遍歷)算法基本思想: 從二叉樹(shù)深度的定義可知,二叉樹(shù)的深度應(yīng)為其左、右子樹(shù)深度的最大值加1。由此,需先分別求得左、右子樹(shù)的深度,算法中“訪(fǎng)問(wèn)結(jié)點(diǎn)”的操作為:求得左、右子樹(shù)深度的最大值,然后加1 。 首先分析二叉樹(shù)的深度和它的左、右子樹(shù)深度之間的關(guān)系。int Depth (BiTree T ) / 返回二叉樹(shù)的深度 if ( !T ) depthval = 0; else depthLeft = Depth( T-lchild ); depthRight= Depth( T-rchild ); depthval = 1 + (depthLeft dept
25、hRight ? depthLeft : depthRight); return depthval;線(xiàn)索二叉樹(shù) 何謂線(xiàn)索二叉樹(shù)? 線(xiàn)索鏈表的遍歷算法 如何建立線(xiàn)索鏈表?一、何謂線(xiàn)索二叉樹(shù)?問(wèn)題的引入:遍歷二叉樹(shù)的結(jié)果是,求得結(jié)點(diǎn)的一個(gè)線(xiàn)性序列。ABCDEFGHK例如:先序序列: A B C D E F G H K中序序列: B D C A H G K F E后序序列: D C B H K G F E A指向該線(xiàn)性序列中的“前驅(qū)”和“后繼” 的指針,稱(chēng)作“線(xiàn)索” 與其相應(yīng)的二叉樹(shù),稱(chēng)作 “線(xiàn)索二叉樹(shù)”包含 “線(xiàn)索” 的存儲(chǔ)結(jié)構(gòu),稱(chēng)作 “線(xiàn)索鏈表”A B C D E F G H K D C B E
26、 對(duì)線(xiàn)索鏈表中結(jié)點(diǎn)的約定: 在二叉鏈表的結(jié)點(diǎn)中增加兩個(gè)標(biāo)志域,并作如下規(guī)定:若該結(jié)點(diǎn)的左子樹(shù)不空,則Lchild域的指針指向其左子樹(shù), 且左標(biāo)志域的值為“指針 Link”或0; 否則,Lchild域的指針指向其“前驅(qū)”, 且左標(biāo)志的值為“線(xiàn)索 Thread”或1 。若該結(jié)點(diǎn)的右子樹(shù)不空,則rchild域的指針指向其右子樹(shù), 且右標(biāo)志域的值為 “指針 Link”或0;否則,rchild域的指針指向其“后繼”, 且右標(biāo)志的值為“線(xiàn)索 Thread”或1。 如此定義的二叉樹(shù)的存儲(chǔ)結(jié)構(gòu)稱(chēng)作“線(xiàn)索鏈表”。線(xiàn)索鏈表的結(jié)點(diǎn)結(jié)構(gòu) ltag和rtag是增加的兩個(gè)標(biāo)志域,用來(lái)區(qū)分結(jié)點(diǎn)的左、右指針域是指向其左、右孩
27、子的指針,還是指向其前驅(qū)或后繼的線(xiàn)索。lchildLTagdataRTagrchildtypedef struct BiThrNod TElemType data; struct BiThrNode *lchild, *rchild; / 左右指針 PointerThr LTag, RTag; / 左右標(biāo)志 BiThrNode, *BiThrTree;線(xiàn)索鏈表的類(lèi)型描述: typedef enum Link, Thread PointerThr; / Link=0:指針,Thread=1:線(xiàn)索ABCDEFGHI例如:一中序線(xiàn)索鏈表的存儲(chǔ)結(jié)構(gòu)二、線(xiàn)索鏈表的遍歷算法: for ( p = firs
28、tNode(T); p; p = Succ(p) ) Visit (p);由于在線(xiàn)索鏈表中添加了遍歷中得到的“前驅(qū)”和“后繼”的信息,從而簡(jiǎn)化了遍歷的算法。(已得到一線(xiàn)性序列)例如: 對(duì)中序線(xiàn)索鏈表的遍歷算法 中序遍歷的第一個(gè)結(jié)點(diǎn) ? 在中序線(xiàn)索化鏈表中結(jié)點(diǎn)的后繼 ?左子樹(shù)上處于“最左下”(沒(méi)有左子樹(shù))的結(jié)點(diǎn)。(注意:從根結(jié)點(diǎn)進(jìn)入)若無(wú)右子樹(shù),則為后繼線(xiàn)索所指結(jié)點(diǎn);否則為對(duì)其右子樹(shù)進(jìn)行中序遍歷時(shí)訪(fǎng)問(wèn)的第一個(gè)結(jié)點(diǎn)。void InOrderTraverse_Thr(BiThrTree T, void (*Visit)(TElemType e) p = T-lchild; / p指向根結(jié)點(diǎn) whil
29、e (p != T) / 空樹(shù)或遍歷結(jié)束時(shí),p=T while (p-LTag=Link) p = p-lchild; / 第一個(gè)結(jié)點(diǎn) Visit(p-data); while (p-RTag=Thread & p - rchild!=T) p = p-rchild; Visit(p-data); / 訪(fǎng)問(wèn)后繼結(jié)點(diǎn) p = p-rchild; / p進(jìn)至其右子樹(shù)根 / InOrderTraverse_Thr中序第一個(gè)結(jié)點(diǎn)為最左下的結(jié)點(diǎn) 在中序遍歷過(guò)程中修改結(jié)點(diǎn)的左、右指針域,以保存當(dāng)前訪(fǎng)問(wèn)結(jié)點(diǎn)的“前驅(qū)”和“后繼”信息。遍歷過(guò)程中,附設(shè)指針pre, 并始終保持指針pre指向當(dāng)前訪(fǎng)問(wèn)的、指針p所指
30、結(jié)點(diǎn)的前驅(qū)。三、如何建立線(xiàn)索鏈表?樹(shù)的線(xiàn)索化算法思想:void InThreading(BiThrTree p) if (p) / 對(duì)以p為根的非空二叉樹(shù)進(jìn)行線(xiàn)索化 InThreading(p-lchild); / 左子樹(shù)線(xiàn)索化 if (!p-lchild) / 建前驅(qū)線(xiàn)索 p-LTag = Thread; p-lchild = pre; if (!pre-rchild) / 建后繼線(xiàn)索 pre-RTag = Thread; pre-rchild = p; pre = p; / 保持 pre 指向 p 的前驅(qū) InThreading(p-rchild); / 右子樹(shù)線(xiàn)索化 / if / InT
31、hreading對(duì)中序遞歸遍歷算法Visit部分改動(dòng)既可 Status InOrderThreading(BiThrTree &Thrt, BiThrTree T) / 構(gòu)建中序線(xiàn)索鏈表 if (!(Thrt = (BiThrTree)malloc(sizeof( BiThrNode) exit (OVERFLOW);Thrt-LTag = Link; Thrt-RTag =Thread; Thrt-rchild = Thrt; if (!T) Thrt-lchild = Thrt; else Thrt-lchild = T; pre = Thrt; InThreading(T); /調(diào)用線(xiàn)索
32、化算法 pre-rchild = Thrt; pre-RTag = Thread; Thrt-rchild = pre; return OK; / InOrderThreading 6.4 樹(shù)和森林 6.4.1 樹(shù)的三種存儲(chǔ)結(jié)構(gòu)一、雙親表示法二、孩子鏈表表示法三、樹(shù)的二叉鏈表(孩子-兄弟) 存儲(chǔ)表示法ABCDEFG0 A -11 B 02 C 03 D 04 E 2 5 F 26 G 5r=0n=7data parent一、雙親表示法: typedef struct PTNode Elem data; int parent; / 雙親位置域 PTNode; data parent#define
33、 MAX_TREE_SIZE 100結(jié)點(diǎn)結(jié)構(gòu):C語(yǔ)言的類(lèi)型描述:typedef struct PTNode nodes MAX_TREE_SIZE; int r, n; / 根結(jié)點(diǎn)的位置和結(jié)點(diǎn)個(gè)數(shù) PTree;樹(shù)結(jié)構(gòu):ABCDEFG0 A -11 B 02 C 03 D 04 E 25 F 26 G 4r=0n=7 data parent firstchild 1 2 34 56二、孩子鏈表表示法:-1000224typedef struct CTNode int child; struct CTNode *next; *ChildPtr;孩子結(jié)點(diǎn)結(jié)構(gòu): child nextC語(yǔ)言的類(lèi)型描述:
34、 typedef struct Elem data; ChildPtr firstchild; / 孩子鏈的頭指針 CTBox;雙親結(jié)點(diǎn)結(jié)構(gòu) data firstchildtypedef struct CTBox nodesMAX_TREE_SIZE; int n, r; / 結(jié)點(diǎn)數(shù)和根結(jié)點(diǎn)的位置 CTree;樹(shù)結(jié)構(gòu):三、樹(shù)的二叉鏈表 (孩子-兄弟)存儲(chǔ)表示法ABCDEFG AB C E D F Groot AB C E D F G typedef struct CSNode Elem data; struct CSNode *firstchild, *nextsibling; CSNode,
35、 *CSTree;C語(yǔ)言的類(lèi)型描述:結(jié)點(diǎn)結(jié)構(gòu): firstchild data nextsibling6.4.2 森林和二叉樹(shù)的對(duì)應(yīng)關(guān)系設(shè)森林 F = ( T1, T2, , Tn ); T1 = (root,t11, t12, , t1m);二叉樹(shù) B =( LBT, Node(root), RBT );由森林轉(zhuǎn)換成二叉樹(shù)的轉(zhuǎn)換規(guī)則為:若 F = ,則 B = ;否則, 由 ROOT( T1 ) 對(duì)應(yīng)得到 Node(root); 由 (t11, t12, , t1m ) 對(duì)應(yīng)得到 LBT; 由 (T2, T3, Tn ) 對(duì)應(yīng)得到 RBT。 B C DE F G H I J K B E C
36、F D G H I J K例如:由二叉樹(shù)轉(zhuǎn)換為森林的轉(zhuǎn)換規(guī)則為:若 B = , 則 F = ;否則,由 Node(root) 對(duì)應(yīng)得到 ROOT( T1 );由LBT 對(duì)應(yīng)得到 ( t11, t12, ,t1m);由RBT 對(duì)應(yīng)得到 (T2, T3, , Tn)。例如: B E C F D G H I J K B C DE F G H I J K 由此,樹(shù)的各種操作均可對(duì)應(yīng)二叉樹(shù)的操作來(lái)完成。 應(yīng)當(dāng)注意的是,和樹(shù)對(duì)應(yīng)的二叉樹(shù),其左、右子樹(shù)的概念已改變?yōu)椋?左是孩子,右是兄弟。6.4.3 樹(shù)和森林的遍歷一、樹(shù)的遍歷二、森林的遍歷樹(shù)的遍歷可有三條搜索路徑:按層次遍歷:先根(次序)遍歷:后根(次序)
37、遍歷: 若樹(shù)不空,則先訪(fǎng)問(wèn)根結(jié)點(diǎn),然后依次先根遍歷各棵子樹(shù)。 若樹(shù)不空,則先依次后根遍歷各棵子樹(shù),然后訪(fǎng)問(wèn)根結(jié)點(diǎn)。 若樹(shù)不空,則自上而下自左至右訪(fǎng)問(wèn)樹(shù)中每個(gè)結(jié)點(diǎn)。一、樹(shù)的遍歷 先根遍歷時(shí)頂點(diǎn)的訪(fǎng)問(wèn)次序:A B C E F G D 后根遍歷時(shí)頂點(diǎn)的訪(fǎng)問(wèn)次序:B E G F C D A 層次遍歷時(shí)頂點(diǎn)的訪(fǎng)問(wèn)次序:A B C D E F G ABCDEFG B C DE F G H I J K1森林中第一棵樹(shù)的根結(jié)點(diǎn);2森林中第一棵樹(shù)的子樹(shù)森林;3森林中其它樹(shù)構(gòu)成的森林。森林由三部分構(gòu)成:二、森林的遍歷 若森林不空,則訪(fǎng)問(wèn)森林中第一棵樹(shù)的根結(jié)點(diǎn);先序遍歷森林中第一棵樹(shù)的子樹(shù)森林;先序遍歷森林中(除第
38、一棵樹(shù)之外)其 余樹(shù)構(gòu)成的森林。1. 先序遍歷森林的遍歷即:依次從左至右對(duì)森林中的每一棵樹(shù)進(jìn)行先根遍歷。中序遍歷 若森林不空,則:中序遍歷森林中第一棵樹(shù)的子樹(shù)森林;訪(fǎng)問(wèn)森林中第一棵樹(shù)的根結(jié)點(diǎn);中序遍歷森林中(除第一棵樹(shù)之外)其 余樹(shù)構(gòu)成的森林。即:依次從左至右對(duì)森林中的每一棵樹(shù)進(jìn)行后根遍歷。 B C DE F G H I J K例如: 先序遍歷時(shí)頂點(diǎn)的訪(fǎng)問(wèn)次序:B E F C D G H I J K 后序遍歷時(shí)頂點(diǎn)的訪(fǎng)問(wèn)次序:E F B C I J K H G D 樹(shù)的遍歷和二叉樹(shù)遍歷的對(duì)應(yīng)關(guān)系 ?先根遍歷后根遍歷樹(shù)二叉樹(shù)(轉(zhuǎn)換)森林先序遍歷先序遍歷中序遍歷中序遍歷6.6 哈 夫 曼 樹(shù) 與
39、哈 夫 曼 編 碼 最優(yōu)樹(shù)(哈夫曼樹(shù))的定義 如何構(gòu)造最優(yōu)樹(shù) 前綴編碼 哈夫曼編碼 一、最優(yōu)樹(shù)的定義樹(shù)的路徑長(zhǎng)度定義為: 樹(shù)中每個(gè)結(jié)點(diǎn)的路徑長(zhǎng)度之和。 結(jié)點(diǎn)的路徑長(zhǎng)度定義為: 從根結(jié)點(diǎn)到該結(jié)點(diǎn)的路徑上 分支的數(shù)目。結(jié)點(diǎn)的帶權(quán)路徑長(zhǎng)度定義為: 從根結(jié)點(diǎn)到該結(jié)點(diǎn)的路徑長(zhǎng)度與 結(jié)點(diǎn)上權(quán)的乘積。 樹(shù)的帶權(quán)路徑長(zhǎng)度定義為: 樹(shù)中所有葉子結(jié)點(diǎn)的帶權(quán)路徑長(zhǎng)度之和 WPL(T) = wklk (對(duì)所有葉子結(jié)點(diǎn))。 在所有含 n 個(gè)葉子結(jié)點(diǎn)、并帶相同權(quán)值的 m 叉樹(shù)中,必存在一棵其帶權(quán)路徑長(zhǎng)度取最小值的樹(shù),稱(chēng)為“最優(yōu)樹(shù)”。例如:WPL(T)= 72+52+22+42 =36WPL(T)= 71+52+23+43
40、=35 WPL(T)= 73+53+42+21 =46 根據(jù)給定的 n 個(gè)權(quán)值 w1 , w2 , , wn,構(gòu)造 n 棵二叉樹(shù)的集合(森林) F = T1, T2, , Tn,其中每棵二叉樹(shù)Ti中均只含一個(gè)帶權(quán)值 為 wi 的根結(jié)點(diǎn), 其左、右子樹(shù)為空樹(shù);二、如何構(gòu)造最優(yōu)樹(shù)(二叉哈夫曼樹(shù))(1)(哈夫曼算法) 以二叉樹(shù)為例: 在 F 中選取其根結(jié)點(diǎn)的權(quán)值為最 小的兩棵二叉樹(shù),分別作為左、 右子樹(shù)構(gòu)造一棵新的二叉樹(shù),并 置這棵新的二叉樹(shù)根結(jié)點(diǎn)的權(quán)值 為其左、右子樹(shù)根結(jié)點(diǎn)的權(quán)值之 和;(2) 從F中刪去這兩棵樹(shù),同時(shí)加入 剛生成的新樹(shù)到F; 重復(fù) (2) 和 (3) 兩步,直至 F 中只含一棵樹(shù)
41、為止。這棵樹(shù)便是哈夫曼樹(shù)(3)(4)9例如: 已知權(quán)值 W= 5, 6, 2, 9, 7 56275276976713952767139527952716671329注意: 初始森林中的n棵二叉樹(shù),每棵樹(shù)有一個(gè)孤立的結(jié)點(diǎn),它們既是根,又是葉子 n個(gè)葉子的哈夫曼樹(shù)要經(jīng)過(guò)n-1次合并,產(chǎn)生n-1個(gè)新結(jié)點(diǎn)。最終求得的哈夫曼樹(shù)中共有2n-1個(gè)結(jié)點(diǎn)。 哈夫曼樹(shù)是嚴(yán)格的二叉樹(shù),沒(méi)有度數(shù)為1的分支結(jié)點(diǎn)。三. 前綴編碼 在電文傳輸中,需要將電文中出現(xiàn)的每個(gè)字符進(jìn)行二進(jìn)制編碼。在設(shè)計(jì)編碼時(shí)需要遵守兩個(gè)原則:(1)發(fā)送方傳輸?shù)亩M(jìn)制編碼,到接收方解碼后必須具有唯一性,即解碼結(jié)果與發(fā)送方發(fā)送的電文完全一樣;(2)發(fā)
42、送的二進(jìn)制編碼盡可能地短。下面我們介紹兩種編碼的方式。 1. 等長(zhǎng)編碼 這種編碼方式的特點(diǎn): 每個(gè)字符的編碼長(zhǎng)度相同。 設(shè)字符集只含有4個(gè)字符A,B,C,D,用兩位二進(jìn)制表示的編碼分別為00,01,10,10,11。若現(xiàn)在電文為:ABACCDA,則應(yīng)發(fā)送二進(jìn)制序列:00010010101100,總長(zhǎng)度為14位。當(dāng)接收方接收到這段電文后,將按兩位一段進(jìn)行譯碼。這種編碼的特點(diǎn):譯碼簡(jiǎn)單且具有唯一性,但編碼長(zhǎng)度并不是最短的。2. 不等長(zhǎng)編碼 在傳送電文時(shí),為了使其二進(jìn)制位數(shù)盡可能地少,可以將每個(gè)字符的編碼設(shè)計(jì)為不等長(zhǎng)的,使用頻度較高的字符分配一個(gè)相對(duì)比較短的編碼,使用頻度較低的字符分配一個(gè)比較長(zhǎng)的編
43、碼。例如,可以為A,B,C,D四個(gè)字符分別分配0,00,1,01,并可將上述電文用二進(jìn)制序列:000011010發(fā)送,其長(zhǎng)度只有9個(gè)二進(jìn)制位,但隨之帶來(lái)了一個(gè)問(wèn)題,接收方接到這段電文后無(wú)法進(jìn)行譯碼,因?yàn)闊o(wú)法斷定前面4個(gè)0是4個(gè)A,1個(gè)B、2個(gè)A,還是2個(gè)B,即譯碼不唯一(二義性),因此這種編碼方法不可使用。3. 前綴編碼 若要設(shè)計(jì)長(zhǎng)短不等的編碼,則必須是任一字符的編碼不是另一字符的編碼的前綴,這樣的編碼為前綴編碼. 例如:DABC111000編碼: A(0) B(10) C(110) D(111)出現(xiàn)頻率高的字符離根結(jié)點(diǎn)近(編碼長(zhǎng)度短)出現(xiàn)頻率低的字符離根結(jié)點(diǎn)遠(yuǎn)(編碼長(zhǎng)度長(zhǎng)) 利用哈夫曼樹(shù)可以
44、構(gòu)造一種不等長(zhǎng)的二進(jìn)制編碼,并且構(gòu)造所得的哈夫曼編碼是一種最優(yōu)前綴編碼,即使所傳電文的總長(zhǎng)度最短(壓縮)。稱(chēng)為哈夫曼編碼四.哈夫曼編碼(1)利用字符集中每個(gè)字符的使用頻率作為權(quán)值構(gòu)造一個(gè)哈夫曼樹(shù);(2)從根結(jié)點(diǎn)開(kāi)始,為到每個(gè)葉子結(jié)點(diǎn)路徑上的左分支賦予0,右分支賦予1,并從根到葉子方向形成該葉子結(jié)點(diǎn)的編碼。哈夫曼編碼的構(gòu)造方法 :例如: 假設(shè)有一個(gè)電文字符集中有8個(gè)字符,每個(gè)字符的使用頻率分別為0.05,0.29,0.07,0.08,0.14,0.23,0.03,0.11,現(xiàn)以此為例設(shè)計(jì)哈夫曼編碼。 為方便計(jì)算,將所有字符的頻度乘以100,使其轉(zhuǎn)換成整型數(shù)值集合,得到5,29,7,8,14,23,3,11; 哈夫曼編碼設(shè)計(jì)如下圖:115297814233100011558290001118421900011100010011001111110111111010哈夫曼樹(shù)的存儲(chǔ)結(jié)構(gòu) 用一個(gè)大小為2n-1的向量來(lái)存儲(chǔ)哈夫曼樹(shù)中的結(jié)點(diǎn),其存儲(chǔ)結(jié)構(gòu)為: typedef struct /結(jié)點(diǎn)類(lèi)
溫馨提示
- 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶(hù)所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶(hù)上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶(hù)上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶(hù)因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 物流與信息技術(shù)整合的策略試題及答案
- 加強(qiáng)信息素養(yǎng)的圖書(shū)管理員試題及答案
- 2024年計(jì)算機(jī)二級(jí)考試全科試題及答案
- 注冊(cè)會(huì)計(jì)師在企業(yè)中的角色試題及答案
- 寵物殯葬師社會(huì)責(zé)任感試題及答案
- 投資咨詢(xún)工程師戰(zhàn)略選擇試題及答案
- 生態(tài)位與生物多樣性試題及答案
- 學(xué)習(xí)投資理論的有效方法試題及答案
- 黑龍江民族職業(yè)學(xué)院《教師工作實(shí)務(wù)》2023-2024學(xué)年第二學(xué)期期末試卷
- 黑龍江省伊春市伊春區(qū)2025年數(shù)學(xué)三下期末質(zhì)量跟蹤監(jiān)視模擬試題含解析
- 受限空間作業(yè)施工方案
- (一模)2025年廣州市普通高中畢業(yè)班綜合測(cè)試(一)政治試卷(含答案)
- 2025年骨科入科考試題及答案
- 2025上半年江西贛州市人民醫(yī)院招考聘用工作人員自考難、易點(diǎn)模擬試卷(共500題附帶答案詳解)
- 2025年武漢鐵路橋梁職業(yè)學(xué)院?jiǎn)握新殬I(yè)技能測(cè)試題庫(kù)必考題
- 2025年度家暴離婚協(xié)議書(shū)范本制作與使用
- 課件:《魯濱遜漂流記》
- 2025護(hù)理十大安全目標(biāo)
- 《遺傳疾病概述》課件
- 《醫(yī)養(yǎng)結(jié)合事業(yè)發(fā)展探究的國(guó)內(nèi)外文獻(xiàn)綜述》4400字
- 水電施工機(jī)械新能源化的可行性分析與應(yīng)用研究
評(píng)論
0/150
提交評(píng)論