數(shù)據(jù)結(jié)構(gòu)第六章樹(shù)課件_第1頁(yè)
數(shù)據(jù)結(jié)構(gòu)第六章樹(shù)課件_第2頁(yè)
數(shù)據(jù)結(jié)構(gòu)第六章樹(shù)課件_第3頁(yè)
數(shù)據(jù)結(jié)構(gòu)第六章樹(shù)課件_第4頁(yè)
數(shù)據(jù)結(jié)構(gòu)第六章樹(shù)課件_第5頁(yè)
已閱讀5頁(yè),還剩175頁(yè)未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說(shuō)明:本文檔由用戶(hù)提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

1、第六章 樹(shù)和二叉樹(shù)6.1 樹(shù)的類(lèi)型定義6.2 二叉樹(shù)6.3 遍歷和線索二叉樹(shù)6.4 樹(shù)和森林6.5 樹(shù)與等價(jià)問(wèn)題6.6 哈夫曼樹(shù)及其應(yīng)用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( )T1T3T2樹(shù)根例如:B(E, F(K, L), C(G), D(H, I, J(M)樹(shù)具有下面兩

2、個(gè)特點(diǎn):(1)樹(shù)的根結(jié)點(diǎn)沒(méi)有前驅(qū)結(jié)點(diǎn),除根結(jié)點(diǎn)之外的所有結(jié)點(diǎn)有且只有一個(gè)前驅(qū)結(jié)點(diǎn)。(2)樹(shù)中所有結(jié)點(diǎn)可以有零個(gè)或多個(gè)后繼結(jié)點(diǎn)。() 有確定的根;() 樹(shù)根和子樹(shù)根之間為有向關(guān)系。有向樹(shù):有序樹(shù):子樹(shù)之間存在確定的次序關(guān)系。無(wú)序樹(shù):子樹(shù)之間不存在確定的次序關(guān)系?;?本 術(shù) 語(yǔ)結(jié)點(diǎn)(node)結(jié)點(diǎn)的度(degree)分支(branch)結(jié)點(diǎn)葉(leaf)結(jié)點(diǎn)孩子(child)結(jié)點(diǎn)雙親(parent)結(jié)點(diǎn)兄弟(sibling)結(jié)點(diǎn)祖先(ancestor)結(jié)點(diǎn)子孫(descendant)結(jié)點(diǎn)結(jié)點(diǎn)所處層次(level)樹(shù)的高度(depth)樹(shù)的度(degree)(從根到結(jié)點(diǎn)的)路徑:結(jié)點(diǎn)的層次:樹(shù)的深度

3、: 由從根到該結(jié)點(diǎn)所經(jīng)分支和結(jié)點(diǎn)構(gòu)成ABCDEFGHIJMKL假設(shè)根結(jié)點(diǎn)的層次為1,第l 層的結(jié)點(diǎn)的子樹(shù)根結(jié)點(diǎn)的層次為l+1樹(shù)中葉子結(jié)點(diǎn)所在的最大層次任何一棵非空樹(shù)是一個(gè)二元組 Tree = (root,F(xiàn))其中:root 被稱(chēng)為根結(jié)點(diǎn), F 被稱(chēng)為子樹(shù)森林森林:是 m(m0)棵互不相交的樹(shù)的集合ArootBEFKLCGDHIJMF對(duì)比樹(shù)型結(jié)構(gòu)和線性結(jié)構(gòu)的結(jié)構(gòu)特點(diǎ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è)后繼)6.2 二叉樹(shù)的類(lèi)型定義 二叉樹(shù)或?yàn)榭諛?shù);或是由

4、一個(gè)根結(jié)點(diǎn)加上兩棵分別稱(chēng)為左子樹(shù)和右子樹(shù)的、互不交的二叉樹(shù)組成。ABCDEFGHK根結(jié)點(diǎn)左子樹(shù)右子樹(shù)EF二叉樹(shù)的五種基本形態(tài):N空樹(shù)只含根結(jié)點(diǎn)NNNLRR右子樹(shù)為空樹(shù)L左子樹(shù)為空樹(shù)左右子樹(shù)均不為空樹(shù)二叉樹(shù)的重要特性 性質(zhì) 1 : 在二叉樹(shù)的第 i 層上至多有2i-1 個(gè)結(jié)點(diǎn)。 (i1)用歸納法證明: 歸納基: 歸納假設(shè): 歸納證明:i = 1 層時(shí),只有一個(gè)根結(jié)點(diǎn), 2i-1 = 20 = 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)證明:

5、 基于上一條性質(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由此, n0 = 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)。12345678910111213141

6、5abcdefghij 性質(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)。6.2.4 二叉樹(shù)的存儲(chǔ)二、二叉樹(shù)的鏈?zhǔn)?存儲(chǔ)表示一、 二叉樹(shù)的順序 存儲(chǔ)表示一、 二叉樹(shù)的順序存儲(chǔ)表示二叉樹(shù)的順序存儲(chǔ),就是用一組連續(xù)的存儲(chǔ)單元存放二叉樹(shù)中的結(jié)點(diǎn)。一般是按照二叉樹(shù)結(jié)點(diǎn)從上至下、從左到右的順序存儲(chǔ)。例如: A B D C E F 0

7、 1 2 3 4 5 6 7 8 9 10 11 12 13ABCDEF1401326#define MAXNODE 30/*二叉樹(shù)的最大結(jié)點(diǎn)數(shù)*/typedef ELEMTYPE SqBiTreeMAXNODE;/* 0號(hào)單元存放根結(jié)點(diǎn) */SqBiTree bt;即將bt定義為含有MAXNODE個(gè)elemtype類(lèi)型元素的一維數(shù)組。 完全二叉樹(shù)和滿(mǎn)二叉樹(shù)適合順序存儲(chǔ)二、二叉樹(shù)的鏈?zhǔn)酱鎯?chǔ)表示1. 二叉鏈表2三叉鏈表3雙親鏈表ADEBCFrootlchild data rchild結(jié)點(diǎn)結(jié)構(gòu):1. 二叉鏈表typedef struct BiTNode / 結(jié)點(diǎn)結(jié)構(gòu) ElemType data;

8、struct BiTNode *lchild, *rchild; / 左右孩子指針 BiTNode, *BiTree;lchild data rchild結(jié)點(diǎn)結(jié)構(gòu):C 語(yǔ)言的類(lèi)型描述如下:rootADEBCF2三叉鏈表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 r

9、child結(jié)點(diǎn)結(jié)構(gòu):C 語(yǔ)言的類(lèi)型描述如下:結(jié)點(diǎn)結(jié)構(gòu):3雙親鏈表 data parentABDCEF0B41D42C03E14A-15F36LRTagLRRRL根 typedef struct BPTNode / 結(jié)點(diǎn)結(jié)構(gòu) TElemType data; int *parent; / 指向雙親的指針 char LRTag; / 左、右孩子標(biāo)志域 BPTNode typedef struct BPTree / 樹(shù)結(jié)構(gòu) BPTNode nodesMAX_TREE_SIZE; int num_node; / 結(jié)點(diǎn)數(shù)目 int root; / 根結(jié)點(diǎn)的位置 BPTree6.3.1二叉樹(shù)的遍歷一、問(wèn)題的

10、提出二、先左后右的遍歷算法三、算法的遞歸描述四、中序遍歷算法的非遞歸描述五、遍歷算法的應(yīng)用舉例 順著某一條搜索路徑巡訪二叉樹(shù)中的結(jié)點(diǎn),使得每個(gè)結(jié)點(diǎn)均被訪問(wèn)一次,而且僅被訪問(wèn)一次。一、問(wèn)題的提出“訪問(wèn)”的含義可以很廣,如:輸出結(jié)點(diǎn)的信息等。 “遍歷”是任何類(lèi)型均有的操作,對(duì)線性結(jié)構(gòu)而言,只有一條搜索路徑(因?yàn)槊總€(gè)結(jié)點(diǎn)均只有一個(gè)后繼),故不需要另加討論。而二叉樹(shù)是非線性結(jié)構(gòu), 每個(gè)結(jié)點(diǎn)有兩個(gè)后繼,則存在如何遍歷即按什么樣的搜索路徑進(jìn)行遍歷的問(wèn)題。 對(duì)“二叉樹(shù)”而言,可以有三條搜索路徑:1先上后下的按層次遍歷;2先左(子樹(shù))后右(子樹(shù))的遍歷;3先右(子樹(shù))后左(子樹(shù))的遍歷。abcdefghij二

11、、先左后右的遍歷算法先(根)序的遍歷算法中(根)序的遍歷算法后(根)序的遍歷算法根左子樹(shù)右子樹(shù)根根根根根 若二叉樹(shù)為空樹(shù),則空操作;否則,(1)訪問(wèn)根結(jié)點(diǎn);(2)先序遍歷左子樹(shù);(3)先序遍歷右子樹(shù)。先(根)序的遍歷算法:ADBCD L RAD L RD L RBDCD L R先序遍歷序列:A B D C先序遍歷: 若二叉樹(shù)為空樹(shù),則空操作;否則,(1)中序遍歷左子樹(shù);(2)訪問(wèn)根結(jié)點(diǎn);(3)中序遍歷右子樹(shù)。中(根)序的遍歷算法:ADBCL D RBL D RL D RADCL D R中序遍歷序列:B D A C中序遍歷: 若二叉樹(shù)為空樹(shù),則空操作;否則,(1)后序遍歷左子樹(shù);(2)后序遍歷右

12、子樹(shù);(3)訪問(wèn)根結(jié)點(diǎn)。后(根)序的遍歷算法:ADBC L R DL R DL R DADCL R D后序遍歷序列: D B C A后序遍歷:B-+/a*b-efcd先序遍歷:中序遍歷:后序遍歷:層次遍歷:-+a*b-cd/ef-+a*b-cd/ef-+a*b-cd/ef-+a*b-cd/efABCDEFGHK例如:先序序列:中序序列:后序序列:A B C D E F G H KB D C A E H G K FD C B H K G F E A三、算法的遞歸描述void Preorder (BiTree T, void( *visit)(TElemType& e) / 先序遍歷二叉樹(shù) if

13、(T) visit(T-data); / 訪問(wèn)結(jié)點(diǎn) Preorder(T-lchild, visit); / 遍歷左子樹(shù) Preorder(T-rchild, visit);/ 遍歷右子樹(shù) void preorder(JD *bt) if(bt!=NULL) printf(%dt,bt-data); preorder(bt-lchild); preorder(bt-rchild); 主程序Pre( T )返回返回pre(T R);返回返回pre(T R);ACBDTBprintf(B);pre(T L);BTAprintf(A);pre(T L);ATDprintf(D);pre(T L);D

14、TCprintf(C);pre(T L);C返回T左是空返回pre(T R);T左是空返回T右是空返回T左是空返回T右是空返回pre(T R);先序序列:A B D C中序遍歷void inorder(JD *bt) if(bt!=NULL) inorder(bt-lchild); printf(%dt,bt-data); inorder(bt-rchild); 后序遍歷void postorder(JD *bt) if(bt!=NULL) postorder(bt-lchild); postorder(bt-rchild); printf(%dt,bt-data); 中序遍歷算法的非遞歸描述

15、有兩種分析(描述)方法:一、“任務(wù)書(shū)”分析方法二、“路徑”分析方法在寫(xiě)算法之前首先需定義棧的元素類(lèi)型。typedef enum Travel, Visit TaskType; / Travel = 1:遍歷, / Visit = 0:訪問(wèn) typedef struct BiTree ptr; / 指向根結(jié)點(diǎn)的指針 TaskType task; / 任務(wù)性質(zhì) ElemType;“遍歷二叉樹(shù)”包括三項(xiàng)子任務(wù):“遍歷左子樹(shù)”“遍歷右子樹(shù)”“訪問(wèn)根結(jié)點(diǎn)”void InOrder_iter( BiTree BT ) / 利用棧實(shí)現(xiàn)中序遍歷二叉樹(shù),T為指向二叉樹(shù)的根結(jié)點(diǎn)的頭指針 InitStack(S);

16、 e.ptr=BT; e.task=Travel; if(T) Push(S, e); / 布置初始任務(wù) while(!StackEmpty(S) Pop(S,e); if (e.task=Visit) visit(e.ptr); else . . . /while/InOrder_iterif(!e.ptr) / 處理非空樹(shù)的遍歷任務(wù) p=e.ptr; e.ptr=p-rchild; Push(S,e); / 最不迫切任務(wù)進(jìn)棧 e.ptr=p; e.task=Visit; Push(S,e); e.ptr=p-lchild; e.task=Travel; Push(S,e); /if voi

17、d Inorder_I(BiTree T, void (*visit) (TelemType& e) Stack *S; t = GoFarLeft(T, S); / 找到最左下的結(jié)點(diǎn) while(t) visit(t-data); if (t-rchild) else if ( !StackEmpty(S ) t = Pop(S); / 退棧 else t = NULL; / ??毡砻鞅闅v結(jié)束 / while/ Inorder_I t = GoFarLeft(t-rchild, S);BiTNode *GoFarLeft(BiTree T, Stack *S) if (!T ) return

18、 NULL; while (T-lchild ) Push(S, T); T = T-lchild; return T;中序的非遞歸算法:void inorder(JD *bt) int i=0; JD *p,*sM; p=bt; do while(p!=NULL) si+=p; p=p-lchild; if(i0) p=s-i; printf(%dt,p-data); p=p-rchild; while(i0|p!=NULL);非遞歸算法ABCDEFGpiP-A(1)ABCDEFGpiP-AP-B(2)ABCDEFGpiP-AP-BP-C(3)p=NULLABCDEFGiP-AP-B訪問(wèn):C

19、(4)pABCDEFGiP-A訪問(wèn):C B(5)ABCDEFGiP-AP-D訪問(wèn):C Bp(6)ABCDEFGiP-AP-DP-E訪問(wèn):C Bp(7)ABCDEFGiP-AP-D訪問(wèn):C B Ep(8)ABCDEFGiP-AP-DP-G訪問(wèn):C B EP=NULL(9)ABCDEFGiP-A訪問(wèn):C B E G Dp(11)ABCDEFGiP-AP-F訪問(wèn):C B E G Dp(12)ABCDEFGiP-AP-D訪問(wèn):C B E Gp(10)ABCDEFGiP-A訪問(wèn):C B E G D Fp=NULL(13)ABCDEFGi訪問(wèn):C B E G D F Ap(14)ABCDEFGi訪問(wèn):C

20、B E G D F Ap=NULL(15)層次遍歷二叉樹(shù)的層次遍歷,是指從二叉樹(shù)的第一層(根結(jié)點(diǎn))開(kāi)始,從上至下逐層遍歷,在同一層中,則按從左到右的順序?qū)Y(jié)點(diǎn)逐個(gè)訪問(wèn)。按層次遍歷所得到的結(jié)果序列為:A B C D E F Gabcdefg在進(jìn)行層次遍歷時(shí),可設(shè)置一個(gè)隊(duì)列結(jié)構(gòu),遍歷從二叉樹(shù)的根結(jié)點(diǎn)開(kāi)始,首先將根結(jié)點(diǎn)指針入隊(duì)列,然后從隊(duì)頭取出一個(gè)元素,每取一個(gè)元素,執(zhí)行下面兩個(gè)操作:(1)訪問(wèn)該元素所指結(jié)點(diǎn);(2)若該元素所指結(jié)點(diǎn)的左、右孩子結(jié)點(diǎn)非空,則將該元素所指結(jié)點(diǎn)的左孩子指針和右孩子指針順序入隊(duì)。void LevelOrder(BiTree bt/ 層次遍歷二叉樹(shù)btBiTree queue

21、MAXNODE; int front,rear;if (bt=NULL) return;Front = -1; rear=0;queuerear=bt;while(front!=rear) front+; Visite(queuefront-data); /*訪問(wèn)隊(duì)首結(jié)點(diǎn)的數(shù)據(jù)域*/ if (queuefront-rchild!=NULL) /* 將隊(duì)首結(jié)點(diǎn)的右孩結(jié)點(diǎn)入隊(duì) */ rear+; queuerear = queuefront-rchild; if (queuefront-lchild!=NULL) /* 將隊(duì)首結(jié)點(diǎn)的左孩結(jié)點(diǎn)入隊(duì) */ rear+; queuerear = queu

22、efront-lchild; 四、遍歷算法的應(yīng)用舉例2、統(tǒng)計(jì)二叉樹(shù)中葉子結(jié)點(diǎn)的個(gè)數(shù)3、求二叉樹(shù)的深度(后序遍歷)4、復(fù)制二叉樹(shù)(后序遍歷)5、建立二叉樹(shù)的存儲(chǔ)結(jié)構(gòu)1、查詢(xún)二叉樹(shù)中某個(gè)結(jié)點(diǎn)1. 在二叉樹(shù)不空的前提下,和根結(jié)點(diǎn)的元素進(jìn)行比較,若相等,則找到返回 TRUE;2. 否則在左子樹(shù)中進(jìn)行查找,若找到,則返回 TRUE;3. 否則繼續(xù)在右子樹(shù)中進(jìn)行查找,若找到,則返回 TRUE,否則返回 FALSE;Status Preorder (BiTree T, ElemType x, BiTree &p) / 若二叉樹(shù)中存在和 x 相同的元素,則 p 指向該結(jié)點(diǎn)并返回 OK,/ 否則返回 FALSE

23、 if (T) if (T-data=x) p = T; return OK, /if else return FALSE;else if (Preorder(T-lchild, x, p) return OK; else return(Preorder(T-rchild, x, p) ;/else2、統(tǒng)計(jì)二叉樹(shù)中葉子結(jié)點(diǎn)的個(gè)數(shù)算法基本思想: 先序(或中序或后序)遍歷二叉樹(shù),在遍歷過(guò)程中查找葉子結(jié)點(diǎn),并計(jì)數(shù)。由此,需在遍歷算法中增添一個(gè)“計(jì)數(shù)”的參數(shù),并將算法中“訪問(wèn)結(jié)點(diǎn)” 的操作改為:若是葉子,則計(jì)數(shù)器增1。void CountLeaf (BiTree T, int& count) if (

24、 T ) if (!T-lchild)& (!T-rchild) count+; / 對(duì)葉子結(jié)點(diǎn)計(jì)數(shù) CountLeaf( T-lchild, count); CountLeaf( T-rchild, count); / if / CountLeafint CountLeaf (BiTree T)/返回指針T所指二叉樹(shù)中所有葉子結(jié)點(diǎn)個(gè)數(shù) if (!T ) return 0; if (!T-lchild & !T-rchild) return 1; else m = CountLeaf( T-lchild); n = CountLeaf( T-rchild); return (m+n); /el

25、se / CountLeafint Count (BiTree T)/返回指針T所指二叉樹(shù)中所有結(jié)點(diǎn)個(gè)數(shù) if (!T ) return 0; if (!T-lchild & !T-rchild) return 1; else m = Count ( T-lchild); n = Count ( T-rchild); return (m+n+1); /else / CountLeaf3、求二叉樹(shù)的深度(后序遍歷)算法基本思想: 從二叉樹(shù)深度的定義可知,二叉樹(shù)的深度應(yīng)為其左、右子樹(shù)深度的最大值加1。由此,需先分別求得左、右子樹(shù)的深度,算法中“訪問(wèn)結(jié)點(diǎn)”的操作為:求得左、右子樹(shù)深度的最大值,然后加

26、 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 depthRight ? depthLeft : depthRight); return depthval;void Depth(BiTree T , int level, int &dval) if ( T ) if (leveldva

27、l) dval = level; Depth( T-lchild, level+1, dval ); Depth( T-rchild, level+1, dval ); / 調(diào)用之前 level 的初值為 1。 / dval 的初值為 0.4、復(fù)制二叉樹(shù)其基本操作為:生成一個(gè)結(jié)點(diǎn)。根元素T左子樹(shù)右子樹(shù)根元素NEWT左子樹(shù)右子樹(shù)左子樹(shù)右子樹(shù)(后序遍歷)BiTNode *GetTreeNode(TElemType item, BiTNode *lptr , BiTNode *rptr ) if (!(T = new BiTNode) exit(1); T- data = item; T- lchi

28、ld = lptr; T- rchild = rptr; return T; 生成一個(gè)二叉樹(shù)的結(jié)點(diǎn)(其數(shù)據(jù)域?yàn)閕tem,左指針域?yàn)閘ptr,右指針域?yàn)閞ptr)BiTNode *CopyTree(BiTNode *T) if (!T ) return NULL; if (T-lchild ) newlptr = CopyTree(T-lchild); /復(fù)制左子樹(shù) else newlptr = NULL; if (T-rchild ) newrptr = CopyTree(T-rchild); /復(fù)制右子樹(shù) else newrptr = NULL; newT = GetTreeNode(T-d

29、ata, newlptr, newrptr); return newT; / CopyTreeABCDEFGHK D C H K G A例如:下列二叉樹(shù)的復(fù)制過(guò)程如下:newT F B E 5、建立二叉樹(shù)的存儲(chǔ)結(jié)構(gòu)不同的定義方法相應(yīng)有不同的存儲(chǔ)結(jié)構(gòu)的建立算法 以字符串的形式 “根 左子樹(shù) 右子樹(shù)”定義一棵二叉樹(shù)例如:以空白字符“ ”表示ABCDA(B( ,C( , ),D( , )空樹(shù)只含一個(gè)根結(jié)點(diǎn)的二叉樹(shù)A以字符串“A ”表示以下列字符串表示Status CreateBiTree(BiTree &T) scanf(&ch); if (ch= ) T = NULL; else if (!(T

30、= new BiTNode) exit(OVERFLOW); T-data = ch; / 生成根結(jié)點(diǎn) CreateBiTree(T-lchild); / 構(gòu)造左子樹(shù) CreateBiTree(T-rchild); / 構(gòu)造右子樹(shù) return OK; / CreateBiTreeA B C D ABCD上頁(yè)算法執(zhí)行過(guò)程舉例如下:ATBCDscanf(&ch);if (ch= ) T = NULL;else if (!(T = new BiTNode) exit(OVERFLOW); T-data = ch;CreateBiTree(T-lchild); CreateBiTree(T-rchi

31、ld); 按給定的表達(dá)式建相應(yīng)二叉樹(shù) 由先綴表示式建樹(shù)例如:已知表達(dá)式的先綴表示式 -+ a b c / d e 由原表達(dá)式建樹(shù)例如:已知表達(dá)式 (a+b)c d/e對(duì)應(yīng)先綴表達(dá)式 -+ a b c / d e的二叉樹(shù)abcde-+/特點(diǎn): 操作數(shù)為葉子結(jié)點(diǎn), 運(yùn)算符為分支結(jié)點(diǎn)scanf(&ch);if ( In(ch, 字母集 ) 建葉子結(jié)點(diǎn);else 建根結(jié)點(diǎn); 遞歸建左子樹(shù); 遞歸建右子樹(shù);由先綴表示式建樹(shù)的算法的基本操作:a+b(a+b)c d/ea+bc 分析表達(dá)式和二叉樹(shù)的關(guān)系:abbac+abc(a+b)c/deabc+-基本操作:scanf(&ch);if (In(ch, 字母

32、集 ) 建葉子結(jié)點(diǎn); 暫存; else if (In(ch, 運(yùn)算符集) 和前一個(gè)運(yùn)算符比較優(yōu)先數(shù); 若當(dāng)前的優(yōu)先數(shù)“高”,則暫存; 否則建子樹(shù);void CrtExptree(BiTree &T, char exp ) InitStack(S); Push(S, #); InitStack(PTR); p = exp; ch = *p; while (!(GetTop(S)=# & ch=#) if (!IN(ch, OP) CrtNode( t, ch ); / 建葉子結(jié)點(diǎn)并入棧 else if ( ch!= # ) p+; ch = *p; / while Pop(PTR, T); /

33、CrtExptree switch (ch) case ( : Push(S, ch); break; case ) : Pop(S, c); while (c!= ( ) CrtSubtree( t, c); / 建二叉樹(shù)并入棧 Pop(S, c) break; defult : / switch while(!Gettop(S, c) & ( precede(c,ch) CrtSubtree( t, c); Pop(S, c);if ( ch!= # ) Push( S, ch); break;建葉子結(jié)點(diǎn)的算法為:void CrtNode(BiTree& T,char ch) if (!(

34、T= new BiTNode) exit(OVERFLOW); T-data = char; T-lchild = T-rchild = NULL; Push( PTR, T );建子樹(shù)的算法為:void CrtSubtree (Bitree& T, char c) if (!(T= new BiTNode) exit(OVERFLOW); T-data = c; Pop(PTR, rc); T-rchild = rc; Pop(PTR, lc); T-lchild = lc; Push(PTR, T); 僅知二叉樹(shù)的先序序列“abcdefg” 不能唯一確定一棵二叉樹(shù),由二叉樹(shù)的先序和中序序列

35、建樹(shù) 如果同時(shí)已知二叉樹(shù)的中序序列“cbdaegf”,則會(huì)如何? 二叉樹(shù)的先序序列二叉樹(shù)的中序序列左子樹(shù)左子樹(shù)右子樹(shù)右子樹(shù)根根a b c d e f gc b d a e g f例如:aab bccddeeffggabcdefg先序序列中序序列void CrtBT(BiTree& T, char pre, char ino, int ps, int is, int n ) / 已知preps.ps+n-1為二叉樹(shù)的先序序列, / inois.is+n-1為二叉樹(shù)的中序序列,本算 / 法由此兩個(gè)序列構(gòu)造二叉鏈表 if (n=0) T=NULL; else k=Search(ino, preps)

36、; / 在中序序列中查詢(xún) if (k= -1) T=NULL; else / / CrtBT if (!(T= new BiTNode) exit(OVERFLOW);T-data = preps;if (k=is) T-Lchild = NULL;else CrtBT(T-Lchild, pre, ino, ps+1, is, k-is );if (k=is+n-1) T-Rchild = NULL;else CrtBT(T-Rchild, pre, ino, ps+1+(k-is), k+1, n-(k-is)-1 ); 6.4 樹(shù)和森林 的表示方法樹(shù)的三種存儲(chǔ)結(jié)構(gòu)一、雙親表示法二、孩子鏈

37、表表示法三、樹(shù)的二叉鏈表(孩子-兄弟) 存儲(chǔ)表示法ABCDEFGr=0n=60 A -11 B 02 C 03 D 04 E 2 5 F 26 G 5data parent一、雙親表示法: typedef struct PTNode Elem data; int parent; / 雙親位置域 PTNode; data parent#define MAX_TREE_SIZE 100結(jié)點(diǎn)結(jié)構(gòu):C語(yǔ)言的類(lèi)型描述:typedef struct PTNode nodesMAX_TREE_SIZE; int r, n; / 根結(jié)點(diǎn)的位置和結(jié)點(diǎn)個(gè)數(shù) PTree;樹(shù)結(jié)構(gòu):二、孩子鏈表表示法:多重鏈表:每個(gè)結(jié)

38、點(diǎn)有多個(gè)指針域,分別指向其子樹(shù)的根結(jié)點(diǎn)同構(gòu):結(jié)點(diǎn)的指針個(gè)數(shù)相等,為樹(shù)的度D結(jié)點(diǎn)不同構(gòu):結(jié)點(diǎn)指針個(gè)數(shù)不等,為該結(jié)點(diǎn)的度ddata child1 child2 . childDdata degree child1 child2 . childdr=0n=6 dataABCDEFG0 A -11 B 02 C 03 D 04 E 25 F 26 G 464 5 1 2 3二、孩子鏈表表示法:-1 0 0 0 2 2 4firstchildparenttypedef struct CTNode int child; struct CTNode *nextchild; *ChildPtr;孩子結(jié)點(diǎn)結(jié)構(gòu):

39、 child nextchildC語(yǔ)言的類(lèi)型描述: 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):ABCDEFGroot AB C E D F G AB C E D F G 三、樹(shù)的二叉鏈表 (孩子-兄弟)存儲(chǔ)表示法roottypedef struct CSNode Elem data; struct CSNode *firs

40、tchild, *nextsibling; CSNode, *CSTree;C語(yǔ)言的類(lèi)型描述:結(jié)點(diǎn)結(jié)構(gòu): firstchild data nextsibling將一棵樹(shù)轉(zhuǎn)換為二叉樹(shù)的方法是:(1)樹(shù)中所有相鄰兄弟之間加一條連線。(2)對(duì)樹(shù)中的每個(gè)結(jié)點(diǎn),只保留它與第一個(gè)孩子結(jié)點(diǎn)之間的連線,刪去它與其它孩子結(jié)點(diǎn)之間的連線。(3)以樹(shù)的根結(jié)點(diǎn)為軸心,將整棵樹(shù)順時(shí)針轉(zhuǎn)動(dòng)一定的角度,使之結(jié)構(gòu)層次分明。63 二叉樹(shù)與樹(shù)、森林之間的轉(zhuǎn)換631 樹(shù)轉(zhuǎn)換為二叉樹(shù)632 森林轉(zhuǎn)換為二叉樹(shù) 森林轉(zhuǎn)換為二叉樹(shù)的方法如下:(1)將森林中的每棵樹(shù)轉(zhuǎn)換成相應(yīng)的二叉樹(shù)(2)第一棵二叉樹(shù)不動(dòng),從第二棵二叉樹(shù)開(kāi)始,依次把后一棵二

41、叉樹(shù)的根結(jié)點(diǎn)作為前一棵二叉樹(shù)根結(jié)點(diǎn)的右孩子,當(dāng)所有二叉樹(shù)連起來(lái)后,此時(shí)所得到的二叉樹(shù)就是由森林轉(zhuǎn)換得到的二叉樹(shù)。633 二叉樹(shù)轉(zhuǎn)換為樹(shù)和森林(1)若某結(jié)點(diǎn)是其雙親的左孩子,則把該結(jié)點(diǎn)的右孩子、右孩子的右孩子,都與該結(jié)點(diǎn)的雙親結(jié)點(diǎn)用線連起來(lái);(2)刪去原二叉樹(shù)中所有的雙親結(jié)點(diǎn)與右孩子結(jié)點(diǎn)的連線; 由此,樹(shù)和森林的各種操作均可與二叉樹(shù)的各種操作相對(duì)應(yīng)。 應(yīng)當(dāng)注意的是,和樹(shù)對(duì)應(yīng)的二叉樹(shù),其左、右子樹(shù)的概念已改變?yōu)椋?左是孩子,右是兄弟6.4 哈 夫 曼 樹(shù) 與 哈 夫 曼 編 碼 最優(yōu)樹(shù)的定義 如何構(gòu)造最優(yōu)樹(shù) 前綴編碼 一、最優(yōu)樹(shù)的定義樹(shù)的路徑長(zhǎng)度定義為: 樹(shù)中每個(gè)結(jié)點(diǎn)的路徑長(zhǎng)度之和。 結(jié)點(diǎn)的路徑長(zhǎng)

42、度定義為: 從根結(jié)點(diǎn)到該結(jié)點(diǎn)的路徑上 分支的數(shù)目。 樹(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ù)”。例如:27 9 75492WPL(T)= 72+52+23+43+92 =60WPL(T)= 74+94+53+42+21 =89 54根據(jù)給定的 n 個(gè)權(quán)值 w1, w2, , wn構(gòu)造 n 棵二叉樹(shù)的集合 F = T1, T2, , Tn,其中每棵二叉樹(shù)中均只含一個(gè)帶權(quán)值 為 wi 的根結(jié)點(diǎn),其左、右子樹(shù)為空樹(shù);二、如何構(gòu)造

43、最優(yōu)樹(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ù) (2) 和 (3) 兩步,直至 F 中只 含一棵樹(shù)為止。(3)(4)9例如: 已知權(quán)值 W= 5, 6, 2, 9, 7 562752769767139527671395279527166713292.哈夫曼樹(shù)的造構(gòu)造算法根據(jù)二叉樹(shù)的性質(zhì)可知,具有n個(gè)葉子結(jié)點(diǎn)的哈夫曼樹(shù)共有2n1個(gè)結(jié)點(diǎn),所以數(shù)組HuffNode的大小設(shè)置為2n1weig

44、htlchildrchildparent下面給出哈夫曼樹(shù)的構(gòu)造算法。#define MAXVALUE 10000 /* 定義最大權(quán)值 */#define MAXLEAF 30 /*定義哈夫曼樹(shù)中葉子結(jié)點(diǎn)個(gè)數(shù)*/#define MAXNODE MAXLEAF*2-1typedef structint weight; int parent; int lchild,rchild;HNodeType;for (i=0;i2*n-1;i+) /* 數(shù)組HuffNode 初始化 */ HuffNodei.weight=0; HuffNodei.parent=-1; HuffNodei.lchild=-1;

45、 HuffNodei.rchild=-1; for (i=0;in;i+) scanf(“%d”,&HuffNodei.weight);/* 將找出的兩棵子樹(shù)合并為一棵子樹(shù) */ HuffNodex1.parent=n+i; HuffNodex2.parent=n+i; HuffNoden+i.weight= HuffNodex1.weight+HuffNodex2.weight; HuffNoden+i.lchild=x1; HuffNoden+i.rchild=x2; for (i=0;in-1;i+) m1=m2=MAXVALUE; x1=x2=0; for (j=0;jn+i;j+)

46、if (HuffNodej.weightm1 & HuffNodej.parent=-1) m2=m1; x2=x1; m1=HuffNodej.weight; x1=j; else if (HuffNodej.weightfirstchild);D2 = Depth(T-nextsibling);Return Maxd1+1,d2int TreeDepth( CTree T ) / T 是樹(shù)的孩子鏈表存儲(chǔ)結(jié)構(gòu), / 返回該樹(shù)的深度 if ( T.n = 0) return 0; else return Depth( T, T.r ); / TreeDepth一、求樹(shù)的深度的算法:int De

47、pth( CTree T, int root ) max = 0; p = T.nodesroot.firstchild; while ( p ) h = Depth( T, p-child ); if ( h max ) max = h; p = p-nextchild; /while return max+1;二、輸出樹(shù)中所有從根到葉子的路徑的算法: A B C DE F G H I J K例如:對(duì)左圖所示的樹(shù),其輸出結(jié)果應(yīng)為:A B EA B FA CA D G H IA D G H JA D G H Kvoid AllPath( BiTree T, Stack& S ) if (T)

48、Push( S, T-data ); if (!T-Lchild & !T-Rchild ) PrintStack(S); else AllPath( T-Lchild, S ); AllPath( T-Rchild, S ); Pop(S); / if(T) / AllPath/ 輸出二叉樹(shù)上從根到所有葉子結(jié)點(diǎn)的路徑void OutPath( Bitree T, Stack& S ) while ( !T ) Push(S, T-data ); if ( !T-firstchild ) Printstack(S); else OutPath( T-firstchild, S ); Pop(S

49、); T = T-nextsibling; / while / OutPath/ 輸出森林中所有從根到葉的路徑三、建樹(shù)的存儲(chǔ)結(jié)構(gòu)的算法: 和二叉樹(shù)類(lèi)似,不同的定義相應(yīng)有不同的算法。 假設(shè)以二元組(F,C)的形式自上而下、自左而右依次輸入樹(shù)的各邊,建立樹(shù)的孩子-兄弟鏈表。ABCDEFG例如:對(duì)下列所示樹(shù)的輸入序列應(yīng)為:(#, A)(A, B)(A, C)(A, D)(C, E)(C, F)(E, G)ABCD(#, A)(A, B)(A, C)(A, D)(C, E)可見(jiàn),算法中需要一個(gè)隊(duì)列保存已建好的結(jié)點(diǎn)的指針void CreatTree( CSTree &T ) T = NULL; for(

50、 scanf(&fa, &ch); ch!= ; scanf(&fa, &ch);) p = GetTreeNode(ch); / 創(chuàng)建結(jié)點(diǎn)EnQueue(Q, p); / 指針入隊(duì)列if (fa = ) T = p; / 所建為根結(jié)點(diǎn) else / 非根結(jié)點(diǎn)的情況 / for / CreateTree GetHead(Q,s); / 取隊(duì)列頭元素(指針值)while (s-data != fa ) / 查詢(xún)雙親結(jié)點(diǎn) DeQueue(Q,s); GetHead(Q,s); if (!(s-firstchild) s-firstchild = p; r = p; / 鏈接第一個(gè)孩子結(jié)點(diǎn)else

51、r-nextsibling = p; r = p; / 鏈接其它孩子結(jié)點(diǎn) 本章作業(yè) 6.33, 6.34, 6.43, 6.45 6.47, 6.51, 6.56 6.59, 6.61, 6.63, 6.686.5線索二叉樹(shù) 何謂線索二叉樹(shù)? 線索鏈表的遍歷算法 如何建立線索鏈表?一、何謂線索二叉樹(shù)?遍歷二叉樹(shù)的結(jié)果是, 求得結(jié)點(diǎn)的一個(gè)線性序列。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指向該線性序列中的“前驅(qū)”和 “后繼” 的指針,稱(chēng)作“線索”與其相應(yīng)的二叉樹(shù),稱(chēng)作 “線索二叉樹(shù)”包含 “線索” 的存儲(chǔ)結(jié)構(gòu),稱(chēng)作 “線索鏈表”A B C D E F G H K D C B E 對(duì)線索鏈表中結(jié)點(diǎn)的約定: 在二叉鏈表的結(jié)點(diǎn)中增加兩個(gè)標(biāo)志域,并作如下規(guī)定:若該結(jié)點(diǎn)的左子樹(shù)不空,則Lchild域的指針指向其左子樹(shù), 且左標(biāo)志域的值為“指針 Link”; 否則,Lchild域的指針指向其“前驅(qū)”, 且左標(biāo)志的值為“線索 Thread” 。若該結(jié)點(diǎn)的右子樹(shù)不空,則rchild域的指針指向其右子樹(shù), 且右標(biāo)志域的值為 “指針 Link”;否則,rchild域的指針指向其“后繼”, 且右標(biāo)志的

溫馨提示

  • 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ì)自己和他人造成任何形式的傷害或損失。

最新文檔

評(píng)論

0/150

提交評(píng)論