1. 程式人生 > 實用技巧 >資料結構C語言實現----樹

資料結構C語言實現----樹

樹的基本知識點

  樹的定義

  樹的ADT(抽象資料型別)

  樹的儲存結構

  二叉樹的定義

  二叉樹的儲存結構

  遍歷二叉樹

  二叉樹的建立

二叉樹的ADT

  

typedef struct BiTNode
{
    ElemType date;        //結點的資料域
    struct BiTNode *lchild , *rchild;        //指向左孩子,右孩子
} BiTNode ,  *BiTree;

  其中 BiTNode T 等價於 BiTNode *T

二叉樹的遍歷

  有三種遍歷方式:(V是訪問visist , L是左邊left ,R是右邊right)(先訪問根節點就叫先序,中間訪問根節點就叫中序)

    VLR(先序):先訪問根結點,再先序遍歷左子樹,再先序遍歷右子樹(後面有舉例)

    LVR(中序):先中序遍歷左子樹,再訪問根節點,再中序遍歷右子樹

    LRV(後序):先後序遍歷左子樹,再後序遍歷右子樹,再訪問根節點

遍歷例項舉例:

  每進去一個新節點都要操作三個步驟:V或L或R  

  (1)先序遍歷

  

void PreOrdeTraverse(BiTree T)
{
    if (T)
    {//遞迴結束條件,T*為空
        visit(T->date);    //訪問根節點
        PreOrdeTraverse(T->lchild);    //先序遍歷左子樹
        PreOrdeTraverse(T->rchild);    //先序遍歷右子樹
    }
}

  

  (2)中序遍歷

  中序遍歷的方法與先序遍歷一樣,只不過順序有改變,每當來到一個新節點,先看有沒有左子樹,有左子樹,就進去左子樹,沒有就訪問當前結點,之後再去找右子樹,沒有左右子樹或左右子樹結點都訪問了,就回到上一個結點

  

void InOrdeTraverse(BiTree T)
{
    if (T)
    {
        InOrdeTraverse(T->lchild);
        visit(T->date);
        InOrdeTraverse(T->rchild);
    }
}

  (3)後序遍歷

  

void PosOrdeTraverse(BiTree T)
{
    if (T)
    {
        PosOrdeTraverse(T->lchild);
        PosOrdeTraverse(T->rchild);
        visit(T->date);
    }
}

  

二叉樹的建立

  

//先序序列建立一顆二叉樹
void CreatBiTree(BiTree *T)
{
    char c;
    scanf("%c" , &c);
    if (c == '#')  *T = NULL;
    else
    {
        *T = (BiTNode*)malloc(sizeof(BiTNode));     //給結點申請一個空間
        (*T)->date = c;
        CreatBiTree(&((*T)->lchild));       //建立左子樹
        CreatBiTree(&((*T)->rchild));       //建立右子樹
    }
}

  

  這裡說明一下,為什麼要傳入樹的指標的指標

  假如我們要用一個函式去改變一個整型變數 n 的值 ,我們知道必須傳入這個變數n的指標進去這個函式,要不然函式中n的變化影響不了函式外的n值

  這裡也是一樣,我們要改變左右子樹的地址,讓他們指向一個新的空間,所以要傳入左右子樹地址的地址,才能在函式裡改變他們的地址

  

  例項:以先序序列輸入一棵樹,並用三種遍歷方式打印出這棵樹,並且找到某個字母所在的層數

     我們下面這棵樹為例(沒有子樹記作#)(找到大寫字母D的所在層數)

     

#include<stdio.h>
#include<stdlib.h>

typedef struct BiTNode
{
    char date;         //結點的資料域
    struct BiTNode *lchild , *rchild;       //指向左孩子和右孩子
}BiTNode , *BiTree ;
//先序序列建立一顆二叉樹
void CreatBiTree(BiTree *T)
{
    char c;
    scanf("%c" , &c);
    if (c == '#')  *T = NULL;
    else
    {
        *T = (BiTNode*)malloc(sizeof(BiTNode));     //給結點申請一個空間
        (*T)->date = c;
        CreatBiTree(&((*T)->lchild));       //建立左子樹
        CreatBiTree(&((*T)->rchild));       //建立右子樹
    }
}
//訪問二叉樹結點操作
void visit(char c)
{
    printf("%c",c);
}
//先序遍歷二叉樹
void PreOrdeTraverse(BiTree T)
{
    if (T)
    {
        visit(T->date);
        PreOrdeTraverse(T->lchild);
        PreOrdeTraverse(T->rchild);
    }
    
}
//中序遍歷二叉樹
void InOrdeTraverse(BiTree T)
{
    if (T)
    {
        InOrdeTraverse(T->lchild);
        visit(T->date);
        InOrdeTraverse(T->rchild);
    }
}
//後序遍歷二叉樹
void PosOrdeTraverse(BiTree T)
{
    if (T)
    {
        PosOrdeTraverse(T->lchild);
        PosOrdeTraverse(T->rchild);
        visit(T->date);
    }
}
//查詢字母D在第幾層
void serch(BiTree T , int leavel)
{
    if (T){
        if (T->date == 'D')
        {
            printf("D在第%d層!",leavel);
        }
        serch(T->lchild , leavel+1);
        serch(T->rchild , leavel+1);
    }
}
int main()
{
    BiTree T;
    int leavel = 1;
    printf("請輸入先序建立的二叉樹,以#結束:");
    CreatBiTree(&T);
    printf("正在先序列印二叉樹:");
    PreOrdeTraverse(T);
    putchar('\n');
    printf("正在中序列印二叉樹:");
    InOrdeTraverse(T);
    putchar('\n');
    printf("正在後序列印二叉樹:");
    PosOrdeTraverse(T);
    putchar('\n');
    serch(T , leavel);
}

  

執行結果: