二叉樹是非線性結構,即每一個數據結點至多隻有一個前驅,但能夠有多個後繼。它可採用順序存儲結構和鏈式存儲結構。node
1.順序存儲結構數組
二叉樹的順序存儲,就是用一組連續的存儲單元存放二叉樹中的結點。所以,必須把二叉樹的全部結點安排成爲一個恰當的序列,結點在這個序列中的相互位置能反映出結點之間的邏輯關係,用編號的方法從樹根起,自上層至下層,每層自左至右地給全部結點編號,缺點是有可能對存儲空間形成極大的浪費,在最壞的狀況下,一個深度爲k且只有k個結點的右單支樹須要2k-1個結點存儲空間。依據二叉樹的性質,徹底二叉樹和滿二叉樹採用順序存儲比較合適,樹中結點的序號能夠惟一地反映出結點之間的邏輯關係,這樣既可以最大可能地節省存儲空間,又能夠利用數組元素的下標值肯定結點在二叉樹中的位置,以及結點之間的關係。圖5-5(a)是一棵徹底二叉樹,圖5-5(b)給出的圖5-5(a)所示的徹底二叉樹的順序存儲結構。spa
(a) 一棵徹底二叉樹 (b) 順序存儲結構指針
圖5-5 徹底二叉樹的順序存儲示意圖code
對於通常的二叉樹,若是仍按從上至下和從左到右的順序將樹中的結點順序存儲在一維數組中,則數組元素下標之間的關係不可以反映二叉樹中結點之間的邏輯關係,只有增添一些並不存在的空結點,使之成爲一棵徹底二叉樹的形式,而後再用一維數組順序存儲。如圖5-6給出了一棵通常二叉樹改造後的徹底二叉樹形態和其順序存儲狀態示意圖。顯然,這種存儲對於需增長許多空結點才能將一棵二叉樹改形成爲一棵徹底二叉樹的存儲時,會形成空間的大量浪費,不宜用順序存儲結構。最壞的狀況是右單支樹,如圖5-7 所示,一棵深度爲k的右單支樹,只有k個結點,卻需分配2k-1個存儲單元。blog
(a) 一棵二叉樹 (b) 改造後的徹底二叉樹it
(c) 改造後徹底二叉樹順序存儲狀態class
圖5-6 通常二叉樹及其順序存儲示意圖二叉樹
(a) 一棵右單支二叉樹 (b) 改造後的右單支樹對應的徹底二叉樹數據類型
(c) 單支樹改造後徹底二叉樹的順序存儲狀態
圖5-7 右單支二叉樹及其順序存儲示意圖
結構5-1二叉樹的順序存儲
#define Maxsize 100 //假設一維數組最多存放100個元素 typedef char Datatype; //假設二叉樹元素的數據類型爲字符 typedef struct { Datatype bt[Maxsize]; int btnum; }Btseq; 複製代碼
2.鏈式存儲結構
二叉樹的鏈式存儲結構是指,用鏈表來表示一棵二叉樹,即用鏈來指示元素的邏輯關係。
一般的方法是鏈表中每一個結點由三個域組成,數據域和左右指針域,左右指針分別用來給出該結點左孩子和右孩子所在的鏈結點的存儲地址。其結點結構爲:
其中,data域存放某結點的數據信息;lchild與rchild分別存放指向左孩子和右孩子的指針,當左孩子或右孩子不存在時,相應指針域值爲空(用符號∧或NULL表示)。利用這樣的結點結構表示的二叉樹的鏈式存儲結構被稱爲二叉鏈表,如圖5-8所示。
(a) 一棵二叉樹 (b) 二叉鏈表存儲結構
圖5-8 二叉樹的二叉鏈表表示示意圖
爲了方便訪問某結點的雙親,還能夠給鏈表結點增長一個雙親字段parent,用來指向其雙親結點。每一個結點由四個域組成,其結點結構爲:
這種存儲結構既便於查找孩子結點,又便於查找雙親結點;可是,相對於二叉鏈表存儲結構而言,它增長了空間開銷。利用這樣的結點結構表示的二叉樹的鏈式存儲結構被稱爲三叉鏈表。
圖5-9給出了圖5-8 (a)所示的一棵二叉樹的三叉鏈表表示。
圖5-9二叉樹的三叉鏈表表示示意圖
儘管在二叉鏈表中沒法由結點直接找到其雙親,但因爲二叉鏈表結構靈活,操做方便,對於通常狀況的二叉樹,甚至比順序存儲結構還節省空間。所以,二叉鏈表是最經常使用的二叉樹存儲方式。
結構5-2二叉樹的鏈式存儲
#define datatype char //定義二叉樹元素的數據類型爲字符 typedef struct node //定義結點由數據域,左右指針組成 { Datatype data; struct node *lchild,*rchild; }Bitree;