資料結構C語言實現----樹
阿新 • • 發佈:2020-07-27
樹的基本知識點
樹的定義
樹的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); }
執行結果: