數據結構6——樹

非線性結構——樹定義

  • 專業定義:
    • 有且只有一個稱爲根的節點。
    • 有若干個互不相交的子樹,這些子樹本身也是一棵樹。
  • 通俗地講:
    • 樹是由節點和邊組成。
    • 每個節點只有一個父節點,但可以有多個子節點。
    • 但有一個節點例外,該節點沒有父節點,此節點稱爲根節點。
  • 專業術語:
    • 節點
    • 父節點
    • 子節點
    • 子孫
    • 堂兄弟
    • 深度:從根節點到最底層節點之間的層數稱之爲深度。
    • 葉子結點:沒有子節點的節點。
    • 非終端節點:實際就是非葉子節點。
    • 度:子節點擁有最多葉子節點的個數。

樹分類

  • 一般樹(可以有序)
    • 任意一個節點的子節點的個數都不受限制。
  • 二叉樹(有序)
    • 任意一個節點的子節點的個數最對是兩個,且子節點的位置不可更改。
    • 二叉樹分類:
      • 一般二叉樹
      • 滿二叉樹:在不增加層數的情況下,無法再增加節點。
      • 完全二叉樹:如果只是刪除了滿二叉樹最底層最右邊的連續若干個節點,這樣形成的二叉樹就是完全二叉樹。
      • 完全二叉樹包含滿二叉樹(滿二叉樹是完全二叉樹的特例)。
  • 森林
    • n個互不相交的樹的集合。

樹的存儲

  • 二叉樹的存儲
    • 連續存儲(完全二叉樹)
      • 優點:查找某個節點的父節點和子節點(也包括判斷有沒有子節點)速度很快
      • 缺點:耗用內存空間過大
    • 鏈式存儲
  • 一般樹的存儲
    • 雙親表示法(求父節點方便)
      在這裏插入圖片描述
    • 孩子表示法(求子節點方便)
      在這裏插入圖片描述
    • 雙親孩子表示法(求父節點子節點都很方便)
      在這裏插入圖片描述
    • 二叉樹表示法
      • 把一個普通數轉換成二叉樹來存儲。
      • 設法保證任意一個節點的左指針域指向它的第一個孩子,右指針域指向它的兄弟節點。
      • 一個普通樹轉化成的二叉樹一定沒有右子樹。
        在這裏插入圖片描述
  • 森林的存儲
    • 同樣是轉化成二叉樹來存。
      在這裏插入圖片描述

樹的操作(二叉樹)

  • 先序遍歷
    • 先訪問根節點,再先序訪問左子樹,再先序訪問右子樹。
      在這裏插入圖片描述在這裏插入圖片描述
  • 中序遍歷
    • 中序遍歷左子樹,再訪問根節點,再中序遍歷右子樹。
      在這裏插入圖片描述在這裏插入圖片描述
  • 後序遍歷
    • 中序遍歷左子樹,中序遍歷右子樹,最後訪問根節點。
      在這裏插入圖片描述在這裏插入圖片描述
  • 已知兩種遍歷序列求二叉樹
    • 通過先序和中序或者中序和後序,我們可以還原出元素二叉樹(確定唯一二叉樹)。
    • 但是通過先序和後序是無法還原原始二叉樹的。
    • 已知先序和中序,求後序
      在這裏插入圖片描述在這裏插入圖片描述
    • 已知中序和後序,求先序
      在這裏插入圖片描述

樹的應用

  • 樹是數據庫數據組織的一種重要形式
  • 操作系統子父進程的關係就是一棵樹
  • 面嚮對象語言中類的繼承關係本身就是一棵樹
  • 赫夫曼樹

鏈式二叉樹遍歷具體程序

在這裏插入圖片描述

//  此程序創建一個靜態鏈式二叉樹,並前中後序遍歷
#include<stdio.h>
#include<malloc.h>

struct BTNode{
    char data;
    struct BTNode * pLchild;// p是指針,L是左
    struct BTNode * pRchild;
}
struct BTNode * CreateBTree(void);	
void PreTraverseBTree(struct BTNode * pT);
void PostTraverseBTree(struct BTNode * pT);
void InTraverseBTree(struct BTNode * pT);

int main(void){
    struct BTNode * pT = CreateBTree();
    PreTraverseBTree(pT); // 先序
    InTraverseBTree(pT); // 中序
    PostTraverseBTree(pT); // 後序
    
    
    return 0;
}
void PreTraverseBTree(struct BTNode * pT){
    if(pT != NULL){ // 條件判斷要加
        printf("%c\n",pT->data);
        if(NULL != pT){ // 優化
        	PreTraverseBTree(pT->pLchild);
        }
        if(NULL != pT){ // 優化
    	PreTraverseBTree(pT->pRchild);
        }
    }
}
void PostTraverseBTree(struct BTNode * pT){
    if(pT != NULL){ // 條件判斷要加
        if(NULL != pT){ // 優化
        	PreTraverseBTree(pT->pLchild);
        }
        if(NULL != pT){ // 優化
    	PreTraverseBTree(pT->pRchild);
        }
        printf("%c\n",pT->data);
    }
}
void InTraverseBTree(struct BTNode * pT){
    if(pT != NULL){ // 條件判斷要加
        if(NULL != pT){ // 優化
        	PreTraverseBTree(pT->pLchild);
        }
        printf("%c\n",pT->data);
        if(NULL != pT){ // 優化
    	PreTraverseBTree(pT->pRchild);
        }
    }
}
struct BTNode * CreateBTree(void){
    struct BTNode * pA = (struct BTNode *)malloc(sizeof(struct BTNode));
    struct BTNode * pB = (struct BTNode *)malloc(sizeof(struct BTNode));
    struct BTNode * pC = (struct BTNode *)malloc(sizeof(struct BTNode));
    struct BTNode * pD = (struct BTNode *)malloc(sizeof(struct BTNode));
    struct BTNode * pE = (struct BTNode *)malloc(sizeof(struct BTNode));
    pA->data = 'A';
    pB->data = 'B';
    pC->data = 'C';
    pD->data = 'D';
    pE->data = 'E';
    
    pA->pLchild = pB;
    pA->pRchild = pC;
    pB->pLchild = pB->pRchild = NULL;
    pC->pLchild = pD;
    pC->pRchild = NULL;
    pD->pLchild = NULL;
    pD->pRchild = pE;
    pE->pLchild = pE->pRchild = NULL;
    
    return pA;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章