此結構是將二叉樹的所有結點,按照一定的次序,儲存到一片連續的儲存單元中。因此,必須將結點排成乙個適當的線性序列,使得結點在這個序列中的相應位置能反映出結點之間的邏輯關係。這種結構特別適用於近似滿二叉樹。
在一棵具有n個結點的近似滿二叉樹中,我們從樹根起,自上層到下層,逐層從左到右給所有結點編號,就能得到乙個足以反映整個二叉樹結構的線性序列,如圖6所示。其中每個結點的編號就作為結點的名稱。
圖6 近似滿二叉樹的結點編號
因此,我們可以對樹的型別作如下說明:
tposition=integer;
treetype=record
nodecount:integer;
nodelist:array [1..maxnodecount] of labeltype;
end;
將陣列下標作為結點名稱(編號),就可將二叉樹中所有結點的標號儲存在一維陣列中。例如,圖6中的二叉樹的順序儲存結構如圖7所示。
圖7 近似滿二叉樹的順序儲存結構
在二叉樹的這種表示方式下,各結點之間的邏輯關係是隱含表示的。近似滿二叉樹中,除最下面一層外,各層都充滿了結點。可能除最底層外,每一層的結點個數恰好是上一層結點個數的2倍。因此,從乙個結點的編號就可推知其父親,左、右兒子,和兄弟等結點的編號。例如,對於結點i我們有:
僅當i=1時,結點i為根結點;
當i>1時,結點i的父結點為i/2;
結點i的左兒子結點為2i;
結點i的右兒子結點為2i+1;
當i為奇數且不為1時,結點i的左兄弟結點為i-1;
當i為偶數時,結點i的右兄弟結點為i+1。
由上述關係可知,近似滿二叉樹中結點的層次關係足以反映結點之間的邏輯關係。因此,對近似滿二叉樹而言,順序儲存結構既簡單又節省儲存空間。
對於一般的二叉樹,採用順序儲存時,為了能用結點在陣列中的位置來表示結點之間的邏輯關係,也必須按近似滿二叉樹的形式來儲存樹中的結點。顯然,這將造成儲存空間的浪費。在最壞情況下,乙個只有k個結點的右單枝樹卻需要2k-1個結點的儲存空間。例如,只有3個結點的右單枝樹,如圖8(a)所示,添上一些實際不存在的虛結點後,成為一棵近似滿二叉樹,相應的順序儲存結構如圖8(b)所示。
圖8 一般二叉樹的順序儲存結構
下面我們就用這種順序儲存結構來實現二叉樹的常用操作。在這種表示法中,整數0表示空結點∧。對於非近似滿二叉樹,我們將其補為近似滿二叉樹,並規定乙個特殊的標號&,用來表示補充的結點,&要根據標號的具體型別來確定。
順序儲存結構實現adt二叉樹的操作
函式 parent(v,t);功能
這是乙個求父結點的函式,函式值為樹t中結點v的父親。當v是根結點時,函式值為∧,表示結點v沒有父結點。
實現
function parent(v:tposition;var t:treetype):tposition;
begin
return(v div 2);
end;
說明
根據這種表示法,我們知道,當i>1時,結點i的父結點為i/2。
複雜性
顯然為o(1)。
函式 left_child(v,t);功能
這是乙個求左兒子結點的函式。函式值為樹t中結點v的左兒子。當結點v沒有左兒子時,函式值為∧。
實現
function left_child(v:tposition;var t:treetype):tposition;
begin
if (2*v>t.nodecount)or(t.nodelist[2*v]=&) then return(0)
else return(2*v);
end;
說明
如果結點v的左兒子存在,則其下標為2*v。
複雜性
顯然為o(1)。
函式 right_child(v,t);功能
這是乙個求右兒子結點的函式。函式值為樹t中結點v的右兒子。當結點v沒有右兒子時,函式值為∧。
實現
procedure right_child(v:tposition;var t:treetype):tposition;
begin
if (2*v+1>t.nodecount)or(t.nodelist[2*v+1]=&) then return(0)
else return(2*v+1);
end;
說明
如果結點v的左兒子存在,則其下標為2*v+1。
複雜性
顯然為o(1)。
函式 create(x,left,right,t);功能
這是乙個建樹過程。該函式生成一棵新的二叉樹t,t的根結點標號為x,左右兒子分別為left和right。
實現
procedure create(x:labeltype;var left,right,t:treetype);
begin
t.nodelist[1]:=x;
t.nodecount:=left.nodecount+right.nodecount+1;
h_left:=cal(left.nodecount);
h_right:=cal(right.nodecount);
if h_left>h_right then h:=h_left else h:=h_right;
for i:=left.nodecount+1 to (1 shl (h+1))-1 do left.nodelist[i]:=&;
left.nodecount:=(1 shl (h+1))-1;
if h_rightbegin
for i:=right.nodecount+1 to (1 shl h)-1 do right.nodelist[i]:=&;
right.nodecount:=(1 shl h)-1;
end;
for i:=1 to left.nodecount do
t.nodelist[(1 shl cal(i))+i]:=left.nodelist[i];
for i:=1 to right.nodecount do
t.nodelist[(1 shl (cal(i)+1))+i]:=right.nodelist[i];
end;
其中cal(i)用來計算含有i個結點的近似滿二叉樹t的高度,cal(i)=log2(i+1)-1,可以實現如下:
function cal(i:integer;):integer;
varx:real;
begin
x:=log2(i+1)-1;
if x=int(x) then return(x) else return(int(x)+1);
end;
其中log2(n)計算實數n以2為底的對數。
說明
在順序儲存的結構下,建立一棵新的二叉樹的過程比較複雜。我們首先給出以下幾個命題:
命題一
一棵高度為h的滿二叉樹有2h+1-1個結點。
證明:
滿二叉樹的第i層有2i個結點,i=0,1,2,...,h(樹根為第0層),因此高度為h的滿二叉樹有20+21+..+2h = 2h+1-1個結點。
推論一
我們從樹根起,自上層到下層,逐層從左到右給二叉樹的所有結點編號,如圖6所示,則近似滿二叉樹的第h層的從左到右第k個結點的編號為2h+k-1。
證明:
由於是近似滿二叉樹,所以第0層到第h-1層是滿二叉樹,根據命題一知道共有2h-1個結點,因此第h層的從左到右第1個結點的編號為2h-1+1,第h層的從左到右第k個結點的編號為2h-1+k。
推論二
一棵有n個結點的近似滿二叉樹,高度為log2(n+1)-1,其中是天花板符號,x表示大於等於x的最小整數。
證明:
有n個結點的近似滿二叉樹,若其高度為h,則滿足2h-1h+1-1,化簡得 log2(n+1)-1 ≤ h < [log2(n+1)-1]+1,即h=log2(n+1)-1。
推論三
在近似滿二叉樹t中,設編號為i的結點處於t的第h層從左到右第k個位置上,則h=log2(i+1)-1,k=i-(2h-1)。
證明:
我們先不考慮編號大於i的結點,則前i個結點構成一棵近似滿二叉樹,根據推論二知其層數為h=log2(i+1)-1,又因為第0層到第h-1層是滿二叉樹,根據命題一知道共有2h-1個結點,所以編號為i的結點處於第h層的第k=i-(2h-1)個位置上。
我們用t(h,k)表示樹t的第h層的第k個結點,則有下列命題:
命題二
left(h,k)=t(h+1,k),right(h,k)=t(h+1,k+2h),其中left和right分別是樹t的根結點的左右子樹。
證明:
顯然。
我們用n(v,t)表示結點v在生成的新樹t中的編號,則有下列命題:
命題三
對於left中編號為i的結點v,n(v,t)=2h +i,其中h=log2(i+1)-1;對於right中編號為i的結點v,n(v,t)=2h+1+i,其中h=log2(i+1)-1。
證明:
在left中編號為i的結點,根據推論三,他處於left的第h=log2(i+1)-1層,第k=i-(2h-1)個位置上。根據命題二該結點處於新樹t的第h+1層第k個位置上,所以根據推論一,它在二叉樹t中的編號為2h+1+k-1=2*2h+[i-(2h-1)]-1=2h+i。結點在right中的情況同理可證。
有了命題三,我們就可以完成建樹的過程。演算法如下:
根據推論二計算left和right的高度,分別為hleft和hright ;
設h=max,新樹t的高度就為h+1;
將left補成高度為h的滿二叉樹;
若hright
依次掃瞄left的每乙個結點,根據命題三計算出left中編號為i的結點在t中的位置,將其複製到t中;
依次掃瞄right的每乙個結點,根據命題三計算出right中編號為i的結點在t中的位置,將其複製到t中;
具體程式見前文的實現。
複雜性
演算法的主要時間花在掃瞄和賦值結點上,設新樹有n個結點,則複雜性為o(n)。
二叉樹的順序儲存結構
二叉樹的順序儲存結構 include includeusing namespace std define virnode 0 定義虛擬節點 define max tree size 100 定義儲存空間最大量 typedef char elemtype 定義節點型別 typedef elemtype...
二叉樹的順序儲存結構
新增鏈結描述 上面文章中講述二叉樹的順序儲存結構的 這裡給執行了一下,以及遇到的一些問題,我都在 裡標註了.include includeusing namespace std const int m 100 class bitree int create bt 手動輸入二叉樹各節點的資訊 void...
二叉樹的順序儲存結構
完全二叉樹的順序儲存結構的性質 完全二叉樹的順序儲存結構 採用一維陣列,按層序順序依次儲存二叉樹的每乙個結 點。如下圖所示 一般二叉樹的順序儲存結構 通過虛設部分結點,使其變成相應的完全二叉樹。如已知某結點的層序編號i,則可求得該結點的雙親結點 左孩子結點和右孩子結點,然後檢測其值是否為虛設的特殊結...