11.樹的抽象數據類型和幾種表示法


/*
樹(Tree)
6.3 樹的抽象數據類型
相對於線性結構,樹的操作就完全不同了,這里我們給出一些基本和常用操作。
ADT 樹(tree)
Data
    樹是由一個根節點和若干棵子樹構成。樹中結點具有相同數據類型及層次關系。
Operation
    InitTree(*T);           構造空樹T
    DestroyTree(*T);        銷毀樹T
    CreateTree(*T, definition);     按definition中給出樹的定義來構造樹
    ClearTree(*T);          若樹T存在,則將樹T清空為空樹
    TreeEmpty(T);           若T為空樹,返回true,否則返回false
    TreeDepth(T);           返回T的深度
    Root(T);                返回T的根結點
    Value(T, cur_e);        cur_e是樹T中一個結點,返回此結點的值
    Assign(T, cur_e, value);    給樹T的結點cur_e賦值為value
    Parent(T, cur_e);       若cur_e是樹T的非根結點,則返回它的雙親,否則返回空
    LeftChild(T, cur_e);    若cur_e是樹T的非葉結點,則返回它的雙親,否則返回空
    RightSibling(T, cur_e); 若cur_e有右兄弟,則返回它的右兄弟,否則返回空
    InsertChild(*T, *p, i, c);  其中p指向樹T的某個結點,i為所指結點p的度加上1,非空樹c與T不相交,
                                操作結果為 插入c為樹T中p指結點的第i棵子樹
    DeleteChild(*T, *p, i);     其中p指向樹T的某個結點,i為所指結點p的度,
                                操作結果為 刪除T中p所指結點的第i棵子樹
endADT
*/

/*
6.4 樹的存儲結構
    說到存儲結構,就會想到我們前面章節講過的順序存儲和鏈式存儲兩種結構。
    先來看看順序存儲結構,用一段地址連續的存儲單元依次存儲線性表的數據元素。這對於線性表來說是很自然的,
對於樹這樣一對多的結構呢?
    樹中某個結點的孩子可以有多個,這就意味着,無論按何種順序將樹中所有結點存儲到數組中,結點的存儲位置
都無法直接反映邏輯關系,你想想看,數據元素挨個存儲,誰是誰的雙親,誰是誰的孩子呢?簡單的存儲結構是不能
滿足樹的實現要求的。
    不過充分利用順序存儲和鏈式存儲結構的特點,完全可以實現對樹的存儲結構的表示。我們這里要介紹三種不同的
表示法:雙親表示法、孩子表示法、孩子兄弟表示法。
*/


/*6.4.1 雙親表示法*/

//樹的雙親表示法結點結構定義
#define MAX_TREE_SIZE 100
//樹節點的數據類型,目前暫定為整形
typedef int TElemType;
//節點結構
typedef struct PTNode
{
    //結點數據
    TElemType data;
    //雙親位置,通常講的父節點
    int parent;
} PTNode;

//樹結構
typedef struct
{
    //結點數組
    PTNode nodes[MAX_TREE_SIZE];
    //跟的位置和結點數
    int r, n;
} PTree;

/*6.4.2 孩子表示法*/
/*
具體的辦法是,把每個結點的孩子結點排列起來,以單鏈表作存儲結構,則n個結點有n個孩子鏈表,如果是
葉子結點則此單鏈表為空。然后n個頭指針又組成一個線性表,采用順序存儲結構,存放進一個一維數組中。
見原書 284頁 圖6-4-4
為此,設計兩種節點結構,
一個是 孩子鏈表的孩子結點;其中child是數據域,用來存儲某個結點在表頭數組中
的下標。next是指針域,用來存儲指向某節點的下一個孩子結點的指針。
另一個 是表頭數組的表頭結點,其中data是數據域,存儲某結點的數據信息。firstchild是頭指針域,存儲
該結點的孩子鏈表的頭指針。
*/

/*樹的孩子表示法結構定義*/
#define MAX_TREE_SIZE 100
//孩子結點
typedef struct CTNode
{
    int child;
    struct CTNode *next;
} *ChildPtr;
//表頭結構
typedef struct 
{
    TElemType data;
    ChildPtr firstchild;
} CTBox;
//樹結構
typedef struct 
{
    /*結點數組*/
    CTBox nodes[MAX_TREE_SIZE];
    int r,n;
} CTree;

/*
這樣的結構對於我們要查找某個結點的某個孩子,或者找某個結點的兄弟,只需要查找這個節點的孩子單鏈表即可
但是,這也存在着問題,我如何知道某個結點的雙親是誰呢?比較麻煩,需要整棵樹遍歷才行 ,難道就不可以把雙親
表示法和孩子表示法綜合一下嗎?
當然可以了 看原書 圖6-4-5(雙親孩子表示法)
*/

/*
6.4.3 孩子兄弟表示法
    剛才我們分別從雙親的角度和孩子的角度研究樹的存儲結構,如果我們從樹結點的兄弟的角度考慮又會如何呢?
當然,對於樹這樣的層級結構來說,只研究結點的兄弟是不行的,我們觀察后發現,任意一棵樹,他的結點的第一個
孩子如果存在就是唯一的,它的右兄弟如果存在也是唯一的。因此我們設置兩個指針,分別指向該結點的第一個孩子和
此結點的右兄弟。
*/
//結構定義代碼如下
//樹的孩子兄弟表示法結構定義
typedef struct CSNode
{
    TElemType data;
    struct CSNode *firstchild,*rightsib;
} CSNode, *CSTree;

/*
這種表示法,給查找某個結點的某個孩子帶來了方便,只需要通過firstchild找到此結點的長子,然后通過長子結點
的rightsib找到它的二弟,接着一直下去,直到找到具體的孩子。當然,如果想找某個結點的雙親,這個表示法
也是有缺陷的,那怎么辦呢?
呵呵,如果真的有必要,完全再增加一個parent指針域來解決快速查找雙親的問題,這里就不細談了。

其實這個表示法的最大好處是它把一顆復雜的樹變成了一顆二叉樹。
*/

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM