1. 程式人生 > >樹的定義和樹的三種儲存結構

樹的定義和樹的三種儲存結構

秩也就是他的高度;

一、樹的定義

1.樹的定義

樹(Tree)是n(n>=0)個結點的有限集。n=0時稱為空樹。在任意一顆非空樹中:

  1. 有且僅有一個特定的稱為根(root)的結點
  2. 當n>1時,其餘結點可分為m(m>0)個互補互動的有限集T1、T2...Tm,其中每一個集合本身又是一棵樹,並稱為根的子樹(SubTree)

    Tree

2.樹的特點

  • n>0時,根節點是唯一的,不可能存在多個根節點。資料結構中的樹只有一個根節點。
  • m>0時,子樹的個數沒有限制,但他們一定是互不相交的

3.結點的分類

  • 結點:樹的結點包含一個數據元素和若干指向其子樹的分支
  • 結點的度(Degree):結點擁有的子樹。
  • 葉子結點(Leaf)/終端結點:度為0的結點。
  • 分支結點/非終端結點:度不為0的結點。
  • 內部結點:除根節點以外,分支結點也稱為內部結點。
  • 樹的度:樹內各結點的度的最大值

    結點的分類

4.結點之間的關係

  • 孩子(Child)和雙親(Parent):結點的子樹的根,相應的,該結點稱為孩子的雙親。(注意是雙親,不是單親)
  • 兄弟(sibling):同一個雙親的孩子之間互稱兄弟。
  • 結點的祖先:從根結點到該結點所經過分支上的所有結點
  • 子孫:以某結點為根的子樹中的任一結點都稱為該節點的子孫。
  • 無序樹和有序樹:如果將樹中結點的各子樹看成從左至右
    是有次序的,不能互換的,則稱該數為有序樹,否則為無序樹。
  • 森林(fores):m(m>=0)棵互不相較的樹的集合。

二、樹的儲存結構

對於儲存結構,可能會聯想到前面的順序儲存和鏈式儲存結構。但是對於數這種可能會有很多孩子的特殊資料結構,只用順序儲存結構或者鏈式儲存結構很那實現,那麼可以將這兩者結合,產生主要的三種儲存結構表示法:雙親表示法、孩子表示法、孩子兄弟表示法。

1.雙親表示法

雙親表示法定義

假設以一組連續空間儲存數的結點,同時在每個結點中,附設一個指示器指示其雙親結點到連結串列中的位置

雙親表示的結點結構

data(資料域) parent(指標域)
儲存結點的資料資訊 儲存該結點的雙親所在陣列中的下標

程式碼實現雙親表示法

/* 樹的雙親表法結點結構定義*/
#define MAX_TREE_SIZE 100
typedef int  ElemeType;

typedef struct PTNode{ // 結點結構
    ElemeType data; //結點資料
    int parent;    // 雙親位置
}PTNode;

typedef struct { // 樹結構
    PTNode nodes[MAX_TREE_SIZE];   // 結點陣列
    int r; // 根的位置
    int n; // 結點數
}PTree;

雙親表示法的特點

  • 由於根結點是沒有雙親的,約定根結點的位置位置域為-1.
  • 根據結點的parent指標很容易找到它的雙親結點。所用時間複雜度為O(1),直到parent為-1時,表示找到了樹結點的根。
  • 缺點:如果要找到孩子結點,需要遍歷整個結構才行

2.孩子表示法

孩子表示法定義

把每個結點的孩子結點排列起來,以單鏈表作為儲存結構,則n個結點有n個孩子連結串列,如果是葉子結點則此單鏈表為空。然後n個頭指標又組成一個線性表,採用順序儲存結構,存放進一個一維陣列中。

孩子表示法

 

孩子表示法的結點結構

孩子表示法有兩種結點結構:孩子連結串列的孩子結點表頭陣列的表頭結點

  • 孩子連結串列的孩子結點
child(資料域) next(指標域)
儲存某個結點在表頭陣列中的下標 儲存指向某結點的下一個孩子結點的指標
  • 表頭陣列的表頭結點
data(資料域) firstchild(頭指標域)
儲存某個結點的資料資訊 儲存該結點的孩子連結串列的頭指標

程式碼實現孩子表示法

/* 樹的孩子表示法結構定義*/
#define MAX_TREE_SIZE 100
typedef int  ElemeType;

typedef struct CTNode{  // 孩子結點
    int child; // 孩子結點的下標
    struct CTNode * next; // 指向下一結點的指標
}*ChildPtr;

typedef struct {  // 表頭結構
    ElemeType data; // 存放在數中的結點資料
    ChildPtr firstchild; // 指向第一個孩子的指標
}CTBox;

typedef struct {  // 樹結構
    CTBox nodes[MAX_TREE_SIZE]; // 結點陣列
    int r;  // 根的位置
    int n;  // 結點樹
}CTree;

雙親孩子表示法定義

對於孩子表示法,查詢某個結點的某個孩子,或者找某個結點的兄弟,只需要查詢這個結點的孩子單鏈表即可。但是當要尋找某個結點的雙親時,就不是那麼方便了。所以可以將雙親表示法和孩子表示法結合,形成雙親孩子表示法


show code

 

/* 樹的雙親孩子表示法結構定義*/
#define MAX_TREE_SIZE 100
typedef int  ElemeType;

typedef struct CTNode{  // 孩子結點
    int child;  // 孩子結點的下標
    struct CTNode * next;  // 指向下一結點的指標
}*ChildPtr;

typedef struct {  // 表頭結構
    ElemeType data;  // 存放在數中的結點資料
    int parent;      // 存放雙親的下標
    ChildPtr firstchild;  // 指向第一個孩子的指標
}CTBox;

typedef struct {  // 樹結構
    CTBox nodes[MAX_TREE_SIZE]; // 結點陣列
    int r;  // 根的位置
    int n;  // 結點樹
}CTree;

3.孩子兄弟表示法

孩子兄弟表示法定義

任意一棵樹,它的結點的第一個孩子如果存在就是唯一的,它的右兄弟存在也是唯一的。因此,設定兩個指標,分別指向該結點的第一個孩子和此結點的右兄弟。

孩子兄弟表示法的結點結構

data(資料域) firstchild(指標域) rightsib(指標域)
儲存結點的資料資訊 儲存該結點的第一個孩子的儲存地址 儲存該結點的右兄弟結點的儲存地址

程式碼實現孩子兄弟表示法

/* 樹的孩子兄弟表示法結構定義*/
#define MAX_TREE_SIZE 100
typedef int  ElemeType;

typedef struct CSNode{
    ElemeType data;
    struct CSNode * firstchild;
    struct CSNode * rightsib;
    
}CSNode, *CSTree;