版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認(rèn)領(lǐng)
文檔簡介
從對線性結(jié)構(gòu)的研究過渡到對樹形結(jié)構(gòu)的研究,是數(shù)據(jù)結(jié)構(gòu)課程學(xué)習(xí)的一次躍變。
6.1樹的定義和基本術(shù)語6.1.1樹的定義
(非遞歸)
樹是由n(n
0)個結(jié)點組成的有限集合。如果n=0,稱為空樹;如果n>0,則:
有一個特定的稱之為根(root)的結(jié)點,它只有后繼,但沒有前驅(qū);
其余結(jié)點有且僅有一個直接前驅(qū),但可以有0個或多個后繼。是不是一棵樹?6.1.2樹的基本術(shù)語結(jié)點:數(shù)據(jù)元素及其分支
結(jié)點的子樹結(jié)點的度:結(jié)點射出的分支數(shù)。樹的度:樹內(nèi)各結(jié)點度的最大值。葉子結(jié)點(終端):度為0的結(jié)點。非終端結(jié)點:度不為0的結(jié)點。結(jié)點的層次:樹中根結(jié)點的層次為1,下一層結(jié)點的層次是2,以此類推。樹的深度:樹中所有結(jié)點層次的最大值。父結(jié)點:結(jié)點的前驅(qū)稱為該結(jié)點的父親。孩子結(jié)點:結(jié)點的后繼稱為該結(jié)點的孩子。兄弟:同一個父親的孩子之間互稱兄弟。堂兄弟:兄弟的孩子之間互稱堂兄弟。有序樹、無序樹:如果樹中每棵子樹從左向右的排列擁有一定的順序,不得互換,則稱為有序樹,否則稱為無序樹。填空:對于一棵具有n個結(jié)點的樹,該樹中所有結(jié)點的度數(shù)之和為?答:結(jié)點的度數(shù)之和應(yīng)為所有分支數(shù)之和,除了根結(jié)點之外,所有結(jié)點都有一個分支射入,因此樹中所有結(jié)點度數(shù)之和是n-16.1.3樹的表示形式(1)倒懸樹。是最常用的表示形式,如圖所示。
ABDCEGFHIMJKL(b)一般的樹6.1.3樹的表示形式(2)嵌套集合。是一些集合的集體,對于任何兩個集合,或者不相交,或者一個集合包含另一個集合。圖6-2(a)是圖6-1(b)樹的嵌套集合形式。(3)廣義表形式。圖6-2(b)是樹的廣義表形式。(4)凹入法表示形式。圖6-2(c)是樹的凹入法表示形式。樹的表示方法的多樣化正說明了樹結(jié)構(gòu)在日常生活中及計算機程序設(shè)計中的重要性。
圖
樹的其他三種表示法6.1.4抽象數(shù)據(jù)類型樹的定義
ADTTREE{
數(shù)據(jù)對象:
D={ai|ai∈ElemSet,i=1,2,...,n,n≥0}
數(shù)據(jù)關(guān)系:R
基本操作:}
ADTTREE
n個數(shù)據(jù)元素的集合。數(shù)據(jù)元素可以是整型、字符型、結(jié)構(gòu)類型。想利用數(shù)學(xué)的語言正確地描述出前驅(qū)和后繼結(jié)點的一對多的關(guān)系不太容易;不再要求,感興趣的同學(xué)自己看教材。關(guān)于基本操作的幾點說明:1、基本操作是定義于邏輯結(jié)構(gòu)上的基本操作,向外界提供一個與其通訊的接口。還沒有用具體的某種程序語言寫出具體的算法,而算法的實現(xiàn)只有在存儲結(jié)構(gòu)確立之后。對應(yīng)于不同的存儲結(jié)構(gòu),樹的基本操作的實現(xiàn)也不相同。2、基本操作的種類可隨實際需要的不同而不同,定義多少種基本操作由自己確定。3、針對不同的需要,基本操作的參數(shù)和返回值可以有所變化。樹的基本操作:(1)Root():求樹的根結(jié)點。(2)Parent(t):求結(jié)點t的雙親結(jié)點。(3)Child(t,i):求結(jié)點t的第i個子結(jié)點。(4)RightSibling(t):求結(jié)點t第一個右邊兄弟結(jié)點。(5)Insert(s,t,i):把樹s插入到樹中作為結(jié)點t的第i棵子樹。(6)Delete(t,i):刪除結(jié)點t的第i棵子樹。(7)Traverse(TraverseType):按某種方式遍歷樹。(8)Clear():清空樹。(9)IsEmpty:判斷樹是否為空樹。(10)GetDepth():求樹的深度。6.2二叉樹(BinaryTree)6.2.1二叉樹的定義1、特點:(1)每個結(jié)點至多有兩棵子樹。(即二叉樹中不存在度大于2的結(jié)點)(2)二叉樹的子樹有左右之分,其次序不能任意顛倒。654321判斷題:二叉樹是度為2的有序樹.()錯,不一定結(jié)點的度:結(jié)點的分支數(shù)樹的度:樹中結(jié)點度的最大值所以該樹的度為1.2、二叉樹的五種不同形態(tài)(a)空二叉樹(b)僅有根結(jié)點的二叉樹(c)右子樹為空的二叉樹(d)左子樹為空的二叉樹(e)左右子樹均非空的二叉樹3、抽象數(shù)據(jù)類型二叉樹的定義
ADT
BINARYTREE{
數(shù)據(jù)對象:
D={ai|ai∈ElemSet,i=1,2,...,n,n≥0}
數(shù)據(jù)關(guān)系:R
基本操作:}
ADTBINARYTREE
n個數(shù)據(jù)元素的集合。數(shù)據(jù)元素可以是整型、字符型、結(jié)構(gòu)類型。想利用數(shù)學(xué)的語言正確地描述出二叉樹中結(jié)點元素之間的關(guān)系不太容易。所以不再要求。關(guān)于基本操作的幾點說明:(1)基本操作是定義于邏輯結(jié)構(gòu)上的基本操作,向外界提供一個與其通訊的接口。還沒有用具體的某種程序語言寫出具體的算法,而算法的實現(xiàn)只有在存儲結(jié)構(gòu)確立之后。對應(yīng)于不同的存儲結(jié)構(gòu),樹的基本操作的實現(xiàn)也不相同。
(2)基本操作的種類可隨實際需要的不同而不同,定義多少種基本操作由自己確定。(3)針對不同的需要,基本操作的參數(shù)和返回值可以有所變化。二叉樹的基本操作:(1)publicbool
IsEmpty()//判斷是否是空二叉樹(2)publicNode<T>GetRoot()//獲取根結(jié)點
(3)publicNode<T>Getleftchild(Node<T>p)//獲取結(jié)點的左孩子結(jié)點
(4)publicNode<T>Getrightchild(Node<T>p)//獲取結(jié)點的右孩子結(jié)點
(5)publicvoidInsertL(T
val,Node<T>p)
//將結(jié)點p的左子樹插入值為val的新結(jié)點,原來的左子樹成為新結(jié)點的左子樹(6)publicvoidInsertR(T
val,Node<T>p)
//將結(jié)點p的右子樹插入值為val的新結(jié)點,原來的右子樹成為新結(jié)點的右子樹
(7)publicNode<T>DeleteL(Node<T>p)
//若p非空,刪除p的左子樹
(8)publicNode<T>DeleteR(Node<T>p)
//若p非空,刪除p的右子樹
(9)publicbool
IsLeaf(Node<T>p)
//判斷是否是葉子結(jié)點(10)publicvoidPreOrder(Node<T>root)//二叉樹的前序遍歷(11)publicvoidInOrder(Node<T>root)//二叉樹的中序遍歷(12)publicvoidPostOrder(Node<T>root)//二叉樹的后序遍歷(13)publicvoidLevelOrder(Node<T>root)//二叉樹的層次遍歷性質(zhì)1
若二叉樹的層次從1開始,則在二叉樹的第i層最多有2i-1個結(jié)點。(i
1)證明:數(shù)學(xué)歸納法。當(dāng)i=1時,2i-1
=1;二叉樹的第1層上只有一個根結(jié)點。第一層的結(jié)點數(shù)1<=2i-1,所以命題成立。假設(shè)i=k時命題成立,即第k層上結(jié)點數(shù)目最多為2k-1
當(dāng)i=k+1時,第k+1層上結(jié)點數(shù)目最多為第k層上的兩倍,即2*2k-1
=2k+1-1;命題也成立。綜上所述:命題成立。
6.2.2二叉樹的性質(zhì)選擇題:在二叉樹的第三層上最多有幾個結(jié)點()。A.3B.4C.5D.6性質(zhì)2
深度為k的二叉樹最多有2k-1個結(jié)點。(k
1)
利用性質(zhì)1的結(jié)論每一層上具有的最大結(jié)點數(shù)如下表所示:
第i層k……321每層結(jié)點數(shù)
2k-1……222120二叉樹所具有的最大結(jié)點數(shù):選擇題:二叉樹的深度為4,則二叉樹最多有()個結(jié)點。A.13B.14C.15D.16
性質(zhì)3
對任何一棵二叉樹,如果其葉結(jié)點個數(shù)為n0,度為2的結(jié)點個數(shù)為n2,則有n0=n2+1。
證明:設(shè)度為1的結(jié)點有n1個,總結(jié)點個數(shù)為n,分支數(shù)為e
因為二叉樹中所有結(jié)點的度都小于等于2,所以有下式成立:
n=n0+n1+n2
(總結(jié)點數(shù)=度為0的結(jié)點數(shù)+度為1的結(jié)點數(shù)+度為2的結(jié)點數(shù))
除了根結(jié)點外,其余結(jié)點都有一個分支進入,所以有下式成立:
n=e+1(總結(jié)點數(shù)=總分支數(shù)+1)鏈接又因為這些分支都是由度為1或度為2的結(jié)點射出的,所以有下式成立:
e=2n2+n1鏈接
綜合上面三式:
n0+n1+n2=2n2+n1+1即n0=n2+1
選擇題假定一棵二叉樹中,度為2的結(jié)點數(shù)為15,度為1的結(jié)點數(shù)為30,則葉子結(jié)點數(shù)為()。A.15B.16C.17D.47定義1
滿二叉樹(FullBinaryTree)
一棵深度為k且有2k-1個結(jié)點的二叉樹稱為滿二叉樹。下面兩棵樹是否是滿二叉樹?為了引出完全二叉樹的定義,需要對滿二叉樹的結(jié)點按照從上至下,從左往右的順序進行編號。定義2
完全二叉樹(CompleteBinaryTree)
深度為k,有n個結(jié)點的二叉樹,當(dāng)且僅當(dāng)其每一個結(jié)點都與深度為k的滿二叉樹中編號從1至n的結(jié)點一一對應(yīng)時,稱之為完全二叉樹。
如何判斷一棵二叉樹是否是完全二叉樹?
1)對二叉樹從上到下、自左至右進行編號。
2)對比二叉樹結(jié)點與相同編號的滿二叉樹結(jié)點位置是否一一對應(yīng);若一一對應(yīng),則是完全二叉樹;如不一一對應(yīng),則不是完全二叉樹。
判斷下列二叉樹abc是否是完全二叉樹(二叉樹結(jié)點已編號)滿二叉樹二叉樹a二叉樹b二叉樹c定義2
完全二叉樹(CompleteBinaryTree)若設(shè)二叉樹的深度為h,則共有h層。除第h層外,其它各層(1
h-1)的結(jié)點數(shù)都必須達(dá)到最大個數(shù),第h層可以從右向左連續(xù)缺若干結(jié)點。
判斷二叉樹是否是完全二叉樹,可根據(jù)此定義判斷.
二叉樹a二叉樹b二叉樹c完全二叉樹的特點是:1)只允許最后一層有空缺結(jié)點且空缺在右邊,即葉子結(jié)點只能在層次最大的兩層上出現(xiàn);2)對任一結(jié)點,如果其右子樹的深度為j,則其左子樹的深度必為j或j+1。性質(zhì)4
具有n個結(jié)點的完全二叉樹的深度為
log2n
+1證明:設(shè)完全二叉樹的深度為k,則前k-1層的結(jié)點數(shù)
第i層K-1……321每層結(jié)點數(shù)
2k-2……222120
k-1層的結(jié)點總數(shù)為2k-1-1,第k層最少有1個結(jié)點,最多有2k-1個結(jié)點,所以結(jié)點數(shù)n滿足:2k-1
n<=2k-1,由此式可推出下式一定成立:2k-1
n<2k
取對數(shù)k-1log2n<k
即log2n
<k
log2n+1
因為k為整數(shù),所以k=
log2n
+1選擇題一棵完全二叉樹有18個結(jié)點,則完全二叉樹的深度為A.3B.4C.5D.6一棵具有n個結(jié)點的完全二叉樹的樹高度(深度)是()
【南京理工大學(xué)1996一、8(2分)】A.
log2n+1B.Log2n+1C.log2n
D.Log2n-1一棵完全二叉樹上有1001個結(jié)點,其中葉子結(jié)點的個數(shù)是()
【西安交通大學(xué)1996三、2(3分)】A.250B.501C.254D.505
解:在完全二叉樹中,度為1的結(jié)點數(shù)n1或為0或為1。
由性質(zhì)3可知n0=n2+1即n2=n0-1
又因為n=n0+n1+n2
所以n=2n0+n1-1
將n=1001代入得:2n0+n1=1002
又因為n0必須為整數(shù),所以n1的值必為0。
所以n0=501
性質(zhì)5
如果將一棵有n個結(jié)點的完全二叉樹的結(jié)點按層序(自頂向下,同一層自左向右)連續(xù)編號1,2,…,n,對結(jié)點i(1
i
n)有以下關(guān)系:
若i==1,則i是二叉樹的根,無雙親若i>1,則i的雙親為
i/2
若2*i≤n,則i的左孩子為2*i,否則無左孩子若2*i+1≤n,則i的右孩子為2*i+1,否則無右孩子6.2.3二叉樹的存儲結(jié)構(gòu)1.順序存儲結(jié)構(gòu)(數(shù)組表示)
完全二叉樹的順序存儲:c語言中認(rèn)為:將完全二叉樹中的結(jié)點按照從上至下、自左往右的順序存儲到一維數(shù)組中。
普通二叉樹的順序存儲:也是將普通二叉樹中的結(jié)點按照從上至下、自左往右的順序存儲到一維數(shù)組中。(中間的空缺結(jié)點也留出相應(yīng)的位置)3105172312013245617051223316543210acb0132456
圖示二叉樹盡管只有三個結(jié)點,也要存儲到一個長度為7的數(shù)組中,浪費存儲空間。6543210cba練習(xí):畫出下圖所示二叉樹的順序存儲結(jié)構(gòu)acb如果存儲結(jié)點數(shù)為30的單支樹,需要一個多大的一維數(shù)組?(同學(xué)們自算)acbG…答:利用性質(zhì)2,補齊空缺結(jié)點后,算出共有230-1個結(jié)點。存儲一個30個結(jié)點的單支樹,要用長度為230-1的數(shù)組(1G),微型機根本不支持。存儲空間的浪費異常明顯。
怎樣來解決這個問題?
不給空缺的結(jié)點留位置。按照從上到下,從左到右的順序?qū)⒍鏄涞慕Y(jié)點存儲到一維數(shù)組中。(30個結(jié)點的單支樹只需存儲到一個長度為30的數(shù)組中)避免了存儲空間的浪費,但這樣做行不行呢?答:不行。兩棵不同的二叉樹對應(yīng)的存儲結(jié)構(gòu)是完全相同的。計算機要嚴(yán)格避免二義性。不同的二叉樹必須對應(yīng)不同的存儲結(jié)構(gòu)。如果兩棵不同的二叉樹對應(yīng)的存儲結(jié)構(gòu)是完全相同的,計算機在看到這樣的一個數(shù)組的時候就不知道它表示的是那棵二叉樹了。2.二叉樹的鏈?zhǔn)酱鎯Γ?)二叉鏈表結(jié)點結(jié)構(gòu):包含兩個指針域和一個數(shù)據(jù)域:指針域存儲指向左右孩子的指針,數(shù)據(jù)域存儲結(jié)點本身的信息。
結(jié)點的JAVA語言描述:class
Node<T>{
Tdata;
Node<T>
leftchild,
rightchild;};二叉樹a的鏈?zhǔn)酱鎯Y(jié)構(gòu)如下圖所示:因每個結(jié)點中包含兩個指針,所以這種形式的鏈?zhǔn)酱鎯Y(jié)構(gòu)又被稱為二叉鏈表。課堂練習(xí):請畫出下面二叉樹的二叉鏈表結(jié)構(gòu)。acbcban個結(jié)點的二叉鏈表共有n+1個空指針域,為什麼?答:在含有n個結(jié)點的二叉鏈表中,共有2n個指針域,但實際有效的指針數(shù)等于二叉樹中的分支數(shù)(即n-1),所以共存在n+1個空的指針域。選擇題10個結(jié)點的二叉鏈表中共有()個空的指針域。A.9B.10C.11D.12(2)三叉鏈表結(jié)點結(jié)構(gòu):包含三個指針域和一個數(shù)據(jù)域:指針域存儲指向左右孩子的指針以及指向父親的指針,數(shù)據(jù)域存儲結(jié)點本身的信息。結(jié)點的JAVA語言表示:class
Node<T>{Tdata;
Node<T>leftchild,rightchild;Node<T>parent;};二叉樹a的三叉鏈表結(jié)構(gòu)如下圖所示:3、二叉鏈表存儲結(jié)構(gòu)下基本操作的實現(xiàn)1)結(jié)點類的實現(xiàn)二叉樹的二叉鏈表的結(jié)點類有3個成員字段:數(shù)據(jù)域字段data;左孩子引用域字段leftchild;右孩子引用域字段rightchild。
packagedspakage3;importdspackage1.CSeqQueue;classNode<T>{
publicTdata;//數(shù)據(jù)域
publicNode<T>leftchild;//左孩子
publicNode<T>rightchild;//右孩子
//三個參數(shù)構(gòu)造器
publicNode(Tval,Node<T>lp,Node<T>rp)
{
data=val;
leftchild=lp;
rightchild=rp;}
//兩個參數(shù)構(gòu)造器
public
Node(Node<T>lp,Node<T>rp){
leftchild=lp;
rightchild=rp;}
//一個參數(shù)構(gòu)造器
public
Node(T
val){
data=val;
leftchild=null;
rightchild=null;}
//無參構(gòu)造器
publicNode(){
leftchild=null;
rightchild=null;}}
2)二叉鏈表類
只要知道了根結(jié)點的地址,就可以確定整棵樹,所以用一個根結(jié)點引用root就可以確定整棵樹。所以二叉鏈表的類BiTree<T>只有一個成員字段root表示根結(jié)點引用。public
class
BiTree<T>{
publicNode<T>root;//根結(jié)點引用
//無參構(gòu)造器
public
BiTree(){
root=null;}
//一個參數(shù)構(gòu)造器
public
BiTree(T
val)
{Node<T>p=newNode<T>(val);
root=p;}
//三個參數(shù)構(gòu)造器
publicBiTree(Tval,Node<T>lp,Node<T>rp){Node<T>p=newNode<T>(val,lp,rp);
root=p;}
//判斷是否是空二叉樹
public
booleanIsEmpty(){
if(root==null){
return
true;}
else{
return
false;}}
//獲取根結(jié)點
publicNode<T>Getroot(){
return
root;
}
//獲取結(jié)點的左孩子結(jié)點
publicNode<T>Getleftchild(Node<T>p){
return
p.leftchild;}
//獲取結(jié)點的右孩子結(jié)點
publicNode<T>Getrightchild(Node<T>p){
return
p.rightchild;}
//將結(jié)點p的左子樹插入值為val的新結(jié)點,
//原來的左子樹成為新結(jié)點的左子樹
public
voidInsertL(Tval,Node<T>p)
//將結(jié)點p的左子樹插入值為val的新結(jié)點,
//原來的左子樹成為新結(jié)點的左子樹
public
voidInsertL(Tval,Node<T>p){Node<T>tmp=newNode<T>(val);
//建立值為val的新結(jié)點
tmp.leftchild=p.leftchild;
//原來的左子樹成為新結(jié)點的左子樹
p.leftchild=tmp;
//新結(jié)點成為結(jié)點p的左孩子
}
//將結(jié)點p的右子樹插入值為val的新結(jié)點,
//原來的右子樹成為新結(jié)點的右子樹
public
voidInsertR(Tval,Node<T>p)
//將結(jié)點p的右子樹插入值為val的新結(jié)點,
//原來的右子樹成為新結(jié)點的右子樹
public
voidInsertR(Tval,Node<T>p){Node<T>tmp=newNode<T>(val);
//建立值為val的新結(jié)點
tmp.rightchild=p.rightchild;
//原來的右子樹成為新結(jié)點的右子樹
p.rightchild=tmp;
//新結(jié)點成為結(jié)點p的右孩子
}
//若p非空,刪除p的左子樹
publicNode<T>DeleteL(Node<T>p){
if((p==null)||(p.leftchild==null)){//p為空或p無左子樹
return
null;//返回空引用
}Node<T>tmp=p.leftchild;
//令新的引用tmp指向左子樹
p.leftchild=null;//令左子樹為空,即刪除
return
tmp;//返回原來左子樹
}
//若p非空,刪除p的右子樹
publicNode<T>DeleteR(Node<T>p){
if((p==null)||(p.rightchild==null)){//p為空或p無右子樹
return
null;//返回空引用
}Node<T>tmp=p.rightchild;
//令新的引用tmp指向右子樹
p.rightchild=null;//令右子樹為空,即刪除
return
tmp;//返回原來右子樹
}
//判斷是否是葉子結(jié)點
public
boolean
IsLeaf(Node<T>p){
if
((p!=null)&&(p.leftchild==null)&&(p.rightchild==null)){//p不為空,且無左孩子和右孩子
return
true;}
else{
return
false;}}
6.3遍歷二叉樹和線索鏈表(TraversingBinaryTree)
所謂樹的遍歷,就是按某種次序訪問樹中的結(jié)點,要求每個結(jié)點訪問一次且僅訪問一次。
遍歷的結(jié)果:產(chǎn)生一個關(guān)于結(jié)點的線性序列。
設(shè)訪問根結(jié)點記作D
遍歷根的左子樹記作L
遍歷根的右子樹記作R
則可能的遍歷次序有
先序DLRDRL逆先序中序LDRRDL逆中序后序LRDRLD
逆后序6.3.1遍歷二叉樹先序遍歷(PreorderTraversal)先序遍歷二叉樹算法的框架是若二叉樹為空,則空操作;否則訪問根結(jié)點(D);先序遍歷左子樹(L);先序遍歷右子樹(R)。cab*-表達(dá)式語法樹遍歷結(jié)果(前綴表達(dá)式)
-*a
b
cpublic
void
PreOrder(Node<T>root){
//根結(jié)點為空
if(root==null){
return;}
//處理根結(jié)點
System.out.println(root.data);
//先序遍歷左子樹
PreOrder(root.leftchild);
//先序遍歷右子樹
PreOrder(root.rightchild);}中序遍歷二叉樹算法的框架是:若二叉樹為空,則空操作;否則中序遍歷左子樹(L);訪問根結(jié)點(D);中序遍歷右子樹(R)。遍歷結(jié)果(中綴表達(dá)式)
a*b-
c中序遍歷(InorderTraversal)表達(dá)式語法樹cab*-
中序遍歷二叉樹的遞歸算法
public
void
InOrder(Node<T>root){
//根結(jié)點為空
if(root==null){
return;}
//中序遍歷左子樹
InOrder(root.leftchild);
//處理根結(jié)點
System.out.println(root.data);
//中序遍歷右子樹
InOrder(root.rightchild);}后序遍歷(PostorderTraversal)后序遍歷二叉樹算法的框架是若二叉樹為空,則空操作;否則后序遍歷左子樹(L);后序遍歷右子樹(R);訪問根結(jié)點(D)。遍歷結(jié)果(后綴表達(dá)式)
a
b*c-cab*-表達(dá)式語法樹后序遍歷二叉樹的遞歸算法
public
void
PostOrder(Node<T>root){
//根結(jié)點為空
if(root==null){
return;}
//后序遍歷左子樹
PostOrder(root.leftchild);
//后序遍歷右子樹
PostOrder(root.rightchild);
//處理根結(jié)點
System.out.println(root.data);}CDEBA上機作業(yè):二叉鏈表存儲結(jié)構(gòu)下,建立圖示二叉樹并對其進行中序遍歷.
源碼:CDEBApublic
static
void
main(String[]args){
BiTree<Character>evergreen=new
BiTree<Character>('A');evergreen.InsertL('B',evergreen.root);
evergreen.InsertR('C',evergreen.root);
evergreen.InsertL('E',evergreen.root.rightchild);
evergreen.InsertR('D',evergreen.root.leftchild);
evergreen.InOrder(evergreen.root);}6.3.2二叉線索鏈表
講完了二叉鏈表及該種存儲結(jié)構(gòu)下基本操作的實現(xiàn)以后,再講二叉鏈表基礎(chǔ)上的另一種存儲結(jié)構(gòu)-二叉線索鏈表.
畫出圖示樹的二叉鏈表,寫出圖示樹的中序遍歷結(jié)果。CDEBACABED圖示樹按照中序遍歷的結(jié)果是:BDAEC當(dāng)以二叉鏈表作存儲結(jié)構(gòu)時,只能找到結(jié)點的左右孩子信息,卻無法直接得到結(jié)點的前驅(qū)和后繼信息(按照中序遍歷次序確定的)。同時n個結(jié)點的二叉鏈表有n+1個空指針域。能否利用這些空的指針域存儲結(jié)點的前驅(qū)和后繼信息(中序)?當(dāng)然是可以的。利用空的左指針指向它的前驅(qū),利用空的右指針指向它的后繼。我們稱這種存儲結(jié)構(gòu)為二叉線索鏈表。6.3.2二叉線索鏈表1、結(jié)點結(jié)構(gòu)lpointerltagdatartagrpointerltag=0表示左指針指向的是左孩子ltag=1表示左指針指向的是前驅(qū)。rtag=0表示右指針指向的是右孩子;rtag=1表示右指針指向的是后繼。用java語言描述一下結(jié)點class
BiThrNode<T>{Tdata;
BiThrNode<T>lpointer,rpointer;
int
ltag,rtag;};如果空的左指針指向的是中序遍歷下的前驅(qū),空的右指針指向的是中序遍歷下的后繼,稱這種二叉線索鏈表為中序線索鏈表。如果空的左指針指向的是先序遍歷下的前驅(qū),空的右指針指向的是先序遍歷下的后繼,稱這種二叉線索鏈表為先序線索鏈表。如果空的左指針指向的是后序遍歷下的前驅(qū),空的右指針指向的是后序遍歷下的后繼,稱這種二叉線索鏈表為后序線索鏈表。畫出圖示樹的中序線索鏈表CDEBACABED1)畫出樹的二叉鏈表結(jié)構(gòu)2)添上標(biāo)志位有孩子填“0”沒孩子填“1”3根據(jù)中序遍歷的結(jié)果BDAEC把空的指針補上
為了處理的方便,一般情況下都給線索鏈表加上一個頭結(jié)點。令剩下的兩個空指針都指向頭結(jié)點。頭結(jié)點的左指針指向根結(jié)點,頭結(jié)點的右指針指向按中序遍歷的最后一個結(jié)點。頭結(jié)點的左標(biāo)志是0,右標(biāo)志是1。作業(yè):畫出圖示樹的先序線索鏈表CDEBA先序線索鏈表、中序線索鏈表、后序線索鏈表存儲結(jié)構(gòu)下基本操作的實現(xiàn),礙于時間關(guān)系,不再講。(但是研究生入學(xué)考試通常會在這兒出大題)山東大學(xué)2005碩士研究生考試試題(10分)寫一算法,完成對中序線索二叉樹的中序掃描。也就是怎樣根據(jù)中序線索鏈表得到二叉樹中序遍歷的線性序列。即中序線索鏈表存儲結(jié)構(gòu)下中序遍歷基本操作的實現(xiàn)。
6.4.1樹的存儲1.雙親表示法主要描述的是結(jié)點的雙親關(guān)系。指出結(jié)點的雙親是誰。把圖示樹的結(jié)點按照從上至下從左往右的順序存儲到一維數(shù)組中,同時附設(shè)一個指示器指示其雙親結(jié)點。ABFKHGEDCR6K6H6G3F1E1D0C0B0A-1R0213456789如何表示此數(shù)組?每一個元素都是兩項的組合,可以考慮用類表示。class
PTNode<T>{//元素類型
Tdata;
int
parent;
//雙親位置};
6K6H6G3F1E1D0C0B0A-1R0213456789此數(shù)組一共有10個元素
PTNode<Character>[]tree=(PTNode<Character>[])newObject[10];2.孩子表示法:
主要描述的是結(jié)點的孩子關(guān)系。指出結(jié)點的孩子有哪些。由于每個結(jié)點的孩子個數(shù)不一定相等,所以利用鏈?zhǔn)酱鎯Y(jié)構(gòu)更加適宜。
(把每個結(jié)點的孩子都用一條鏈把它們串起來,父親牽著孩子的手丟不了)
K
H
G
F
E
D
C
B
A
R1235987460123456789ABFKHGEDCR鏈表中結(jié)點:class
CTNode{
int
child;
CTNode
next;};數(shù)組中結(jié)點:class
CTBox<T>{Tdata;
CTNode
firstchild;
//孩子鏈表頭引用};整個數(shù)組:CTBox<Character>[]tree1=(CTBox<Character>[])newObject[10];
K
H
G
F
E
D
C
B
A
R1235987460123456789用JAVA語言描述一下此種結(jié)構(gòu):3.孩子雙親表示法
指出結(jié)點的父親是誰,同時指出結(jié)點的孩子有哪些。ABFKHGEDCR6K6H6G3F1E1D0C0B0A-1R1235987460123456789鏈表中結(jié)點:class
CTNode{
int
child;
CTNode
next;};數(shù)組中結(jié)點:class
CTBox<T>{Tdata;
intparent;
CTNode
firstchild;
//孩子鏈表頭引用};整個數(shù)組:CTBox<Character>[]tree1=(CTBox<Character>[])newObject[10];6K6H6G3F1E1D0C0B0A-1R1235987460123456789用JAVA語言描述一下此種結(jié)構(gòu):4.孩子兄弟表示法(二叉鏈表表示)結(jié)點的左指針指向結(jié)點的第一個孩子結(jié)點,右指針指向下一個兄弟結(jié)點。ABFKHGEDCRKFACDEGHBR結(jié)點的C#表示:class
CSNode<T>{Tdata;
CSNode<T>firstchild;
CSNode<T>nextsibling;};KFACDEGHBRABFKHGEDCRABFKHGEDCR以二叉鏈表為媒介可以導(dǎo)出樹和二叉樹之間的一個對應(yīng)關(guān)系。給定一棵樹,可以找到唯一的一棵二叉樹與之對應(yīng)。圖示樹對應(yīng)的二叉樹是什麼?練習(xí):畫出圖示樹對應(yīng)的二叉樹ADECBBEDCAADECB6.4.2森林與二叉樹的轉(zhuǎn)換1、森林轉(zhuǎn)換成二叉樹:
1)將森林中的每一棵樹都轉(zhuǎn)化成二叉樹
2)第二棵二叉樹作為第一棵二叉樹的右子樹,第三棵二叉樹作為第二棵二叉樹的右子樹,依次類推。例題:將下面三棵樹的森林轉(zhuǎn)化成二叉樹。2、二叉樹轉(zhuǎn)換成森林1)分解二叉樹取二叉樹的根及左子樹為第一棵二叉樹,取其右子樹的根及其左子樹為第二棵二叉樹……依次類推。2)把沒有右子樹的二叉樹轉(zhuǎn)化成樹。例題:將下面的二叉樹轉(zhuǎn)化成森林。6.4.3樹與森林的遍歷1、樹的遍歷(先根遍歷、后根遍歷)(1)先根遍歷:先訪問樹的根結(jié)點,然后依次先根遍歷根的每棵子樹(2)后根遍歷:先依次后根遍歷每棵子樹,然后訪問根結(jié)點圖示樹的先根遍歷結(jié)果:ABCDE圖示樹的后根遍歷結(jié)果:BDCEA對應(yīng)二叉樹的先序遍歷結(jié)果:ABCDE對應(yīng)二叉樹的中序遍歷結(jié)果:BDCEA樹的先根遍歷轉(zhuǎn)換后的二叉樹的先序遍歷樹的后根遍歷轉(zhuǎn)換后的二叉樹的中序遍歷森林的遍歷(1)先根次序遍歷的規(guī)則:
訪問F的第一棵樹的根結(jié)點;
先根次序遍歷第一棵樹的子樹森林;
先根次序遍歷其它樹組成的森林。(2)中根次序遍歷的規(guī)則:
中根次序遍歷第一棵樹的子樹森林;
訪問F的第一棵樹的根結(jié)點;
中根次序遍歷其它樹組成的森林。 森林的先序遍歷:對應(yīng)二叉樹的先序遍歷森林的中序遍歷:對應(yīng)二叉樹的中序遍歷具有不同路徑長度的二叉樹6.6赫夫曼樹
(HuffmanTree)及其應(yīng)用1、路徑長度(PathLength)
兩個結(jié)點之間的路徑長度是連接兩結(jié)點的路徑上的分支數(shù)。樹的路徑長度是各結(jié)點到根結(jié)點的路徑長度之和。6.6.1哈夫曼樹2、帶權(quán)路徑長度(WeightedPathLength,WPL)
結(jié)點的帶權(quán)路徑長度:從該結(jié)點到樹根的路徑長度與結(jié)點上權(quán)的乘積。
樹的帶權(quán)路徑長度是樹的各葉結(jié)點所帶的權(quán)值與該結(jié)點到根的路徑長度的乘積的和。3、Huffman樹
給定的n個權(quán)值{w1,w2,…,wn},在n個葉結(jié)點(葉結(jié)點權(quán)值分別為w1,w2,…,wn
)的帶權(quán)二叉樹中,帶權(quán)路徑長度達(dá)到最小的二叉樹稱為Huffman(哈夫曼)樹,又稱最優(yōu)二叉樹。給定的n個權(quán)值{w1,w2,…,wn},如何構(gòu)造一棵哈夫曼樹?
Huffman算法(1)
由給定的n個權(quán)值{w1,w2,…,wn},構(gòu)造具有n棵二叉樹的森林F={T1,T2,…,Tn},其中每一棵二叉樹Ti只有一個帶有權(quán)值wi的根結(jié)點,其左、右子樹均為空。
在F中選取兩棵根結(jié)點的權(quán)值最小的二叉樹,作為左、右子樹合并成一棵新的二叉樹,且新二叉樹的根結(jié)點的權(quán)值為其左、右子樹上根結(jié)點的權(quán)值之和。
(2)
重復(fù)以下步驟,直到F中僅剩下一棵樹為止:
Huffman樹構(gòu)造示例在F中選取兩棵根結(jié)點的權(quán)值最小的二叉樹,作為左、右子樹合并成一棵新的二叉樹,且新二叉樹的根結(jié)點的權(quán)值為其左、右子樹上根結(jié)點的權(quán)值之和。作業(yè):給定一組權(quán)值(5,9,11,2,7,16),試設(shè)計相應(yīng)的哈夫曼樹。6.6.2哈夫曼樹的應(yīng)用(哈夫曼編碼)對信息進行編碼,得到二進制碼文,在介質(zhì)(網(wǎng)線)中傳輸?shù)氖潜忍亓鳎炊M制碼文),接收方對收到的二進制碼文按編碼規(guī)則進行譯碼,還原成信息。‘ABACCDA’
00010010101100‘ABACCDA’
編碼譯碼A,B,C,D四個的編碼分別為00,01,10和11。通過網(wǎng)絡(luò)傳輸7道選擇題的答案給同學(xué)‘ABACCDA’,因為要傳輸?shù)男畔⒅兄怀霈F(xiàn)了ABCD四種字符,用?位二進制編碼就可以。對ABCD的編碼如下所示:則信息‘ABACCDA’的編碼為:00010010101100,要傳送的二進制碼文總長為14位。二進制碼文到達(dá)接收方后,接收方按照二位一個字符的編碼原則進行譯碼,還原成信息‘ABACCDA’。
別的因素相同的情況下,所要傳輸?shù)亩M制碼文長度越短,信息傳輸所需要的時間越短,信息的傳輸速度就越快。
為減少二進制碼文長度,重新設(shè)A,B,C,D四個字符的編碼為0,00,1和01,則‘ABACCDA’的二進制碼文為000011010,總長為9位。接收方對收到的二進制碼文進行譯碼的時候會出現(xiàn)什麼問題呢?
0000可譯成ABA,AAAA,BB,BAA
都可以。
盡管這種編碼方式縮短了二進制碼文,但由于不能正確地譯碼,所以是不可行的。怎樣的編碼才能正確地譯碼呢?前綴編碼前綴編碼:任何一個字符的編碼都不是另一個字符的編碼的前綴。000101
010010111
ABCD00011011
是前綴編碼不是前綴編碼是前綴編碼
利用赫夫曼樹可以構(gòu)造一種不等長的二進制編碼,并且構(gòu)造所得的赫夫曼編碼是一種最優(yōu)前綴編碼,使所傳二進制碼文的總長度最短。利用哈夫曼樹構(gòu)造哈夫曼編碼
1、以信息‘ABACCDA’各個字符出現(xiàn)的次數(shù)作為權(quán)值構(gòu)造哈夫曼樹。
A--3B--1C--2D--17124312BDCA2、從根結(jié)點開始,左分支填0,右分支填1。7124312BDCA010011
3、根據(jù)哈夫曼樹可得到哈夫曼編碼,如下所示:
A--0B--110C--10D--111
按哈夫曼編碼A--0B--110C--10D--111
對信息‘ABACCDA’進行編碼:0110010
10
1110二進制碼文總長度13位
再也找不到一種前綴編碼使得二進制碼文比這個長度更短。
A--0B--100C--101D--11是前綴編碼信息‘ABACCDA’的編碼為:01000101101110二進制碼文總長度是14位。
A--00B--01C--10D--11是前綴編碼信息‘ABACCDA’的編碼為:00010010101100二進制碼文總長度為14位。
作業(yè):已知某系統(tǒng)在通訊聯(lián)絡(luò)中只可能出現(xiàn)八種字符A,B,C,D,E,F,G,H,其概率分別為:0.05,0.29,0.07,0.08,0.14,0.23,0.03,0.11。試設(shè)計赫夫曼編碼.
解:可以以概率{0.05,0.29,0.07,0.08,0.14,0.23,0.03,0.11}作為權(quán)值構(gòu)造哈夫曼樹。若嫌小數(shù)麻煩,也可以以概率*100作為權(quán)值構(gòu)造哈夫曼樹。只要各個權(quán)值的比例保持不變就行。即以{5,29,7,8,14,23,3,11}作為權(quán)值構(gòu)造哈夫曼樹。1、構(gòu)造哈夫曼樹295783142311A5G38D8C715H1119E1429F2342B29581002、左分支填0,右分支填1,可得到八個字符的哈夫曼編碼。A5G38D8C715H1119E1429F2342B29581000000111100011100010011001111011011101111源碼實現(xiàn)對應(yīng)于哈夫曼樹不同的存儲結(jié)構(gòu)建立哈夫曼樹和求哈夫曼編碼的實現(xiàn)算法也不一樣。假定哈夫曼樹采用如下存儲結(jié)構(gòu):Weight域存放結(jié)點的權(quán)值,同時parent指出結(jié)點的父親是誰,lChild指出結(jié)點的左孩子是誰、rChild指出右孩子是誰?結(jié)點有四個域:一個域weight,存放該結(jié)點的權(quán)值;一個域lChild,存放該結(jié)點的左孩子結(jié)點在數(shù)組中的序號;一個域rChild,存放該結(jié)點的右孩子結(jié)點在數(shù)組中的序號;一個域parent,存放結(jié)點的父親結(jié)點在數(shù)組中的序號;
weightparentlChild
rChild結(jié)點類Node的C#定義:packagedspackage4;import
java.util.Scanner;classNode{
public
float
weight;
//weight表示該結(jié)點的權(quán)值;
public
int
lChild;
public
int
rChild;
//lChild和rChild分別表示左、右孩子結(jié)點在數(shù)組中的序號;
public
int
parent;
//parent表示結(jié)點的父親結(jié)點在數(shù)組中的序號;
//無參構(gòu)造器
publicNode() {
weight=0;
lChild=-1;
rChild=-1;
parent=-1; }
//四個參數(shù)構(gòu)造器
public
Node(float
w,int
lc,int
rc,int
p) {
weight=w;
lChild=lc;
rChild=rc;
parent=p; }}哈夫曼樹類HuffmanTree的C#實現(xiàn):public
class
HuffmanTree{
public
int
leafNum;
//leafNum表示哈夫曼樹葉子結(jié)點的數(shù)目;
publicNode[]data;
//data數(shù)組用于存放結(jié)點;
public
HuffmanTree(int
n)
{leafNum=n;
data=newNode[2*n-1];
//在哈夫曼樹中沒有度為1的結(jié)點,哈夫曼樹中總結(jié)點數(shù)=n0+n2又由二叉樹的性質(zhì)知n0=n2+1;即n2=n0-1,所以哈夫曼樹中總結(jié)點數(shù)=n0+n2=2n0-1;所以葉子結(jié)點數(shù)目為n時,總結(jié)點數(shù)目為2n-1,需要一個長度為2n-1的數(shù)組存儲哈夫曼樹中的結(jié)點。
}
//成員方法Create,它的功能是輸入n個葉子結(jié)點的權(quán)值,創(chuàng)建一棵哈夫曼樹
public
voidCreate() {
float
min1;
float
min2;
int
tmp1;
int
tmp2;
//令所有結(jié)點的父親域,左孩子域,右孩子域均為-1
for(int
i=0;i<2*leafNum-1;i++) {
data[i]=newNode();
data[i].parent=data[i].lChild=data[i].rChild=-1; }
//輸入n個葉子結(jié)點的權(quán)值
Scannerreader=newScanner(System.in);
//實例化Scanner類對象reader
//調(diào)用reader對象的相應(yīng)方法,讀取鍵盤數(shù)據(jù)
for(int
i=0;i<leafNum;++i) { System.out.print("第"+(i+1)+"個葉子結(jié)點的權(quán)值");
data[i].weight=reader.nextFloat(); }
//處理leafNum個葉子結(jié)點,建立哈夫曼樹
for(int
i=leafNum;i<2*leafNum-1;++i)
{
min1=min2=Float.MAX_VALUE;
tmp1=tmp2=0;
//在0~i-1個結(jié)點中找權(quán)值最小的兩個結(jié)點
,min1<=min2,循環(huán)執(zhí)行完畢以后,min1權(quán)值最小的結(jié)點的權(quán)值,min2是權(quán)值次小的結(jié)點的權(quán)值。
for(int
j=0;j<i;++j)
{
if((data[j].weight<min1)&&(data[j].parent==-1))
{
min2=min1;
tmp2=tmp1;
tmp1=j;
min1=data[j].weight; }
else
if((data[j].weight<min2)&&(data[j].parent==-1)) {
min2=data[j].weight;
tmp2=j; } }
//權(quán)值最小的兩個結(jié)點父結(jié)點為i
data[tmp1].parent=i;
data[tmp2].parent=i;
data[i].weight=data[tmp1].weight+data[tmp2].weight;
//父結(jié)點的權(quán)值為兩個結(jié)點的權(quán)值之和
//權(quán)值最小的兩結(jié)點分別是i結(jié)點的左孩子和右孩子
data[i].lChild=tmp1;
data[i].rChild=tmp2; } }
1475274Weightparentlchild
rchild7
-1-1
-15
-1-1
-12
-1-1
-14
-1-1
-1
-1-1
-1
-1-1
-1
-1-1
-10123456哈夫曼樹構(gòu)造示例:14852746Weightparentlchild
rchild7
-1-1
-15
-1-1
-12
-1-1
-14
-1-1
-16
-1-1
-1
-1-1
-1
-1-1
-10123456tmp1tmp24423i1495274611Weightparentlchild
rchild7
-1-1
-15
-1-1
-12
4
-1-14
4
-1-16
-12
311
-1-1
-1
-1-1
-10123456tmp1tmp25514i1505274611Weightparentlchild
rchild7
-1-1
-15
5
-1-12
4
-1-14
4
-1-16
5
2
311
-11
418
-1-1
-10123456tmp1tmp26605i18
public
void
huffmancode() {String[]huffman=new
String[leafNum];
//新建一個字符串?dāng)?shù)組huffman,長度為葉子結(jié)點的數(shù)目,存放各葉子的哈夫曼編碼
for(int
i=0;i<leafNum;i++) {
huffman[i]="";//第i個字符串初始值為空
for(int
c=i,f=data[i].parent;f!=-1;c=f,f=data[f].parent)
{
if(data[f].lChild==c)huffman[i]="0"+huffman[i];
else
huffman[i]="1"+huffman[i]; }//從葉子到根逆向求各個葉子結(jié)點的哈夫曼編碼
System.out.println("權(quán)值為"+data[i].weight+"的哈夫曼編碼是"+huffman[i]); } }
public
static
void
main(String[]args){
System.out.print("請輸入葉子結(jié)點的數(shù)目"); Scannerreader=new
Scanner(System.in);
//實例化Scanner類對象reader
//調(diào)用reader對象的相應(yīng)方法,讀取鍵盤數(shù)據(jù)
int
m=reader.nextInt();
HuffmanTree
ceshi=new
HuffmanTree(m);
//調(diào)用構(gòu)造函數(shù)
System.out.println("請輸入各葉子結(jié)點的權(quán)值");
ceshi.Create();//構(gòu)造哈夫曼樹
ceshi.huffmancode();//求哈夫曼編碼
}}
作業(yè):已知某系統(tǒng)在通訊聯(lián)絡(luò)中只可能出現(xiàn)十種字符A,B,C,D,E,F,G,H,I,G
其概率分別為:0.04,0.21,0.09,0.07,0.08,0.14,0.11,0.13,0.10,0.03。試設(shè)計赫夫曼編碼.
解:可以以概率{0.04,0.21,0.09,0.07,0.08,0.14,0.11,0.13,0.10,0.03}作為權(quán)值構(gòu)造哈夫曼樹。若嫌小數(shù)麻煩,也可以以概率*100作為權(quán)值構(gòu)造哈夫曼樹。只要各個權(quán)值的比例保持不變就行。即以{4,21,9,7,8,14,11,13,10,3}作為權(quán)值構(gòu)造哈夫曼樹。1、構(gòu)造哈夫曼樹42111021217347141327981714312、左分支填0,右分支填1,可得到十個字符的哈夫曼編碼。4211g10i2121b7d3j4a71413h279c8e1714f31010000000011
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 蘇教版語文說課稿技巧
- 英語中考單詞記憶技巧分享
- 北師大版小學(xué)數(shù)學(xué)長方體教學(xué)
- 春季蘇教版三年數(shù)學(xué)科目期中測試題
- 八年級上蘇教版物理考試題目
- 蘇教版五年級數(shù)學(xué)小數(shù)改寫的教學(xué)設(shè)計分享與點評
- 油脂對心血管疾病的治療策略
- 蘇教版不規(guī)則圖形面積計算解析
- 養(yǎng)花公開課在北師大的創(chuàng)新實踐
- 人教版鴻門宴教學(xué)總結(jié)
- 項目施工圖設(shè)計現(xiàn)場交底參考工作指引
- 單板滑雪專題教育課件
- 賈否動畫概論第三版優(yōu)質(zhì)課件
- 彌漫性間質(zhì)性肺病診斷思路-董文
- 含山昱潔環(huán)??萍加邢薰竞浇?jīng)濟開發(fā)區(qū)樹脂砂綜合處置中心建設(shè)項目環(huán)境影響報告表
- 肩周炎肩關(guān)節(jié)周圍炎治療與康復(fù)
- 明視視光中心創(chuàng)業(yè)計劃書
- 拼音詞語總表1
- GB/T 14100-1993燃?xì)廨啓C驗收試驗
- 項目一-發(fā)售車票課件
- 《別了不列顛尼亞》 《縣委書記的榜樣-焦裕祿》課件-統(tǒng)編版高中語文選擇性必修上冊1
評論
0/150
提交評論