數據結構04-樹

數據結構04-樹

4:樹(QUEUE)

樹.png

4.1:樹的定義和性質

  1. 樹是一種重要的非線性數據結構;
  2. 樹是由一個或多個結點組成的有限集合;

樹必有一個特定的稱為根(ROOT)的結點;

剩下的結點被分成n>=0個互不相交的集合T1、T2、......Tn,而且, 這些集合的每一個又都是樹。樹T1、T2、......Tn被稱作根的子樹(Subtree)。

樹的遞歸定義如下:
1. 至少有一個結點(稱為根)
2. 其它是互不相交的子樹。

樹的度:結點的最大分支數。以組成該樹各結點中最大的度作為該樹的度;

樹中度為零的結點稱為葉結點或終端結點。樹中度不為零的結點稱為分枝結點或非終端結點。除根結點外的分枝結點統稱為內部結點。

樹的深度:組成該樹各結點的最大層次,從1開始計數;

有序樹:指樹中同層結點從左到右有次序排列,它們之間的次序不能互換,這樣的樹稱為有序樹,否則稱為無序樹。

二叉樹:每個節點至多只有兩棵子樹,度不能大于2,并且二叉樹的子樹有左右之分,左右次序不能改變。


image.png

二叉樹五種基本形態(如上圖 依次分別為):

  1. 空二叉樹
  2. 只有一個根節點的二叉樹
  3. 只有左子樹
  4. 只有右子樹
  5. 完全二叉樹

image.png
  1. 滿二叉樹:一顆深度為K且有2^(k-1)個結點的二叉樹.
  2. 完全二叉樹:對二叉樹的結點進行連續編號,約定編號從根節點起,自上而下,自左至右。深度為k,有n個結點的二叉樹,當且僅當其每一個結點都與深度k的滿二叉樹中編號從1到n的結點一一對應

二叉樹的第i層上至多有2^i-1個結點(i>=1)

深度為k的二叉樹至多有2^k-1個結點(k>=1)

具有n個結點的完全二叉樹的深度為:
image

4.1:樹的創建

//二叉樹存儲結構
typedef struct _treeNode {
    int value;
    struct _treeNode *left;
    struct _treeNode *right;
} tree, *pTree;

//二叉樹的創建,遞歸創建
tree *creat_tree() {
    int value = 0;
    scanf("%d", &value);
    
    if (value == 0)//輸入零,表示左或右子樹為空
        return NULL;
    
    tree *node = (tree *)malloc(sizeof(tree));
    
    if (node == NULL) 
        return NULL;
        
    memset(node, 0, sizeof(tree));
    node->value = value;
     
    //遞歸創建左右子樹
    printf("Please create the left tree of %d\n",value);
    node->left = create_tree();
    printf("Please create the right tree of %d\n",value);
    node->right = create_tree();
    
    return node;
}

4.2:樹的遍歷

遍歷:對樹的一種最基本的運算(二叉樹是非線性結構,但在遍歷時是按一定規則和順序走遍二叉樹的所有結點,使每一個結點都被訪問一次,而且只被訪問一次)。

樹的遍歷實質上是將二叉樹的各個結點轉換成為一個線性序列來表示。

  1. L:遍歷左子樹
  2. D:訪問根結點
  3. R:遍歷右子樹

對一棵二叉樹遍歷分三種情況(下面先序,中序和后序都是以根為標準):

  1. DLR(稱為先根次序遍歷,即先序遍歷)
  2. LDR(稱為中根次序遍歷,即中序遍歷)
  3. LRD(稱為后根次序遍歷,即后序遍歷)

4.2.1:樹的先序遍歷

image.png

先序遍歷的方法:訪問根;按先序遍歷左子樹;按先序遍歷右子樹。

//先序遍歷的遞歸算法
void preorder(tree *node) {
    if(node == NULL)
        return;

    printf(“%d”, node->data);//7,3,1,4,6,8,5,2

    preorder(node->left);
    preorder(node->right);
}

4.2.2:樹的中序遍歷

image.png

中序遍歷的方法:按中序遍歷左子樹;訪問根;按中序遍歷右子樹。

//中序遍歷
void inorder(tree *node) {
    if(node == NULL)
        return;

    inorder(node->left);
    printf(“%d”, node->data);//1,3,6,4,7,5,8,2
    inorder(node->right);
}

4.2.3:樹的后序遍歷

image.png

后序遍歷的方法:按后序遍歷左子樹;按后序遍歷右子樹;訪問根。

void postorder(tree *node) {
    if(node == NULL)
        return;

     postorder(t->left);
     postorder(t->right);
     printf(“%d”, t->data);//1,6,4,3,5,2,8,7
}

4.3:樹的銷毀

vode pre_destroy(tree *node) {
    if (node == NULL) 
        return NULL;
        
    tree *left = node->left;
    tree *right = node->right;
    free(node);
    
    pre_destroy(left);
    pre_destroy(right);
}

4.4:平衡二叉樹(AVL)/紅黑樹(rbtree)/B+樹/B-樹

  1. 二叉排序樹:所有非葉子結點至多擁有兩個兒子(Left和Right);所有結點存儲一個關鍵字;非葉子結點的左指針指向小于其關鍵字的子樹,右指針指向大于其關鍵字的子樹;
  2. 平衡二叉排序樹:一種改進的二叉排序樹,一棵平衡二叉排序樹或者是一棵空樹,或者是一棵任意一結點的左子樹與右子樹的高度至多差1的二叉樹排序樹。對于二叉排序樹上的任何結點,其平衡因子定義為該結點左子樹的高度減去該結點右子樹高度。任一結點的平衡因子只可能是-1,0,1。平衡的二叉排序樹的查找方法與一般的二叉排序樹完全一樣,其優點是總能保持查找長度為O(log2n)量級。往平衡的二叉排序樹插入新結點時,需要對樹的結構進行必要調整,以動態地保持平衡二叉排序樹的特點。
  3. 紅黑樹(RB Tree):是平衡二叉樹,查找的效率也就一樣,為logN。所以在C++的STL庫中,set/map,multiset/multimap就是用的紅黑樹作為底層的數據結構,方便查找與插入刪除操作。
image

紅黑樹是每個節點都帶有顏色屬性的二叉查找樹,顏色或紅色或黑色。在二叉查找樹強制一般要求以外,對于任何有效的紅黑樹增加了如下的額外要求:

性質1: 節點是紅色或黑色。

性質2: 根是黑色。

性質3: 每個紅色節點的兩個子節點都是黑色。(從每個葉子到根的所有路徑上不能有兩個連續的紅色節點)

性質4: 從任一節點到其每個葉子的所有路徑都包含相同數目的黑色節點。

這些約束強制了紅黑樹的關鍵性質: 從根到葉子的最長的可能路徑不多于最短的可能路徑的兩倍長。結果是這個樹大致上是平衡的。因為操作比如插入、刪除和查找某個值的最壞情況時間都要求與樹的高度成比例,這個在高度上的理論上限允許紅黑樹在最壞情況下都是高效的,而不同于普通的二叉查找樹。


B樹:即二叉排序(搜索)樹

  1. 所有非葉子結點至多擁有兩個兒子(Left和Right);
  2. 所有結點存儲一個關鍵字;
  3. 非葉子結點的左指針指向小于其關鍵字的子樹,右指針指向大于其關鍵字的子樹;


    image

B-樹:一種多路搜索樹(并不是二叉的)

  1. 定義任意非葉子結點最多只有M個兒子;且M>2;
  2. 根結點的兒子數為[2, M];
  3. 除根結點以外的非葉子結點的兒子數為[M/2, M];
  4. 每個結點存放至少M/2-1(取上整)和至多M-1個關鍵字;(至少2個關鍵字)
  5. 非葉子結點的關鍵字個數=指向兒子的指針個數-1;
  6. 非葉子結點的關鍵字:K[1], K[2], …, K[M-1];且K[i] < K[i+1];
  7. 非葉子結點的指針:P[1], P[2], …, P[M];其中P[1]指向關鍵字小于K[1]的子樹,P[M]指向關鍵字大于K[M-1]的子樹,其它P[i]指向關鍵字屬于(K[i-1], K[i])的子樹;
  8. 所有葉子結點位于同一層;
image

B+樹:是B-樹的變體,也是一種多路搜索樹:

  1. 其定義基本與B-樹同,除了:
  2. 非葉子結點的子樹指針與關鍵字個數相同;
  3. 非葉子結點的子樹指針P[i],指向關鍵字值屬于[K[i], K[i+1])的子樹(B-樹是開區間);
  4. 為所有葉子結點增加一個鏈指針;
  5. 所有關鍵字都在葉子結點出現
image
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • 第一章 緒論 什么是數據結構? 數據結構的定義:數據結構是相互之間存在一種或多種特定關系的數據元素的集合。 第二章...
    SeanCheney閱讀 5,807評論 0 19
  • 數據結構和算法--二叉樹的實現 幾種二叉樹 1、二叉樹 和普通的樹相比,二叉樹有如下特點: 每個結點最多只有兩棵子...
    sunhaiyu閱讀 6,511評論 0 14
  • 1.樹(Tree): 樹是 n(n>=0) 個結點的有限集。當 n=0 時稱為空樹。在任意一顆非空樹中:有且僅有一...
    ql2012jz閱讀 1,039評論 0 3
  • B樹的定義 一棵m階的B樹滿足下列條件: 樹中每個結點至多有m個孩子。 除根結點和葉子結點外,其它每個結點至少有m...
    文檔隨手記閱讀 13,322評論 0 25
  • 課程介紹 先修課:概率統計,程序設計實習,集合論與圖論 后續課:算法分析與設計,編譯原理,操作系統,數據庫概論,人...
    ShellyWhen閱讀 2,343評論 0 3