樹的儲存:雙親陣列法,孩子連結串列法,孩子兄弟法
在實際應用中,人們採用多種形式的儲存結構來表示樹,既有順序儲存結構,又有鏈式儲存結構,但無論採用哪種儲存結構,都要求儲存結構不但能儲存結點本身的資訊,還能儲存樹中各結點之間的邏輯關係。下面介紹幾種常用的樹的儲存方式。
1、雙親表示法
從樹的定義可知,除根結點外,樹中的每個結點都有唯一的一個雙親結點。根據這一特性,可用一組連續的儲存空間(一維陣列)儲存樹中的各結點。樹中的結點除儲存結點本身的資訊之外,還要儲存其雙親結點在陣列中的位置(陣列的序號),樹的這種表示法稱為雙親表示法。
下圖1
所示的樹的雙親表示法如圖1所示。圖中 pPos 域的值為-1 表示該結點是根結點,無雙親結點。
struct node
{
char data;
int pPos;
};
struct head
{
struct node m [10];
int n;
int pPos;
};
樹的雙親表示法對於實現 Parent(t)操作和 Root()操作非常方便。 Parent(t)操作可以在常量時間內實現,反覆呼叫Parent(t)操作, 直到遇到無雙親的結點(其 pPos值為-1)時,便找到了樹的根,這就是Root()操作的執行過程。但要實現查詢孩子結點和兄弟結點等操作非常困難,因為這需要查詢整個陣列。要實現這些操作,需要在結點結構中增設存放第1個孩子
2、孩子連結串列表示法
孩子連結串列表示法也是用一維陣列來儲存樹中各結點的資訊。但結點的結構與雙親表示法中結點的結構不同,孩子連結串列表示法中的結點除儲存本身的資訊外,不是儲存其雙親結點在陣列中的序號,而是儲存一個連結串列的第一個結點的地址資訊。這個連結串列是由該結點的所有孩子結點組成。每個孩子結點儲存有兩個資訊,一個是每個孩子結點在一維陣列中的
序號,另一個是下一個孩子結點的地址資訊。 孩子結點的結構如下所示:
孩子結點類 的定義如下(與前面一樣,只列出了成員欄位):
struct node
{
int pPos;
struct node *next;
};
樹的孩子連結串列表示法的結點的結構如下所示:
樹的孩子連結串列表示法的結點類 的定義如下:
struct elem
{
char data;
struct node *firstchild;
};
樹類的定義如下:
struct head
{
struct elem m[10];
int pPos;
int n;
} ;
圖1所示的樹的孩子連結串列表示法如圖3所示。
圖3樹的的孩子連結串列表示法
樹的孩子連結串列表示法對於實現查詢孩子結點等操作非常方便,但對於實現查詢雙親結點、兄弟結點等操作則比較困難。
3、孩子兄弟表示法
這是一種常用的資料結構,又稱二叉樹表示法,或二叉連結串列表示法,即以二叉連結串列作為樹的儲存結構。每個結點除儲存本身的資訊外,還有兩個引用域分別儲存該結點第一個孩子的地址資訊和下一個兄弟的地址資訊。樹類 CSTree只有一個成員欄位head,表示頭引用。 樹的孩子兄弟表示法的結點的結構如下所示: 樹的孩子兄弟表示法的結點類 CSNode的定義如下(與前面一樣,只列出了成員欄位):
struct node
{
char data;
struct node *child;
struct node *sibling;
};
圖1所示的樹的孩子兄弟表示法如圖4所示。
樹的孩子兄弟表示法對於實現查詢孩子、兄弟等操作非常方便,但對於實現查詢雙親結點等操作則非常困難。如果在樹的結點中再增加一個域來儲存孩子的雙親結點的地址資訊,則就可以較方便地實現上述操作了。