




版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡介
樹結(jié)構(gòu)是一種比線性結(jié)構(gòu)更復(fù)雜的數(shù)據(jù)結(jié)構(gòu),比較適合描述具有層次關(guān)系的數(shù)據(jù)結(jié)構(gòu)。樹結(jié)構(gòu)在計(jì)算機(jī)領(lǐng)域中有著廣泛的應(yīng)用編譯程序中的語法樹;數(shù)據(jù)挖掘中用決策樹來進(jìn)行數(shù)據(jù)分類。第5
章樹和二叉樹樹的邏輯結(jié)構(gòu)樹的存儲(chǔ)結(jié)構(gòu)二叉樹的邏輯結(jié)構(gòu)二叉樹的存儲(chǔ)結(jié)構(gòu)及實(shí)現(xiàn)二叉樹遍歷的非遞歸算法樹、森林與二叉樹的轉(zhuǎn)換哈夫曼樹和哈夫曼編碼第5
章樹和二叉樹本章的主要內(nèi)容是:本章學(xué)習(xí)重點(diǎn)樹的遍歷二叉樹的性質(zhì)二叉樹和樹的存儲(chǔ)表示二叉樹的遍歷樹與二叉樹之間的轉(zhuǎn)換哈夫曼樹第5
章樹和二叉樹樹的定義樹:n(n≥0)個(gè)結(jié)點(diǎn)的有限集合。當(dāng)n=0時(shí),稱為空樹;任意一棵非空樹滿足以下條件:⑴
有且僅有一個(gè)特定的稱為根的結(jié)點(diǎn);⑵
當(dāng)n>1時(shí),除根結(jié)點(diǎn)之外的其余結(jié)點(diǎn)被分成m(m>0)個(gè)互不相交的有限集合T1,T2,…,Tm,其中每個(gè)集合又是一棵樹,并稱為這個(gè)根結(jié)點(diǎn)的子樹。5.1樹的邏輯結(jié)構(gòu)樹的定義是采用遞歸方法(a)一棵樹結(jié)構(gòu)(b)一個(gè)非樹結(jié)構(gòu)(c)一個(gè)非樹結(jié)構(gòu)5.1樹的邏輯結(jié)構(gòu)樹的定義ACBGFEDHIACBGFDACBGFDE樹的應(yīng)用舉例——文件結(jié)構(gòu)5.1樹的邏輯結(jié)構(gòu)MyComputerC:D:E:etcWINDOWSProgramFilesPictureMusic…………………………………………樹的基本術(shù)語結(jié)點(diǎn)的度:結(jié)點(diǎn)所擁有的子樹的個(gè)數(shù)。樹的度:樹中各結(jié)點(diǎn)度的最大值。5.1樹的邏輯結(jié)構(gòu)CGBDEFKLHMIJA5.1樹的邏輯結(jié)構(gòu)葉子結(jié)點(diǎn):度為0的結(jié)點(diǎn),也稱為終端結(jié)點(diǎn)。分支結(jié)點(diǎn):度不為0的結(jié)點(diǎn),也稱為非終端結(jié)點(diǎn)。CGBDEFKLHMIJA樹的基本術(shù)語孩子、雙親:樹中某結(jié)點(diǎn)子樹的根結(jié)點(diǎn)稱為這個(gè)結(jié)點(diǎn)的孩子結(jié)點(diǎn),這個(gè)結(jié)點(diǎn)稱為它孩子結(jié)點(diǎn)的雙親結(jié)點(diǎn);兄弟:具有同一個(gè)雙親的孩子結(jié)點(diǎn)互稱為兄弟。
5.1樹的邏輯結(jié)構(gòu)CGBDEFKLHMIJA樹的基本術(shù)語路徑:如果樹的結(jié)點(diǎn)序列n1,n2,…,nk有如下關(guān)系:結(jié)點(diǎn)ni是ni+1的雙親(1<=i<k),則把n1,n2,…,nk稱為一條由n1至nk的路徑;路徑上經(jīng)過的邊的個(gè)數(shù)稱為路徑長度。CGBDEFKLHMIJA5.1樹的邏輯結(jié)構(gòu)樹的基本術(shù)語祖先、子孫:在樹中,如果有一條路徑從結(jié)點(diǎn)x到結(jié)點(diǎn)y,則x稱為y的祖先,而y稱為x的子孫。5.1樹的邏輯結(jié)構(gòu)CGBDEFKLHMIJA樹的基本術(shù)語結(jié)點(diǎn)所在層數(shù):根結(jié)點(diǎn)的層數(shù)為1;對(duì)其余任何結(jié)點(diǎn),若某結(jié)點(diǎn)在第k層,則其孩子結(jié)點(diǎn)在第k+1層。樹的深度:樹中所有結(jié)點(diǎn)的最大層數(shù),也稱高度。1層2層4層3層高度=4CGBDEFKLHMIJA5.1樹的邏輯結(jié)構(gòu)樹的基本術(shù)語CBDEFKLHJA71234568910層序編號(hào):將樹中結(jié)點(diǎn)按照從上層到下層、同層從左到右的次序依次給他們編以從1開始的連續(xù)自然數(shù)。5.1樹的邏輯結(jié)構(gòu)樹的基本術(shù)語有序樹、無序樹:如果一棵樹中結(jié)點(diǎn)的各子樹從左到右是有次序的,稱這棵樹為有序樹;反之,稱為無序樹。數(shù)據(jù)結(jié)構(gòu)中討論的一般都是有序樹
5.1樹的邏輯結(jié)構(gòu)樹的基本術(shù)語ACBGFEDACBGFEDCBDEFKLHJ森林:m(m≥0)棵互不相交的樹的集合。
5.1樹的邏輯結(jié)構(gòu)樹的基本術(shù)語A樹結(jié)構(gòu)和線性結(jié)構(gòu)的比較線性結(jié)構(gòu)樹結(jié)構(gòu)第一個(gè)數(shù)據(jù)元素根結(jié)點(diǎn)(只有一個(gè))無前驅(qū)無雙親最后一個(gè)數(shù)據(jù)元素葉子結(jié)點(diǎn)(可以有多個(gè))無后繼無孩子其它數(shù)據(jù)元素其它結(jié)點(diǎn)一個(gè)前驅(qū),一個(gè)后繼一個(gè)雙親,多個(gè)孩子一對(duì)一一對(duì)多5.1樹的邏輯結(jié)構(gòu)樹的抽象數(shù)據(jù)類型定義ADTTreeData
樹是由一個(gè)根結(jié)點(diǎn)和若干棵子樹構(gòu)成,樹中結(jié)點(diǎn)具有相同數(shù)據(jù)類型及層次關(guān)系Operation5.1樹的邏輯結(jié)構(gòu)樹的應(yīng)用很廣泛,在不同的實(shí)際應(yīng)用中,樹的基本操作不盡相同。下面給出一個(gè)樹的抽象數(shù)據(jù)類型定義的例子,簡單起見,基本操作只包含樹的遍歷,針對(duì)具體應(yīng)用,需要重新定義其基本操作。InitTree
前置條件:樹不存在輸入:無功能:初始化一棵樹輸出:無后置條件:構(gòu)造一個(gè)空樹DestroyTree
前置條件:樹已存在輸入:無功能:銷毀一棵樹輸出:無后置條件:釋放該樹占用的存儲(chǔ)空間
樹的抽象數(shù)據(jù)類型定義5.1樹的邏輯結(jié)構(gòu)
PreOrder
前置條件:樹已存在輸入:無功能:前序遍歷樹輸出:樹的前序遍歷序列后置條件:樹保持不變
PostOrder
前置條件:樹已存在輸入:無功能:后序遍歷樹輸出:樹的后序遍歷序列后置條件:樹保持不變endADT樹的抽象數(shù)據(jù)類型定義5.1樹的邏輯結(jié)構(gòu)樹的遍歷操作
樹的遍歷:從根結(jié)點(diǎn)出發(fā),按照某種次序訪問樹中所有結(jié)點(diǎn),使得每個(gè)結(jié)點(diǎn)被訪問一次且僅被訪問一次。
如何理解訪問?抽象操作,可以是對(duì)結(jié)點(diǎn)進(jìn)行的各種處理,這里簡化為輸出結(jié)點(diǎn)的數(shù)據(jù)。如何理解次序?樹通常有前序(根)遍歷、后序(根)遍歷和層序(次)遍歷三種方式。5.1樹的邏輯結(jié)構(gòu)樹結(jié)構(gòu)(非線性結(jié)構(gòu))→線性結(jié)構(gòu)。遍歷的實(shí)質(zhì)?前序遍歷
樹的前序遍歷操作定義為:若樹為空,則空操作返回;否則⑴訪問根結(jié)點(diǎn);⑵
按照從左到右的順序前序遍歷根結(jié)點(diǎn)的每一棵子樹。
5.1樹的邏輯結(jié)構(gòu)前序遍歷序列:ABDEHIFCGACBGFEDHI后序遍歷
樹的后序遍歷操作定義為:若樹為空,則空操作返回;否則⑴按照從左到右的順序后序遍歷根結(jié)點(diǎn)的每一棵子樹;⑵
訪問根結(jié)點(diǎn)。
5.1樹的邏輯結(jié)構(gòu)后序遍歷序列:DHIEFBGCAACBGFEDHI層序遍歷
樹的層序遍歷操作定義為:從樹的第一層(即根結(jié)點(diǎn))開始,自上而下逐層遍歷,在同一層中,按從左到右的順序?qū)Y(jié)點(diǎn)逐個(gè)訪問。
5.1樹的邏輯結(jié)構(gòu)層序遍歷序列:ABCDEFGHIACBGFEDHI5.2樹的存儲(chǔ)結(jié)構(gòu)實(shí)現(xiàn)樹的存儲(chǔ)結(jié)構(gòu),關(guān)鍵是什么?什么是存儲(chǔ)結(jié)構(gòu)?樹中結(jié)點(diǎn)之間的邏輯關(guān)系是什么?思考問題的出發(fā)點(diǎn):如何表示結(jié)點(diǎn)的雙親和孩子。
如何表示樹中結(jié)點(diǎn)之間的邏輯關(guān)系。數(shù)據(jù)元素以及數(shù)據(jù)元素之間的邏輯關(guān)系在存儲(chǔ)器中的表示。雙親表示法基本思想:用一維數(shù)組來存儲(chǔ)樹的各個(gè)結(jié)點(diǎn)(一般按層序存儲(chǔ)),數(shù)組中的一個(gè)元素對(duì)應(yīng)樹中的一個(gè)結(jié)點(diǎn),包括結(jié)點(diǎn)的數(shù)據(jù)信息以及該結(jié)點(diǎn)的雙親在數(shù)組中的下標(biāo)。
5.2樹的存儲(chǔ)結(jié)構(gòu)
data
parentdata:存儲(chǔ)樹中結(jié)點(diǎn)的數(shù)據(jù)信息parent:存儲(chǔ)該結(jié)點(diǎn)的雙親在數(shù)組中的下標(biāo)template<classDataType>structPNode{
DataTypedata;//數(shù)據(jù)域intparent;//指針域,雙親在數(shù)組中的下標(biāo)};
data
parent5.2樹的存儲(chǔ)結(jié)構(gòu)樹的雙親表示法實(shí)質(zhì)上是一個(gè)靜態(tài)鏈表。雙親表示法下標(biāo)
dataparent012345678
A-1B0C0D1E1F1G2H2I
45.2樹的存儲(chǔ)結(jié)構(gòu)如何查找雙親結(jié)點(diǎn)?時(shí)間性能?雙親表示法ACBHFEDGI5.2樹的存儲(chǔ)結(jié)構(gòu)雙親表示法ACBHFEDGI如何查找孩子結(jié)點(diǎn)?時(shí)間性能?下標(biāo)
dataparentfirstchild136-18-1-1-1-1012345678
A-1B0C0D1E1F1G2H2I
4下標(biāo)
dataparentrightsib-12-145-17-1-15.2樹的存儲(chǔ)結(jié)構(gòu)雙親表示法012345678
A-1B0C0D1E1F1G2H2I
4ACBHFEDGI如何查找兄弟結(jié)點(diǎn)?時(shí)間性能?鏈表中的每個(gè)結(jié)點(diǎn)包括一個(gè)數(shù)據(jù)域和多個(gè)指針域,每個(gè)指針域指向該結(jié)點(diǎn)的一個(gè)孩子結(jié)點(diǎn)。如何表示孩子?5.2樹的存儲(chǔ)結(jié)構(gòu)孩子鏈表表示法方案一:指針域的個(gè)數(shù)等于樹的度datachild1child2……childd其中:data:數(shù)據(jù)域,存放該結(jié)點(diǎn)的數(shù)據(jù)信息;
child1~childd:指針域,指向該結(jié)點(diǎn)的孩子。
5.2樹的存儲(chǔ)結(jié)構(gòu)∧缺點(diǎn):浪費(fèi)空間!ACBHFEDGIA∧B∧C∧D∧E∧F∧G∧H∧I∧∧∧∧∧∧∧∧∧∧∧鏈表中的每個(gè)結(jié)點(diǎn)包括一個(gè)數(shù)據(jù)域和多個(gè)指針域,每個(gè)指針域指向該結(jié)點(diǎn)的一個(gè)孩子結(jié)點(diǎn)。如何表示孩子?5.2樹的存儲(chǔ)結(jié)構(gòu)孩子鏈表表示法方案二:
指針域的個(gè)數(shù)等于該結(jié)點(diǎn)的度data
degree
child1
child2
……
childd其中:data:數(shù)據(jù)域,存放該結(jié)點(diǎn)的數(shù)據(jù)信息;
degree:度域,存放該結(jié)點(diǎn)的度;
child1~childd:指針域,指向該結(jié)點(diǎn)的孩子。
5.2樹的存儲(chǔ)結(jié)構(gòu)缺點(diǎn):結(jié)點(diǎn)結(jié)構(gòu)不一致!ACBHFEDGIA2B3C2E1I0G0H0F0D0孩子鏈表表示法孩子鏈表的基本思想:
把每個(gè)結(jié)點(diǎn)的孩子排列起來,看成是一個(gè)線性表,且以單鏈表存儲(chǔ),則n個(gè)結(jié)點(diǎn)共有n個(gè)孩子鏈表。這n個(gè)單鏈表共有n個(gè)頭指針,這n個(gè)頭指針又組成了一個(gè)線性表,為了便于進(jìn)行查找采用順序存儲(chǔ)。最后,將存放n個(gè)頭指針的數(shù)組和存放n個(gè)結(jié)點(diǎn)的數(shù)組結(jié)合起來,構(gòu)成孩子鏈表的表頭數(shù)組。
5.2樹的存儲(chǔ)結(jié)構(gòu)如何表示孩子?將結(jié)點(diǎn)的所有孩子放在一起,構(gòu)成線性表。childnext孩子結(jié)點(diǎn)structCTNode{
intchild;CTNode*next;};5.2樹的存儲(chǔ)結(jié)構(gòu)template<classDataType>structCBNode{DataTypedata;CTNode*firstchild;};孩子鏈表表示法datafirstchild表頭結(jié)點(diǎn)ACBHFEDGI012345678下標(biāo)
datafirstchild
ABCDEFG
H
I
∧∧∧∧5.2樹的存儲(chǔ)結(jié)構(gòu)如何查找孩子結(jié)點(diǎn)?時(shí)間性能?∧12∧345∧7∧68∧ACBHFEDGI012345678下標(biāo)
datafirstchild
ABCDEFG
H
I
∧∧∧∧∧5.2樹的存儲(chǔ)結(jié)構(gòu)12∧345∧7∧68∧如何查找雙親結(jié)點(diǎn)?時(shí)間性能?雙親孩子表示法5.2樹的存儲(chǔ)結(jié)構(gòu)012345678
A-1B0C0D1
∧
E1F1
∧
G
2
∧H
2
∧I
4
∧dataparentfirstchild12∧345∧7∧68∧ACBHFEDGI孩子兄弟表示法5.2樹的存儲(chǔ)結(jié)構(gòu)ACBHFEDGI某結(jié)點(diǎn)的第一個(gè)孩子是惟一的某結(jié)點(diǎn)的右兄弟是惟一的設(shè)置兩個(gè)分別指向該結(jié)點(diǎn)的第一個(gè)孩子和右兄弟的指針
template<classDataType>structTNode{DataTypedata;TNode<DataType>*firstchild,*rightsib;};5.2樹的存儲(chǔ)結(jié)構(gòu)結(jié)點(diǎn)結(jié)構(gòu)firstchild
data
rightsibdata:數(shù)據(jù)域,存儲(chǔ)該結(jié)點(diǎn)的數(shù)據(jù)信息;firstchild:指針域,指向該結(jié)點(diǎn)第一個(gè)孩子;rightsib:指針域,指向該結(jié)點(diǎn)的右兄弟結(jié)點(diǎn)。
孩子兄弟表示法5.2樹的存儲(chǔ)結(jié)構(gòu)孩子兄弟表示法ACBHFEDGI
A
B
C
D
E
F
G
H
I∧∧∧∧∧∧∧∧∧∧如何查找兄弟結(jié)點(diǎn)?時(shí)間性能?5.2樹的存儲(chǔ)結(jié)構(gòu)孩子兄弟表示法ACBHFEDGI
A
B
C
D
E
F
G
H
I∧∧∧∧∧∧∧∧∧∧如何查找孩子結(jié)點(diǎn)?時(shí)間性能?二叉樹的定義
二叉樹是n(n≥0)個(gè)結(jié)點(diǎn)的有限集合,該集合或者為空集(稱為空二叉樹),或者由一個(gè)根結(jié)點(diǎn)和兩棵互不相交的、分別稱為根結(jié)點(diǎn)的左子樹和右子樹的二叉樹組成。5.3二叉樹的邏輯結(jié)構(gòu)問題轉(zhuǎn)化:將樹轉(zhuǎn)換為二叉樹,從而利用二叉樹解決樹的有關(guān)問題。研究二叉樹的意義?二叉樹的特點(diǎn)⑴每個(gè)結(jié)點(diǎn)最多有兩棵子樹;⑵二叉樹是有序的,其次序不能任意顛倒。
5.3二叉樹的邏輯結(jié)構(gòu)注意:二叉樹和樹是兩種樹結(jié)構(gòu)。ABCDEFGABAB二叉樹的基本形態(tài)Ф空二叉樹只有一個(gè)根結(jié)點(diǎn)左子樹根結(jié)點(diǎn)只有左子樹右子樹根結(jié)點(diǎn)只有右子樹左子樹右子樹根結(jié)點(diǎn)同時(shí)有左右子樹5.3二叉樹的邏輯結(jié)構(gòu)5.3二叉樹的邏輯結(jié)構(gòu)具有3個(gè)結(jié)點(diǎn)的樹和具有3個(gè)結(jié)點(diǎn)的二叉樹的形態(tài):二叉樹和樹是兩種樹結(jié)構(gòu)。特殊的二叉樹斜樹1.所有結(jié)點(diǎn)都只有左子樹的二叉樹稱為左斜樹;2.所有結(jié)點(diǎn)都只有右子樹的二叉樹稱為右斜樹;3.左斜樹和右斜樹統(tǒng)稱為斜樹。1.在斜樹中,每一層只有一個(gè)結(jié)點(diǎn);2.斜樹的結(jié)點(diǎn)個(gè)數(shù)與其深度相同。
5.3二叉樹的邏輯結(jié)構(gòu)斜樹的特點(diǎn):ABCABC滿二叉樹在一棵二叉樹中,如果所有分支結(jié)點(diǎn)都存在左子樹和右子樹,并且所有葉子都在同一層上。滿二叉樹的特點(diǎn):葉子只能出現(xiàn)在最下一層;只有度為0和度為2的結(jié)點(diǎn)。5.3二叉樹的邏輯結(jié)構(gòu)特殊的二叉樹CDEFGHIJKLMNO1112131415滿二叉樹5.3二叉樹的邏輯結(jié)構(gòu)不是滿二叉樹,雖然所有分支結(jié)點(diǎn)都有左右子樹,但葉子不在同一層上。滿二叉樹在同樣深度的二叉樹中結(jié)點(diǎn)個(gè)數(shù)最多滿二叉樹在同樣深度的二叉樹中葉子結(jié)點(diǎn)個(gè)數(shù)最多A1523467BCDEFGLM89特殊的二叉樹完全二叉樹對(duì)一棵具有n個(gè)結(jié)點(diǎn)的二叉樹按層序編號(hào),如果編號(hào)為i(1≤i≤n)的結(jié)點(diǎn)與同樣深度的滿二叉樹中編號(hào)為i的結(jié)點(diǎn)在二叉樹中的位置完全相同。5.3二叉樹的邏輯結(jié)構(gòu)特殊的二叉樹CDEFGHIJKLMNO1112131415CDEFGHIJ在滿二叉樹中,從最后一個(gè)結(jié)點(diǎn)開始,連續(xù)去掉任意個(gè)結(jié)點(diǎn),即是一棵完全二叉樹。5.3二叉樹的邏輯結(jié)構(gòu)A1523467910BCDEFGHIJK11L12M13N14O158CDEFGHIJ不是完全二叉樹,結(jié)點(diǎn)10與滿二叉樹中的結(jié)點(diǎn)10不是同一個(gè)結(jié)點(diǎn)特殊的二叉樹1.葉子結(jié)點(diǎn)只能出現(xiàn)在最下兩層且最下層的葉子結(jié)點(diǎn)都集中在二叉樹的左面;2.完全二叉樹中如果有度為1的結(jié)點(diǎn),只可能有一個(gè),且該結(jié)點(diǎn)只有左孩子。3.深度為k的完全二叉樹在k-1層上一定是滿二叉樹。4.在同樣結(jié)點(diǎn)個(gè)數(shù)的二叉樹中,完全二叉樹的深度最小。
完全二叉樹的特點(diǎn)5.3二叉樹的邏輯結(jié)構(gòu)特殊的二叉樹CDEFGHIJ二叉樹的基本性質(zhì)
性質(zhì)5-1:二叉樹的第i層上最多有2i-1個(gè)結(jié)點(diǎn)(i≥1)。
證明:當(dāng)i=1時(shí),第1層只有一個(gè)根結(jié)點(diǎn),而2i-1=20=1,結(jié)論顯然成立。假定i=k(1≤k<i)時(shí)結(jié)論成立,即第k層上至多有2k-1個(gè)結(jié)點(diǎn),則
i=k+1時(shí),因?yàn)榈趉+1層上的結(jié)點(diǎn)是第k層上結(jié)點(diǎn)的孩子,而二叉樹中每個(gè)結(jié)點(diǎn)最多有2個(gè)孩子,故在第k+1層上最大結(jié)點(diǎn)個(gè)數(shù)為第k層上的最大結(jié)點(diǎn)個(gè)數(shù)的二倍,即2×2k-1=2k。結(jié)論成立。5.3二叉樹的邏輯結(jié)構(gòu)性質(zhì)5-2:一棵深度為k的二叉樹中,最多有2k-1個(gè)結(jié)點(diǎn),最少有k個(gè)結(jié)點(diǎn)。
證明:由性質(zhì)1,深度為k的二叉樹中結(jié)點(diǎn)個(gè)數(shù)最多==2k-1;每一層至少要有一個(gè)結(jié)點(diǎn),因此深度為k的二叉樹,至少有k個(gè)結(jié)點(diǎn)。5.3二叉樹的邏輯結(jié)構(gòu)深度為k且具有2k-1個(gè)結(jié)點(diǎn)的二叉樹一定是滿二叉樹,深度為k且具有k個(gè)結(jié)點(diǎn)的二叉樹不一定是斜樹。二叉樹的基本性質(zhì)
性質(zhì)5-3:在一棵二叉樹中,如果葉子結(jié)點(diǎn)數(shù)為n0,度為2的結(jié)點(diǎn)數(shù)為n2,則有:n0=n2+1。
證明:設(shè)n為二叉樹的結(jié)點(diǎn)總數(shù),n1為二叉樹中度為1的結(jié)點(diǎn)數(shù),則有:
n=n0+n1+n2
在二叉樹中,除了根結(jié)點(diǎn)外,其余結(jié)點(diǎn)都有唯一的一個(gè)分枝進(jìn)入,一個(gè)度為1的結(jié)點(diǎn)射出一個(gè)分枝,一個(gè)度為2的結(jié)點(diǎn)射出兩個(gè)分枝,所以有:
n=n1+2n2+1因此可以得到:n0=n2+1。5.3二叉樹的邏輯結(jié)構(gòu)二叉樹的基本性質(zhì)
5.3二叉樹的邏輯結(jié)構(gòu)n個(gè)結(jié)點(diǎn)的滿二叉樹有多少個(gè)葉子結(jié)點(diǎn)?解:因?yàn)樵跐M二叉樹中沒有度為1的結(jié)點(diǎn),只有度為0的葉子結(jié)點(diǎn)和度為2的分支結(jié)點(diǎn),所以,n=n0+n2n0=n2+1
即葉子結(jié)點(diǎn)n0=(n+1)/2
二叉樹的基本性質(zhì)
性質(zhì)5-3:在一棵二叉樹中,如果葉子結(jié)點(diǎn)數(shù)為n0,度為2的結(jié)點(diǎn)數(shù)為n2,則有:n0=n2+1。
性質(zhì)5-4:具有n個(gè)結(jié)點(diǎn)的完全二叉樹的深度為log2n+1。
5.3二叉樹的邏輯結(jié)構(gòu)證明:假設(shè)具有n個(gè)結(jié)點(diǎn)的完全二叉樹的深度為k,根據(jù)完全二叉樹的定義和性質(zhì)2,有下式成立
2k-1≤n<2k
2k-1-1…2k-12k-1———第k-1層———第k層…最少結(jié)點(diǎn)數(shù)最多結(jié)點(diǎn)數(shù)完全二叉樹的基本性質(zhì)
5.3二叉樹的邏輯結(jié)構(gòu)證明:假設(shè)具有n個(gè)結(jié)點(diǎn)的完全二叉樹的深度為k,根據(jù)完全二叉樹的定義和性質(zhì)2,有下式成立
2k-1≤n<2k完全二叉樹的基本性質(zhì)
對(duì)不等式取對(duì)數(shù),有:
k-1≤log2n<k即:
log2n<k≤log2n+1由于k是整數(shù),故必有k=log2n+1。性質(zhì)5-4:具有n個(gè)結(jié)點(diǎn)的完全二叉樹的深度為log2n+1。
性質(zhì)5-5:對(duì)一棵具有n個(gè)結(jié)點(diǎn)的完全二叉樹中從1開始按層序編號(hào),則對(duì)于任意的序號(hào)為i(1≤i≤n)的結(jié)點(diǎn)(簡稱為結(jié)點(diǎn)i),有:
(1)如果i>1,則結(jié)點(diǎn)i的雙親結(jié)點(diǎn)的序號(hào)為
i/2;如果i=1,則結(jié)點(diǎn)i是根結(jié)點(diǎn),無雙親結(jié)點(diǎn)。(2)如果2i≤n,則結(jié)點(diǎn)i的左孩子的序號(hào)為2i;如果2i>n,則結(jié)點(diǎn)i無左孩子。(3)如果2i+1≤n,則結(jié)點(diǎn)i的右孩子的序號(hào)為2i+1;如果2i+1>n,則結(jié)點(diǎn)
i無右孩子。
5.3二叉樹的邏輯結(jié)構(gòu)完全二叉樹的基本性質(zhì)
i/2;結(jié)點(diǎn)i的左孩子為2i;結(jié)點(diǎn)i的右孩子為2i+1。
5.3二叉樹的邏輯結(jié)構(gòu)性質(zhì)5表明,在完全二叉樹中,結(jié)點(diǎn)的層序編號(hào)反映了結(jié)點(diǎn)之間的邏輯關(guān)系。完全二叉樹的基本性質(zhì)
二叉樹的抽象數(shù)據(jù)類型定義ADTBiTreeData
由一個(gè)根結(jié)點(diǎn)和兩棵互不相交的左右子樹構(gòu)成,結(jié)點(diǎn)具有相同數(shù)據(jù)類型及層次關(guān)系Operation
5.3二叉樹的邏輯結(jié)構(gòu)同樹類似,在不同的應(yīng)用中,二叉樹的基本操作不盡相同。下面給出一個(gè)二叉樹抽象數(shù)據(jù)類型定義的例子,簡單起見,基本操作只包含二叉樹的遍歷,在實(shí)際應(yīng)用中,應(yīng)根據(jù)具體需要重新定義其基本操作。
InitBiTree
前置條件:無輸入:無功能:初始化一棵二叉樹輸出:無后置條件:構(gòu)造一個(gè)空的二叉樹DestroyBiTree
前置條件:二叉樹已存在輸入:無功能:銷毀一棵二叉樹輸出:無后置條件:釋放二叉樹占用的存儲(chǔ)空間
二叉樹的抽象數(shù)據(jù)類型定義5.3二叉樹的邏輯結(jié)構(gòu)
PreOrder前置條件:二叉樹已存在輸入:無功能:前序遍歷二叉樹輸出:二叉樹中結(jié)點(diǎn)的一個(gè)線性排列后置條件:二叉樹不變
InOrder
前置條件:二叉樹已存在輸入:無功能:中序遍歷二叉樹輸出:二叉樹中結(jié)點(diǎn)的一個(gè)線性排列后置條件:二叉樹不變二叉樹的抽象數(shù)據(jù)類型定義5.3二叉樹的邏輯結(jié)構(gòu)
PostOrder
前置條件:二叉樹已存在輸入:無功能:后序遍歷二叉樹輸出:二叉樹中結(jié)點(diǎn)的一個(gè)線性排列后置條件:二叉樹不變
LeverOrder
前置條件:二叉樹已存在輸入:無功能:層序遍歷二叉樹輸出:二叉樹中結(jié)點(diǎn)的一個(gè)線性排列后置條件:二叉樹不變endADT二叉樹的抽象數(shù)據(jù)類型定義5.3二叉樹的邏輯結(jié)構(gòu)二叉樹的遍歷操作
二叉樹的遍歷是指從根結(jié)點(diǎn)出發(fā),按照某種次序訪問二叉樹中的所有結(jié)點(diǎn),使得每個(gè)結(jié)點(diǎn)被訪問一次且僅被訪問一次。二叉樹遍歷操作的結(jié)果?非線性結(jié)構(gòu)線性化5.3二叉樹的邏輯結(jié)構(gòu)抽象操作,可以是對(duì)結(jié)點(diǎn)進(jìn)行的各種處理,這里簡化為輸出結(jié)點(diǎn)的數(shù)據(jù)。前序遍歷中序遍歷后序遍歷層序遍歷
二叉樹的遍歷方式:DLR、LDR、LRD、DRL、RDL、RLD
如果限定先左后右,則二叉樹遍歷方式有三種:前序:DLR中序:LDR后序:LRD層序遍歷:按二叉樹的層序編號(hào)的次序訪問各結(jié)點(diǎn)。
5.3二叉樹的邏輯結(jié)構(gòu)考慮二叉樹的組成:根結(jié)點(diǎn)D左子樹L右子樹R二叉樹前序(根)遍歷若二叉樹為空,則空操作返回;否則:①訪問根結(jié)點(diǎn);②前序遍歷根結(jié)點(diǎn)的左子樹;③前序遍歷根結(jié)點(diǎn)的右子樹。5.3二叉樹的邏輯結(jié)構(gòu)前序遍歷序列:ABDGCEFABCDEFG二叉樹的遍歷操作
中序(根)遍歷若二叉樹為空,則空操作返回;否則:①中序遍歷根結(jié)點(diǎn)的左子樹;②訪問根結(jié)點(diǎn);③中序遍歷根結(jié)點(diǎn)的右子樹。
5.3二叉樹的邏輯結(jié)構(gòu)中序遍歷序列:DGBAECFABCDEFG二叉樹的遍歷操作
后序(根)遍歷若二叉樹為空,則空操作返回;否則:①后序遍歷根結(jié)點(diǎn)的左子樹;②后序遍歷根結(jié)點(diǎn)的右子樹。③訪問根結(jié)點(diǎn);5.3二叉樹的邏輯結(jié)構(gòu)后序遍歷序列:GDBEFCAABCDEFG二叉樹的遍歷操作
層序遍歷二叉樹的層次遍歷是指從二叉樹的第一層(即根結(jié)點(diǎn))開始,從上至下逐層遍歷,在同一層中,則按從左到右的順序?qū)Y(jié)點(diǎn)逐個(gè)訪問。
5.3二叉樹的邏輯結(jié)構(gòu)層序遍歷序列:ABCDEFGABCDEFG二叉樹的遍歷操作
5.3二叉樹的邏輯結(jié)構(gòu)-%/+*abcdef二叉樹遍歷操作練習(xí)前序遍歷結(jié)果:-+a*b
%cd/ef中序遍歷結(jié)果:a+b*c%
d-e/f后序遍歷結(jié)果:abcd%*+ef/-5.3二叉樹的邏輯結(jié)構(gòu)若已知一棵二叉樹的前序(或中序,或后序,或?qū)有颍┬蛄校芊裎ㄒ淮_定這棵二叉樹呢?ABC例:已知前序序列為ABC,則可能的二叉樹有5種。ABC二叉樹的遍歷操作
5.3二叉樹的邏輯結(jié)構(gòu)例:已知前序遍歷序列為ABC,后序遍歷序列為CBA,則下列二叉樹都滿足條件。ABCABC若已知一棵二叉樹的前序序列和后序序列,能否唯一確定這棵二叉樹呢?二叉樹的遍歷操作
若已知一棵二叉樹的前序序列和中序序列,能否唯一確定這棵二叉樹呢?怎樣確定?
例如:已知一棵二叉樹的前序遍歷序列和中序遍歷序列分別為ABCDEFGHI和BCAEDGHFI,如何構(gòu)造該二叉樹呢?
5.3二叉樹的邏輯結(jié)構(gòu)二叉樹的遍歷操作
前序:ABCDEFG
HI中序:BCAEDGHFI前序:BC中序:BC5.3二叉樹的邏輯結(jié)構(gòu)
BCDEFGHIA前序:DEFGHI中序:EDGHFIABCDEFGHI前序:FG
HI中序:GHFI5.3二叉樹的邏輯結(jié)構(gòu)前序:DEFGHI中序:EDGHFIABCDEFGHIABCDEFIGH1.根據(jù)前序序列的第一個(gè)元素建立根結(jié)點(diǎn);2.在中序序列中找到該元素,確定根結(jié)點(diǎn)的左右子樹的中序序列;3.在前序序列中確定左右子樹的前序序列;4.由左子樹的前序序列和中序序列建立左子樹;5.由右子樹的前序序列和中序序列建立右子樹。5.3二叉樹的邏輯結(jié)構(gòu)已知一棵二叉樹的前序序列和中序序列,構(gòu)造該二叉樹的過程如下:
二叉樹的遍歷操作
順序存儲(chǔ)結(jié)構(gòu)二叉樹的順序存儲(chǔ)結(jié)構(gòu)就是用一維數(shù)組存儲(chǔ)二叉樹中的結(jié)點(diǎn),并且結(jié)點(diǎn)的存儲(chǔ)位置(下標(biāo))應(yīng)能體現(xiàn)結(jié)點(diǎn)之間的邏輯關(guān)系——父子關(guān)系。
如何利用數(shù)組下標(biāo)來反映結(jié)點(diǎn)之間的邏輯關(guān)系?完全二叉樹和滿二叉樹中結(jié)點(diǎn)的序號(hào)可以唯一地反映出結(jié)點(diǎn)之間的邏輯關(guān)系。5.4二叉樹的存儲(chǔ)結(jié)構(gòu)及實(shí)現(xiàn)
A
B
C
D
E
F
G
H
I
J數(shù)組下標(biāo)12345678910完全二叉樹的順序存儲(chǔ)5.4二叉樹的存儲(chǔ)結(jié)構(gòu)及實(shí)現(xiàn)CDEFGHIJ以編號(hào)為下標(biāo)二叉樹的順序存儲(chǔ)ABC∧DE∧∧∧F∧∧G數(shù)組下標(biāo)123456789101112135.4二叉樹的存儲(chǔ)結(jié)構(gòu)及實(shí)現(xiàn)ABCDEGF以編號(hào)為下標(biāo)ABCDEGF123561013按照完全二叉樹編號(hào)二叉樹的順序存儲(chǔ)ABC∧DE∧∧∧F∧∧G數(shù)組下標(biāo)01234567891011125.4二叉樹的存儲(chǔ)結(jié)構(gòu)及實(shí)現(xiàn)ABCDEGFABCDEGF123561013按照完全二叉樹編號(hào)注意到C++語言的數(shù)組下標(biāo)從0開始,也可以將編號(hào)為i的結(jié)點(diǎn)存儲(chǔ)到下標(biāo)為i-1的位置。
一棵斜樹的順序存儲(chǔ)會(huì)怎樣呢?深度為k的右斜樹,k個(gè)結(jié)點(diǎn)需分配2k-1個(gè)存儲(chǔ)單元。
一棵二叉樹改造后,變成完全二叉樹形態(tài),需增加很多空結(jié)點(diǎn),造成存儲(chǔ)空間的浪費(fèi)。5.4二叉樹的存儲(chǔ)結(jié)構(gòu)及實(shí)現(xiàn)二叉樹的順序存儲(chǔ)結(jié)構(gòu)一般僅存儲(chǔ)完全二叉樹!ABC137D15二叉鏈表基本思想:令二叉樹的每個(gè)結(jié)點(diǎn)對(duì)應(yīng)一個(gè)鏈表結(jié)點(diǎn),鏈表結(jié)點(diǎn)除了存放與二叉樹結(jié)點(diǎn)有關(guān)的數(shù)據(jù)信息外,還要設(shè)置指示左右孩子的指針。
結(jié)點(diǎn)結(jié)構(gòu):
lchild
data
rchild其中,data:數(shù)據(jù)域,存放該結(jié)點(diǎn)的數(shù)據(jù)信息;lchild:左指針域,存放指向左孩子的指針;rchild:右指針域,存放指向右孩子的指針。
5.4二叉樹的存儲(chǔ)結(jié)構(gòu)及實(shí)現(xiàn)template<classDataType>structBiNode{DataTypedata;BiNode<T>*lchild,*rchild;};5.4二叉樹的存儲(chǔ)結(jié)構(gòu)及實(shí)現(xiàn)lchild
datarchild左孩子結(jié)點(diǎn)右孩子結(jié)點(diǎn)二叉鏈表GFEDBAABCDEFG∧∧∧∧∧∧∧∧C二叉鏈表5.4二叉樹的存儲(chǔ)結(jié)構(gòu)及實(shí)現(xiàn)具有n個(gè)結(jié)點(diǎn)的二叉鏈表中,有多少個(gè)空指針?GFEDBAABCDEFG∧∧∧∧∧∧∧∧C二叉鏈表5.4二叉樹的存儲(chǔ)結(jié)構(gòu)及實(shí)現(xiàn)具有n個(gè)結(jié)點(diǎn)的二叉鏈表中,有n+1個(gè)空指針。template<classDataType>classBiTree{public:BiTree(){root=Creat(root);}//構(gòu)造函數(shù),建立一棵二叉樹
~BiTree(){Release(root);}//析構(gòu)函數(shù)
voidPreOrder(){PreOrder(root);}//前序遍歷二叉樹
voidInOrder(){InOrder(root);}//中序遍歷二叉樹
voidPostOrder(){PostOrder(root);}//后序遍歷二叉樹
voidLeverOrder();//層序遍歷二叉樹private:BiNode<DataType>*root;//指向根結(jié)點(diǎn)的頭指針
BiNode<DataType>*Creat(BiNode<DataType>*bt);//構(gòu)造函數(shù)調(diào)用
voidRelease(BiNode<DataType>*bt);//析構(gòu)函數(shù)調(diào)用voidPreOrder(BiNode<DataType>*bt);//前序遍歷函數(shù)調(diào)用
voidInOrder(BiNode<DataType>*bt);//中序遍歷函數(shù)調(diào)用
voidPostOrder(BiNode<DataType>*bt);//后序遍歷函數(shù)調(diào)用};5.4二叉樹的存儲(chǔ)結(jié)構(gòu)及實(shí)現(xiàn)前序遍歷——遞歸算法template<classDataType>voidBiTree<DataType>::PreOrder(BiNode<DataType>*bt){if(bt==NULL)return;//遞歸調(diào)用的結(jié)束條件else{cout<<bt->data;//訪問根結(jié)點(diǎn)bt的數(shù)據(jù)域
PreOrder(bt->lchild);//前序遞歸遍歷bt的左子樹PreOrder(bt->rchild);//前序遞歸遍歷bt的右子樹}}5.4二叉樹的存儲(chǔ)結(jié)構(gòu)及實(shí)現(xiàn)前序遍歷——遞歸算法template<classDataType>voidBiTree<DataType>::PreOrder(BiNode<DataType>*bt){if(bt==NULL)return;else{cout<<bt->data;
PreOrder(bt->lchild);PreOrder(bt->rchild);
}}5.4二叉樹的存儲(chǔ)結(jié)構(gòu)及實(shí)現(xiàn)ABCDEFG中序遍歷——遞歸算法
template<classDataType>voidBiTree<DataType>::InOrder(BiNode<DataType>*bt){if(bt==NULL)return;//遞歸調(diào)用的結(jié)束條件else{InOrder(bt->lchild);//中序遞歸遍歷bt的左子樹
cout<<bt->data;//訪問根結(jié)點(diǎn)bt的數(shù)據(jù)域InOrder(bt->rchild);//中序遞歸遍歷bt的右子樹}}5.4二叉樹的存儲(chǔ)結(jié)構(gòu)及實(shí)現(xiàn)中序遍歷——遞歸算法
template<classDataType>voidBiTree<DataType>::InOrder(BiNode<DataType>*bt){if(bt==NULL)return;else{InOrder(bt->lchild);
cout<<bt->data;InOrder(bt->rchild);}}5.4二叉樹的存儲(chǔ)結(jié)構(gòu)及實(shí)現(xiàn)ABCDEFG后序遍歷——遞歸算法template<classDataType>voidBiTree<DataType>::PostOrder(BiNode<DataType>*bt){if(bt==NULL)return;//遞歸調(diào)用的結(jié)束條件else{PostOrder(bt->lchild);//后序遞歸遍歷bt的左子樹PostOrder(bt->rchild);//后序遞歸遍歷bt的右子樹cout<<bt->data;//訪問根結(jié)點(diǎn)bt的數(shù)據(jù)域}}5.4二叉樹的存儲(chǔ)結(jié)構(gòu)及實(shí)現(xiàn)后序遍歷——遞歸算法template<classDataType>voidBiTree<DataType>::PostOrder(BiNode<DataType>*bt){if(bt==NULL)return;else{PostOrder(bt->lchild);PostOrder(bt->rchild);cout<<bt->data;}}5.4二叉樹的存儲(chǔ)結(jié)構(gòu)及實(shí)現(xiàn)ABCDEFG層序遍歷5.4二叉樹的存儲(chǔ)結(jié)構(gòu)及實(shí)現(xiàn)ABCDEFG遍歷序列:AABCBDCEFGDEFG層序遍歷隊(duì)列Q初始化;2.如果二叉樹非空,將根指針入隊(duì);3.循環(huán)直到隊(duì)列Q為空3.1q=隊(duì)列Q的隊(duì)頭元素出隊(duì);3.2訪問結(jié)點(diǎn)q的數(shù)據(jù)域;3.3若結(jié)點(diǎn)q存在左孩子,則將左孩子指針入隊(duì);3.4若結(jié)點(diǎn)q存在右孩子,則將右孩子指針入隊(duì);5.4二叉樹的存儲(chǔ)結(jié)構(gòu)及實(shí)現(xiàn)層序遍歷template<classDataType>voidBiTree<DataType>::LeverOrder(){front=rear=-1;//采用順序隊(duì)列,并假定不會(huì)發(fā)生上溢if(root==NULL)return;//二叉樹為空,算法結(jié)束Q[++rear]=root;//根指針入隊(duì)while(front!=rear)//當(dāng)隊(duì)列非空時(shí){q=Q[++front];//出隊(duì)cout<<q->data;if(q->lchild!=NULL)Q[++rear]=q->lchild;if(q->rchild!=NULL)Q[++rear]=q->rchild;}}5.4二叉樹的存儲(chǔ)結(jié)構(gòu)及實(shí)現(xiàn)構(gòu)造函數(shù)——建立二叉樹為了建立一棵二叉樹,將二叉樹中每個(gè)結(jié)點(diǎn)的空指針引出一個(gè)虛結(jié)點(diǎn),其值為一特定值如“#”,以標(biāo)識(shí)其為空,把這樣處理后的二叉樹稱為原二叉樹的擴(kuò)展二叉樹。
為什么如此處理?5.4二叉樹的存儲(chǔ)結(jié)構(gòu)及實(shí)現(xiàn)如何由一種遍歷序列生成該二叉樹?遍歷是二叉樹各種操作的基礎(chǔ),可以在遍歷的過程中進(jìn)行各種操作,例如建立一棵二叉樹。擴(kuò)展二叉樹的前序遍歷序列:AB#D##C##5.4二叉樹的存儲(chǔ)結(jié)構(gòu)及實(shí)現(xiàn)DBAC#DBAC####構(gòu)造函數(shù)——建立二叉樹設(shè)二叉樹中的結(jié)點(diǎn)均為一個(gè)字符。假設(shè)擴(kuò)展二叉樹的前序遍歷序列由鍵盤輸入,root為指向根結(jié)點(diǎn)的指針,二叉鏈表的建立過程是:首先輸入根結(jié)點(diǎn),若輸入的是一個(gè)“#”字符,則表明該二叉樹為空樹,即root=NULL;否則輸入的字符應(yīng)該賦給root->data,,之后依次遞歸建立它的左子樹和右子樹。5.4二叉樹的存儲(chǔ)結(jié)構(gòu)及實(shí)現(xiàn)構(gòu)造函數(shù)——建立二叉樹template<classDataType>BiTree::BiTree(){
root=Creat(root);
}template<classDataType>BiNode<DataType>*BiTree<DataType>::Creat(BiNode<DataType>*bt){cin>>ch;//輸入結(jié)點(diǎn)的數(shù)據(jù)信息,假設(shè)為字符if(ch=='#')bt=NULL;//建立一棵空樹else{bt=newBiNode;bt->data=ch;//生成一個(gè)結(jié)點(diǎn),數(shù)據(jù)域?yàn)閏hbt->lchild=Creat(bt->lchild);//遞歸建立左子樹
bt->rchild=Creat(bt->rchild);//遞歸建立右子樹}returnbt;}5.4二叉樹的存儲(chǔ)結(jié)構(gòu)及實(shí)現(xiàn)二叉樹算法設(shè)計(jì)練習(xí)
遍歷二叉樹是二叉樹各種操作的基礎(chǔ),遍歷算法中對(duì)每個(gè)結(jié)點(diǎn)的訪問操作可以是多種形式及多個(gè)操作,根據(jù)遍歷算法的框架,適當(dāng)修改訪問操作的內(nèi)容,可以派生出很多關(guān)于二叉樹的應(yīng)用算法。voidInOrder
(BiNode<T>*root){if(root==NULL)return;else{
InOrder(root->lchild);
cout<<root->data;
InOrder(root->rchild);}}二叉樹算法設(shè)計(jì)練習(xí)設(shè)計(jì)算法求二叉樹的結(jié)點(diǎn)個(gè)數(shù)。voidCount(BiNode*root)//count為全局量并已初始化為0{if(root==NULL)return;else{
Count(root->lchild);count++;
Count(root->rchild);}}二叉樹算法設(shè)計(jì)練習(xí)設(shè)計(jì)算法按前序次序打印二叉樹中的葉子結(jié)點(diǎn)。voidPreOrder(BiNode*root){if(root==NULL)return;else{
if(!root->lchild&&!root->rchild)cout<<root->data;PreOrder(root->lchild);PreOrder(root->rchild);}}二叉樹算法設(shè)計(jì)練習(xí)設(shè)計(jì)算法求二叉樹的深度。
intDepth(BiNode*root){if(root==NULL)return0;else{hl=Depth(root->lchild);hr=Depth(root->rchild);returnmax(hl,hr)+1;}}二叉樹算法設(shè)計(jì)練習(xí)設(shè)計(jì)算法求樹中結(jié)點(diǎn)x的第i個(gè)孩子。
TNode*Search(TNode*root,DataTypex,inti){if(root->data==x){j=1;p=root->firstchild;while(p!=NULL&&j<i){j++;p=p->rightsib;}if(p!=NULL)returnp;elsereturnNULL;}
Search(root->firstchild,x,i);Search(root->rightsib,x,i);}AEBCFDGABCDEFG三叉鏈表5.4二叉樹的存儲(chǔ)結(jié)構(gòu)及實(shí)現(xiàn)GFEDBAABCDEFG∧∧∧∧∧∧∧∧C在二叉鏈表中,如何求某結(jié)點(diǎn)的雙親?三叉鏈表
lchild
dataparentrchild在二叉鏈表的基礎(chǔ)上增加了一個(gè)指向雙親的指針域。結(jié)點(diǎn)結(jié)構(gòu)其中:data、lchild和rchild三個(gè)域的含義同二叉鏈表的結(jié)點(diǎn)結(jié)構(gòu);parent域?yàn)橹赶蛟摻Y(jié)點(diǎn)的雙親結(jié)點(diǎn)的指針。
5.4二叉樹的存儲(chǔ)結(jié)構(gòu)及實(shí)現(xiàn)ABCDEFGA∧B∧D∧E∧F∧CG∧∧∧∧三叉鏈表5.4二叉樹的存儲(chǔ)結(jié)構(gòu)及實(shí)現(xiàn)ABCDEFG三叉鏈表的靜態(tài)鏈表形式5.4二叉樹的存儲(chǔ)結(jié)構(gòu)及實(shí)現(xiàn)0123456dataparentlchildrchildABCDEFG-1001223134-1-1-1-12-156-1-1-1線索鏈表5.4二叉樹的存儲(chǔ)結(jié)構(gòu)及實(shí)現(xiàn)如何保存二叉樹的某種遍歷序列?ABCDEFG中序遍歷序列:DGBAFCF如果二叉樹不改變,如何保存?順序存儲(chǔ)DGBAFCF線索鏈表5.4二叉樹的存儲(chǔ)結(jié)構(gòu)及實(shí)現(xiàn)如何保存二叉樹的某種遍歷序列?ABCDEFG中序遍歷序列:DGBAFCF如果二叉樹改變,如何保存?鏈接存儲(chǔ)DF
線索鏈表5.4二叉樹的存儲(chǔ)結(jié)構(gòu)及實(shí)現(xiàn)如何保存二叉樹的某種遍歷序列?ABCDEFG中序遍歷序列:DGBAFCF如何將二叉鏈表與中序鏈表結(jié)合?鏈接存儲(chǔ)DF
線索鏈表線索:將二叉鏈表中的空指針域指向前驅(qū)結(jié)點(diǎn)和后繼結(jié)點(diǎn)的指針被稱為線索;線索化:使二叉鏈表中結(jié)點(diǎn)的空鏈域存放其前驅(qū)或后繼信息的過程稱為線索化;線索鏈表:加上線索的二叉鏈表稱為線索鏈表。5.4二叉樹的存儲(chǔ)結(jié)構(gòu)及實(shí)現(xiàn)如何保存二叉樹的某種遍歷序列?將二叉鏈表中的空指針域指向其前驅(qū)結(jié)點(diǎn)和后繼結(jié)點(diǎn)
ltag
lchild
data
child
rtag0:lchild指向該結(jié)點(diǎn)的左孩子1:lchild指向該結(jié)點(diǎn)的前驅(qū)結(jié)點(diǎn)0:rchild指向該結(jié)點(diǎn)的右孩子1:rchild指向該結(jié)點(diǎn)的后繼結(jié)點(diǎn)ltag=rtag=5.4二叉樹的存儲(chǔ)結(jié)構(gòu)及實(shí)現(xiàn)結(jié)點(diǎn)結(jié)構(gòu)線索鏈表enumflag{Child,Thread};template<classDataType>structThrNode{DataTypedata;ThrNode<DataType>*lchild,*rchild;
flagltag,rtag;};5.4二叉樹的存儲(chǔ)結(jié)構(gòu)及實(shí)現(xiàn)線索鏈表
ltag
lchild
data
child
rtag結(jié)點(diǎn)結(jié)構(gòu)二叉樹的遍歷方式有4種,故有4種意義下的前驅(qū)和后繼,相應(yīng)的有4種線索二叉樹:⑴前序線索二叉樹⑵中序線索二叉樹⑶后序線索二叉樹⑷層序線索二叉樹5.4二叉樹的存儲(chǔ)結(jié)構(gòu)及實(shí)現(xiàn)線索二叉樹FABDCEG中序線索二叉樹5.4二叉樹的存儲(chǔ)結(jié)構(gòu)及實(shí)現(xiàn)線索二叉樹中序序列:DGBAECFtemplate<classDataType>classInThrBiTree{public:InThrBiTree();//構(gòu)造函數(shù),建立中序線索鏈表
~InThrBiTree();//析構(gòu)函數(shù),釋放各結(jié)點(diǎn)的存儲(chǔ)空間
ThrNode*Next(ThrNode<DataType>*p);//查找p的后繼
voidInOrder();//中序遍歷線索鏈表private:ThrNode*root;//指向線索鏈表的頭指針
ThrNode<DataType>*Creat(ThrNode<DataType>*bt);
voidThrBiTree(ThrNode<DataType>*bt,ThrNode<DataType>*pre);//構(gòu)造函數(shù)調(diào)用};5.4二叉樹的存儲(chǔ)結(jié)構(gòu)及實(shí)現(xiàn)中序線索鏈表類的聲明分析:建立線索鏈表,實(shí)質(zhì)上就是將二叉鏈表中的空指針改為指向前驅(qū)或后繼的線索,而前驅(qū)或后繼的信息只有在遍歷該二叉樹時(shí)才能得到。5.4二叉樹的存儲(chǔ)結(jié)構(gòu)及實(shí)現(xiàn)建立二叉鏈表遍歷二叉樹,將空指針改為線索中序線索鏈表的建立——構(gòu)造函數(shù)A頭指針BCDEFG∧∧∧∧∧∧00000000000000∧∧中序線索鏈表的建立過程5.4二叉樹的存儲(chǔ)結(jié)構(gòu)及實(shí)現(xiàn)已經(jīng)建立起二叉鏈表A頭指針BCDEFG∧∧∧∧∧∧00000000000000∧∧中序線索鏈表的建立過程5.4二叉樹的存儲(chǔ)結(jié)構(gòu)及實(shí)現(xiàn)中序遍歷二叉鏈表p為正在訪問的結(jié)點(diǎn)pre為剛訪問的結(jié)點(diǎn)p1A頭指針BCDEFG∧∧∧∧∧∧00000000000000∧∧中序線索鏈表的建立過程5.4二叉樹的存儲(chǔ)結(jié)構(gòu)及實(shí)現(xiàn)中序遍歷二叉鏈表p為正在訪問的結(jié)點(diǎn)pre為剛訪問的結(jié)點(diǎn)pre1p1A頭指針BCDEFG∧∧∧∧∧∧00000000000000∧中序線索鏈表的建立過程5.4二叉樹的存儲(chǔ)結(jié)構(gòu)及實(shí)現(xiàn)中序遍歷二叉鏈表p為正在訪問的結(jié)點(diǎn)pre為剛訪問的結(jié)點(diǎn)pre11p1A頭指針BCDEFG∧∧∧∧∧∧00000000000000中序線索鏈表的建立過程5.4二叉樹的存儲(chǔ)結(jié)構(gòu)及實(shí)現(xiàn)中序遍歷二叉鏈表p為正在訪問的結(jié)點(diǎn)pre為剛訪問的結(jié)點(diǎn)pre11p11A頭指針BCDEFG∧∧∧∧∧00000000000000中序線索鏈表的建立過程5.4二叉樹的存儲(chǔ)結(jié)構(gòu)及實(shí)現(xiàn)中序遍歷二叉鏈表p為正在訪問的結(jié)點(diǎn)pre為剛訪問的結(jié)點(diǎn)pre11p111A頭指針BCDEFG∧∧∧∧00000000000000中序線索鏈表的建立過程5.4二叉樹的存儲(chǔ)結(jié)構(gòu)及實(shí)現(xiàn)中序遍歷二叉鏈表p為正在訪問的結(jié)點(diǎn)pre為剛訪問的結(jié)點(diǎn)pre11p1111A頭指針BCDEFG∧∧∧00000000000000中序線索鏈表的建立過程5.4二叉樹的存儲(chǔ)結(jié)構(gòu)及實(shí)現(xiàn)中序遍歷二叉鏈表p為正在訪問的結(jié)點(diǎn)pre為剛訪問的結(jié)點(diǎn)pre11p11111A頭指針BCDEFG∧∧00000000000000中序線索鏈表的建立過程5.4二叉樹的存儲(chǔ)結(jié)構(gòu)及實(shí)現(xiàn)中序遍歷二叉鏈表p為正在訪問的結(jié)點(diǎn)pre為剛訪問的結(jié)點(diǎn)pre111111115.4二叉樹的存儲(chǔ)結(jié)構(gòu)及實(shí)現(xiàn)中序線索鏈表查找后繼FABDCEG⑴如果結(jié)點(diǎn)p的右標(biāo)志為1,則表明該結(jié)點(diǎn)的右指針是線索;⑵如果結(jié)點(diǎn)p的右標(biāo)志為0,則表明該結(jié)點(diǎn)有右孩子。根據(jù)中序遍歷的操作定義,它的后繼結(jié)點(diǎn)應(yīng)該是遍歷其右子樹時(shí)第一個(gè)訪問的結(jié)點(diǎn),即右子樹中的最左下結(jié)點(diǎn)。template<classDataType>ThrNode<DataType>*InThrBiTree<DataType>::Next(ThrNode<DataType>*p){if(p->rtag==1)q=p->rchild;//右標(biāo)志為1,可直接得到后繼結(jié)點(diǎn)
else{q=p->rchild;//工作指針q指向結(jié)點(diǎn)p的右孩子
while(q->ltag==0)//查找最左下結(jié)點(diǎn)
q=q->lchild;}returnq;}5.4二叉樹的存儲(chǔ)結(jié)構(gòu)及實(shí)現(xiàn)中序線索鏈表查找后繼二叉樹前序遍歷的非遞歸算法的關(guān)鍵:在前序遍歷過某結(jié)點(diǎn)的整個(gè)左子樹后,如何找到該結(jié)點(diǎn)的右子樹的根指針。解決辦法:在訪問完該結(jié)點(diǎn)后,將該結(jié)點(diǎn)的指針保存在棧中,以便以后能通過它找到該結(jié)點(diǎn)的右子樹。
在前序遍歷中,設(shè)要遍歷二叉樹的根指針為root,則有兩種可能:⑴若root!=NULL,則表明?如何處理?⑵若root=NULL,則表明?如何處理?前序遍歷——非遞歸算法5.5二叉樹遍歷的非遞歸算法訪問結(jié)點(diǎn)序列:A棧S內(nèi)容:BD
A
B前序遍歷的非遞歸實(shí)現(xiàn)
ADBC5.5二叉樹遍歷的非遞歸算法訪問結(jié)點(diǎn)序列:A棧S內(nèi)容:BD
A前序遍歷的非遞歸實(shí)現(xiàn)
ADBC
D5.5二叉樹遍歷的非遞歸算法訪問結(jié)點(diǎn)序列:A棧S內(nèi)容:BD
C前序遍歷的非遞歸實(shí)現(xiàn)
ADBCC5.5二叉樹遍歷的非遞歸算法1.棧s初始化;2.循環(huán)直到root為空且棧s為空
2.1當(dāng)root不空時(shí)循環(huán)
2.1.1輸出root->data;2.1.2將指針root的值保存到棧中;
2.1.3繼續(xù)遍歷root的左子樹
2.2如果棧s不空,則
2.2.1將棧頂元素彈出至root;
2.2.2準(zhǔn)備遍歷root的右子樹;前序遍歷——非遞歸算法(偽代碼)5.5二叉樹遍歷的非遞歸算法前序遍歷——非遞歸算法(偽代碼)template<classDataType>voidBiTree::PreOrder(BiNode<DataType>*root){top=-1;//采用順序棧,并假定不會(huì)發(fā)生上溢
while(root!=NULL||top!=-1){while(root!=NULL){cout<<root->data;//先訪問s[++top]=root;//再壓棧root=root->lchild;}if(top!=-1){root=s[top--];root=root->rchild;}
}}5.5二叉樹遍歷的非遞歸算法ADBC中序遍歷——非遞歸算法
在二叉樹的中序遍歷中,訪問結(jié)點(diǎn)的操作發(fā)生在該結(jié)點(diǎn)的左子樹遍歷完畢并準(zhǔn)備遍歷右子樹時(shí),所以,在遍歷過程中遇到某結(jié)點(diǎn)時(shí)并不能立即訪問它,而是將它壓棧,等到它的左子樹遍歷完畢后,再從棧中彈出并訪問之。中序遍歷的非遞歸算法只需將前序遍歷的非遞歸算法中的輸出語句cout<<bt->data移到bt=s[top--]之后即可。
5.5二叉樹遍歷的非遞歸算法中序遍歷——非遞歸算法template<classDataType>voidBiTree::PreOrder(BiNode<DataType>*root){top=-1;//采用順序棧,并假定不會(huì)發(fā)生上溢
while(root!=NULL||top!=-1){while(root!=NULL){s[++top]=root;root=root->lchild;}if(top!=-1){
root=s[top--];
cout<<root->data;root=root->rchild;}}}5.5二叉樹遍歷的非遞歸算法ABCDEFG后序遍歷——非遞歸算法在后序遍歷過程中,結(jié)點(diǎn)要入兩次棧,出兩次棧:⑴第一次出棧:只遍歷完左子樹,該結(jié)點(diǎn)不出棧,利用棧頂結(jié)點(diǎn)找到它的右子樹,準(zhǔn)備遍歷它的右子樹;⑵第二次出棧:遍歷完右子樹,將該結(jié)點(diǎn)出棧,并訪問它。因此,為了區(qū)別同一個(gè)結(jié)點(diǎn)的兩次出棧,設(shè)置標(biāo)志flag。5.5二叉樹遍歷的非遞歸算法棧元素類型定義如下:template<classDataType>structelement{BiNode<DataType>*ptr;intflag;//1表示第1次出棧,2表示第2次出棧};后序遍歷——非遞歸算法設(shè)根指針為bt,則可能有以下兩種情況:⑴若bt不等于NULL
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(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ǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 項(xiàng)目成本控制策略試題及答案
- 2025市政工程考試問題分析與試題及答案
- 經(jīng)濟(jì)法概論核心知識(shí)試題及答案集合
- 2025年云計(jì)算服務(wù)在智慧城市交通管理系統(tǒng)中的應(yīng)用與優(yōu)化報(bào)告
- 目標(biāo)明確的中級(jí)經(jīng)濟(jì)師試題及答案
- 2025年公共關(guān)系學(xué)考試快速通關(guān)試題及答案
- 招聘人事培訓(xùn)體系構(gòu)建
- 針對(duì)性訓(xùn)練提升效率執(zhí)業(yè)醫(yī)師考試試題及答案
- 高級(jí)會(huì)計(jì)信息處理試題及答案
- 項(xiàng)目審計(jì)的關(guān)鍵點(diǎn)試題及答案
- 19G522-1鋼筋桁架混凝土樓板圖集
- 2023年上半年中級(jí)信息系統(tǒng)監(jiān)理師下午真題
- 農(nóng)學(xué)專業(yè)深度解析模板
- 儲(chǔ)罐內(nèi)噴鋁施工方案
- 2024年江西省高考地理真題(解析版)
- 紹興市糧食批發(fā)市場經(jīng)營有限公司招聘筆試題庫2024
- 畢業(yè)研究生登記表(適用于江蘇省)
- 2024年光伏行業(yè)供應(yīng)鏈數(shù)字化建設(shè)白皮書
- 網(wǎng)絡(luò)傳播概論(第5版)課件 第七章 網(wǎng)絡(luò)傳播建構(gòu)的關(guān)系
- 公安機(jī)關(guān)拘留通知書(存根、附卷副本、正本)模板
- 《教育心理學(xué)(第3版)》全套教學(xué)課件
評(píng)論
0/150
提交評(píng)論