樹的基本知識點
樹的定義
樹的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);
}
運行結果:

