先序遍歷規(guī)則??先序遍歷的核心思想:1.訪問根節(jié)點(diǎn);2.訪問當(dāng)前節(jié)點(diǎn)的左子樹;3.若當(dāng)前節(jié)點(diǎn)無左子樹,則訪問當(dāng)前節(jié)點(diǎn)的右子樹;即考察到一個節(jié)點(diǎn)后,即刻輸出該節(jié)點(diǎn)的值,并繼續(xù)遍歷其左右子樹。(根左右) 先序遍歷舉例??如圖所示,采用先序遍歷訪問這顆二叉樹的詳細(xì)過程為: 先序遍歷代碼(遞歸)/*
* @Description:
* @Version:
* @Autor: Carlos
* @Date: 2020-05-29 16:55:41
* @LastEditors: Carlos
* @LastEditTime: 2020-05-30 17:03:23
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define TElemType int
//構(gòu)造結(jié)點(diǎn)的結(jié)構(gòu)體
typedef struct BiTNode{
TElemType data;//數(shù)據(jù)域
struct BiTNode *lchild,*rchild;//左右孩子指針
}BiTNode,*BiTree;
/**
* @Description: 初始化樹的函數(shù)
* @Param: BiTree *T 結(jié)構(gòu)體指針的指針
* @Return: 無
* @Author: Carlos
*/
void CreateBiTree(BiTree *T){
*T=(BiTree)malloc(sizeof(BiTNode));
//根節(jié)點(diǎn)
(*T)->data=1;
(*T)->lchild=(BiTree)malloc(sizeof(BiTNode));
(*T)->rchild=(BiTree)malloc(sizeof(BiTNode));
//1節(jié)點(diǎn)的左孩子2
(*T)->lchild->data=2;
(*T)->lchild->lchild=(BiTree)malloc(sizeof(BiTNode));
(*T)->lchild->rchild=(BiTree)malloc(sizeof(BiTNode));
//2節(jié)點(diǎn)的右孩子5
(*T)->lchild->rchild->data=5;
(*T)->lchild->rchild->lchild=NULL;
(*T)->lchild->rchild->rchild=NULL;
//1節(jié)點(diǎn)的右孩子3
(*T)->rchild->data=3;
(*T)->rchild->lchild=(BiTree)malloc(sizeof(BiTNode));
//3節(jié)點(diǎn)的左孩子6
(*T)->rchild->lchild->data=6;
(*T)->rchild->lchild->lchild=NULL;
(*T)->rchild->lchild->rchild=NULL;
(*T)->rchild->rchild=(BiTree)malloc(sizeof(BiTNode));
//3節(jié)點(diǎn)的右孩子7
(*T)->rchild->rchild->data=7;
(*T)->rchild->rchild->lchild=NULL;
(*T)->rchild->rchild->rchild=NULL;
//2節(jié)點(diǎn)的左孩子4
(*T)->lchild->lchild->data=4;
(*T)->lchild->lchild->lchild=NULL;
(*T)->lchild->lchild->rchild=NULL;
}
/**
* @Description: 模擬操作結(jié)點(diǎn)元素的函數(shù),輸出結(jié)點(diǎn)本身的數(shù)值
* @Param:BiTree elem 就結(jié)構(gòu)體指針
* @Return: 無
* @Author: Carlos
*/
void PrintBiT(BiTree elem){
printf("%d ",elem->data);
}
/**
* @Description: 先序遍歷
* @Param: BiTree T 結(jié)構(gòu)體指針
* @Return: 無
* @Author: Carlos
*/
void PreOrderTraverse(BiTree T){
if (T) {
PrintBiT(T);//調(diào)用操作結(jié)點(diǎn)數(shù)據(jù)的函數(shù)方法
PreOrderTraverse(T->lchild);//訪問該結(jié)點(diǎn)的左孩子
PreOrderTraverse(T->rchild);//訪問該結(jié)點(diǎn)的右孩子
}
//如果結(jié)點(diǎn)為空,返回上一層
return;
}
int main() {
BiTree Tree;
CreateBiTree(&Tree);
printf("先序遍歷: \n");
PreOrderTraverse(Tree);
}先序遍歷代碼(非遞歸)??因?yàn)橐诒闅v完某個樹的根節(jié)點(diǎn)的左子樹后接著遍歷節(jié)點(diǎn)的右子樹,為了能找到該樹的根節(jié)點(diǎn),需要使用棧來進(jìn)行暫存。中序和后序也都涉及到回溯,所以都需要用到棧。 #include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define TElemType int
//構(gòu)造結(jié)點(diǎn)的結(jié)構(gòu)體
typedef struct BiTNode{
TElemType data;//數(shù)據(jù)域
struct BiTNode *lchild,*rchild;//左右孩子指針
}BiTNode,*BiTree;
int top = -1;
//定義一個順序棧
BiTree a[20];
/**
* @Description: 初始化樹
* @Param: BiTree *T 指針的指針
* @Return: 無
* @Author: Carlos
*/
void CreateBiTree(BiTree *T){
*T=(BiTree)malloc(sizeof(BiTNode));
//根節(jié)點(diǎn)
(*T)->data=1;
(*T)->lchild=(BiTree)malloc(sizeof(BiTNode));
(*T)->rchild=(BiTree)malloc(sizeof(BiTNode));
//1節(jié)點(diǎn)的左孩子2
(*T)->lchild->data=2;
(*T)->lchild->lchild=(BiTree)malloc(sizeof(BiTNode));
(*T)->lchild->rchild=(BiTree)malloc(sizeof(BiTNode));
//2節(jié)點(diǎn)的右孩子5
(*T)->lchild->rchild->data=5;
(*T)->lchild->rchild->lchild=NULL;
(*T)->lchild->rchild->rchild=NULL;
//1節(jié)點(diǎn)的右孩子3
(*T)->rchild->data=3;
(*T)->rchild->lchild=(BiTree)malloc(sizeof(BiTNode));
//3節(jié)點(diǎn)的左孩子6
(*T)->rchild->lchild->data=6;
(*T)->rchild->lchild->lchild=NULL;
(*T)->rchild->lchild->rchild=NULL;
(*T)->rchild->rchild=(BiTree)malloc(sizeof(BiTNode));
//3節(jié)點(diǎn)的右孩子7
(*T)->rchild->rchild->data=7;
(*T)->rchild->rchild->lchild=NULL;
(*T)->rchild->rchild->rchild=NULL;
//2節(jié)點(diǎn)的左孩子4
(*T)->lchild->lchild->data=4;
(*T)->lchild->lchild->lchild=NULL;
(*T)->lchild->lchild->rchild=NULL;
}
/**
* @Description: 打印二叉樹
* @Param: BiTree elem 指針的指針
* @Return: 無
* @Author: Carlos
*/
void PrintBiT(BiTree elem){
printf("%d ",elem->data);
}
/**
* @Description: 二叉樹壓棧函數(shù)
* @Param: BiTree* a 結(jié)構(gòu)體指針的指針(也可以理解為指針數(shù)組) BiTree elem 結(jié)構(gòu)體指針
* @Return: 無
* @Author: Carlos
*/
void Push(BiTree* a,BiTree elem)
{
a[++top]=elem;
}
/**
* @Description: 二叉樹彈棧函數(shù)
* @Param: 無
* @Return: 無
* @Author: Carlos
*/
void Pop()
{
if (top==-1) {
return ;
}
top--;
}
/**
* @Description: 獲取棧頂元素
* @Param: BiTree*a 結(jié)構(gòu)體指針數(shù)組
* @Return: 結(jié)構(gòu)體指針
* @Author: Carlos
*/
BiTree GetTop(BiTree*a){
return a[top];
}
/**
* @Description: 先序遍歷
* @Param: BiTree Tree 結(jié)構(gòu)體指針
* @Return: 無
* @Author: Carlos
*/
void PreOrderTraverse(BiTree Tree)
{
//臨時指針
BiTree p;
//根結(jié)點(diǎn)進(jìn)棧
Push(a, Tree);
while (top!=-1) {
//取棧頂元素
p=GetTop(a);
//彈棧
Pop();
while (p) {
//調(diào)用結(jié)點(diǎn)的操作函數(shù)
PrintBiT(p);
//如果該結(jié)點(diǎn)有右孩子,右孩子進(jìn)棧
if (p->rchild) {
Push(a,p->rchild);
}
p=p->lchild;//一直指向根結(jié)點(diǎn)最后一個左孩子
}
}
}
int main() {
BiTree Tree;
CreateBiTree(&Tree);
printf("先序遍歷: \n");
PreOrderTraverse(Tree);
}中序遍歷中序遍歷規(guī)則??二叉樹中序遍歷的實(shí)現(xiàn)思想是:1.訪問當(dāng)前節(jié)點(diǎn)的左子樹;2.訪問根節(jié)點(diǎn);3.訪問當(dāng)前節(jié)點(diǎn)的右子樹。即考察到一個節(jié)點(diǎn)后,將其暫存,遍歷完左子樹后,再輸出該節(jié)點(diǎn)的值,然后遍歷右子樹。(左根右) 中序遍歷舉例
中序遍歷代碼(遞歸)/*
* @Description: 遞歸實(shí)現(xiàn)的中序遍歷
* @Version: V1.0
* @Autor: Carlos
* @Date: 2020-05-18 14:53:29
* @LastEditors: Carlos
* @LastEditTime: 2020-05-30 17:21:06
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define TElemType int
//構(gòu)造結(jié)點(diǎn)的結(jié)構(gòu)體
typedef struct BiTNode{
//數(shù)據(jù)域
TElemType data;
//左右孩子指針
struct BiTreelchild,*rchild;
}BiTNode,*BiTree;
/**
* @Description: 初始化樹
* @Param: BiTree *T 結(jié)構(gòu)體指針的指針(指針數(shù)組)
* @Return: 無
* @Author: Carlos
*/
void CreateBiTree(BiTree *T){
*T=(BiTree)malloc(sizeof(BiTNode));
(*T)->data=1;
(*T)->lchild=(BiTree)malloc(sizeof(BiTNode));
(*T)->rchild=(BiTree)malloc(sizeof(BiTNode));
(*T)->lchild->data=2;
(*T)->lchild->lchild=(BiTree)malloc(sizeof(BiTNode));
(*T)->lchild->rchild=(BiTree)malloc(sizeof(BiTNode));
(*T)->lchild->rchild->data=5;
(*T)->lchild->rchild->lchild=NULL;
(*T)->lchild->rchild->rchild=NULL;
(*T)->rchild->data=3;
(*T)->rchild->lchild=(BiTree)malloc(sizeof(BiTNode));
(*T)->rchild->lchild->data=6;
(*T)->rchild->lchild->lchild=NULL;
(*T)->rchild->lchild->rchild=NULL;
(*T)->rchild->rchild=(BiTree)malloc(sizeof(BiTNode));
(*T)->rchild->rchild->data=7;
(*T)->rchild->rchild->lchild=NULL;
(*T)->rchild->rchild->rchild=NULL;
(*T)->lchild->lchild->data=4;
(*T)->lchild->lchild->lchild=NULL;
(*T)->lchild->lchild->rchild=NULL;
}
/**
* @Description: 顯示函數(shù)
* @Param: BiTree elem 結(jié)構(gòu)體指針
* @Return: 無
* @Author: Carlos
*/
void PrintBiT(BiTree elem){
printf("%d ",elem->data);
}
/**
* @Description: 中序遍歷
* @Param: BiTree T 結(jié)構(gòu)體指針
* @Return: 無
* @Author: Carlos
*/
void INOrderTraverse(BiTree T){
if (T) {
INOrderTraverse(T->lchild);//遍歷左孩子
PrintBiT(T);//調(diào)用操作結(jié)點(diǎn)數(shù)據(jù)的函數(shù)方法
INOrderTraverse(T->rchild);//遍歷右孩子
}
//如果結(jié)點(diǎn)為空,返回上一層
return;
}
int main() {
BiTree Tree;
CreateBiTree(&Tree);
printf("中序遍歷算法: \n");
INOrderTraverse(Tree);
}中序遍歷代碼(非遞歸)??和非遞歸先序遍歷類似,唯一區(qū)別是考查到當(dāng)前節(jié)點(diǎn)時,并不直接輸出該節(jié)點(diǎn)。而是當(dāng)考查節(jié)點(diǎn)為空時,從棧中彈出的時候再進(jìn)行輸出(永遠(yuǎn)先考慮左子樹,直到左子樹為空才訪問根節(jié)點(diǎn))。 /*
* @Description: 二叉樹的先序遍歷(非遞歸)
* @Version: V1.0
* @Autor: Carlos
* @Date: 2020-05-17 16:35:27
* @LastEditors: Carlos
* @LastEditTime: 2020-05-18 14:51:01
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define DBG_PRINTF(fmt, args...) do{ printf("<<File:%s Line:%d Function:%s>> ", __FILE__, __LINE__, __FUNCTION__); printf(fmt, ##args);}while(0)
#define TElemType int
int top=-1;//top變量時刻表示棧頂元素所在位置
//構(gòu)造結(jié)點(diǎn)的結(jié)構(gòu)體
typedef struct BiTNode{
//數(shù)據(jù)域
TElemType data;
//左右孩子指針
struct BiTNode *lchild,*rchild;
}BiTNode,*BiTree;
/**
* @Description: 初始化樹
* @Param: BiTree *T 結(jié)構(gòu)體指針的指針
* @Return: 無
* @Author: Carlos
*/
void CreateBiTree(BiTree *T){
*T=(BiTree)malloc(sizeof(BiTNode));
(*T)->data=1;
(*T)->lchild=(BiTree)malloc(sizeof(BiTNode));
(*T)->rchild=(BiTree)malloc(sizeof(BiTNode));
(*T)->lchild->data=2;
(*T)->lchild->lchild=(BiTree)malloc(sizeof(BiTNode));
(*T)->lchild->rchild=(BiTree)malloc(sizeof(BiTNode));
(*T)->lchild->rchild->data=5;
(*T)->lchild->rchild->lchild=NULL;
(*T)->lchild->rchild->rchild=NULL;
(*T)->rchild->data=3;
(*T)->rchild->lchild=(BiTree)malloc(sizeof(BiTNode));
(*T)->rchild->lchild->data=6;
(*T)->rchild->lchild->lchild=NULL;
(*T)->rchild->lchild->rchild=NULL;
(*T)->rchild->rchild=(BiTree)malloc(sizeof(BiTNode));
(*T)->rchild->rchild->data=7;
(*T)->rchild->rchild->lchild=NULL;
(*T)->rchild->rchild->rchild=NULL;
(*T)->lchild->lchild->data=4;
(*T)->lchild->lchild->lchild=NULL;
(*T)->lchild->lchild->rchild=NULL;
}
/**
* @Description: 中序遍歷使用的進(jìn)棧函數(shù)
* @Param: BiTree* a 指向樹的指針數(shù)組 BiTree elem 進(jìn)棧的元素
* @Return: 無
* @Author: Carlos
*/
void Push(BiTree* a,BiTree elem){
//指針進(jìn)棧
a[++top]=elem;
}
/**
* @Description: 前序遍歷使用的彈棧函數(shù)
* @Param: 無
* @Return: 無
* @Author: Carlos
*/
void Pop( ){
if (top==-1) {
return;
}
top--;
}
/**
* @Description: 顯示函數(shù)
* @Param: BiTree elem 指向樹的指針
* @Return: 無
* @Author: Carlos
*/
void PrintBiT(BiTree elem){
printf("%d ",elem->data);
}
/**
* @Description: 拿到棧頂元素
* @Param: BiTree*a 指針數(shù)組
* @Return: 棧頂元素的地址
* @Author: Carlos
*/
BiTree GetTop(BiTree*a){
return a[top];
}
/**
* @Description: 中序遍歷非遞歸算法,先左,然后回退,然后右。從根結(jié)點(diǎn)開始,遍歷左孩子同時壓棧,當(dāng)遍歷結(jié)束,說明當(dāng)前遍歷的結(jié)點(diǎn)沒有左孩子,
* 從棧中取出來調(diào)用操作函數(shù),然后訪問該結(jié)點(diǎn)的右孩子,繼續(xù)以上重復(fù)性的操作
* @Return: 棧頂元素的地址
* @Author: Carlos
*/
void InOrderTraverse1(BiTree Tree){
//定義一個順序棧
BiTree a[20];
//臨時指針
BiTree p;
//根結(jié)點(diǎn)進(jìn)棧
Push(a, Tree);
//top!=-1說明棧內(nèi)不為空,程序繼續(xù)運(yùn)行
while (top!=-1) {
//一直取棧頂元素,且不能為NULL
while ((p=GetTop(a)) &&p){
//將該結(jié)點(diǎn)的左孩子進(jìn)棧,如果沒有左孩子,NULL進(jìn)棧
Push(a, p->lchild);
}
//跳出循環(huán),棧頂元素肯定為NULL,將NULL彈棧。 打印的第一個元素沒有右孩子,所以也會Pop掉,再取棧頂元素就是第一個元素的父節(jié)點(diǎn)
Pop();
if (top!=-1) {
//取棧頂元素
p=GetTop(a);
//棧頂元素彈棧
Pop();
//遍歷完所有左孩子之后,打印棧頂?shù)脑亍? PrintBiT(p);
//將p指向的結(jié)點(diǎn)的右孩子進(jìn)棧
Push(a, p->rchild);
}
}
}
/**
* @Description: 中序遍歷非遞歸算法。中序遍歷過程中,只需將每個結(jié)點(diǎn)的左子樹壓棧即可,右子樹不需要壓棧。
* 當(dāng)結(jié)點(diǎn)的左子樹遍歷完成后,只需要以棧頂結(jié)點(diǎn)的右孩子為根結(jié)點(diǎn),繼續(xù)循環(huán)遍歷即可
* @Param: 無
* @Return: 棧頂元素的地址
* @Author: Carlos
*/
void InOrderTraverse2(BiTree Tree){
//定義一個順序棧
BiTree a[20];
//臨時指針
BiTree p;
p=Tree;
//當(dāng)p為NULL或者棧為空時,表明樹遍歷完成
while (p || top!=-1) {
//如果p不為NULL,將其壓棧并遍歷其左子樹
if (p) {
Push(a, p);
p=p->lchild;
}
//如果p==NULL,表明左子樹遍歷完成,需要遍歷上一層結(jié)點(diǎn)的右子樹 彈出時順便訪問右子樹
else{
p=GetTop(a);
Pop();
PrintBiT(p);
p=p->rchild;
}
}
}
int main(){
BiTree Tree;
CreateBiTree(&Tree);
printf("中序遍歷: \r\n");
InOrderTraverse2(Tree);
DBG_PRINTF("123456\r\n");
return 0;
}后序遍歷后序遍歷規(guī)則??二叉樹后序遍歷的實(shí)現(xiàn)思想是:1.訪問左子樹;2.訪問右子樹;3.完成該節(jié)點(diǎn)的左右子樹的訪問后,再訪問該節(jié)點(diǎn)。即考察到一個節(jié)點(diǎn)后,將其暫存,遍歷完左右子樹后,再輸出該節(jié)點(diǎn)的值。(左右根) 后序遍歷舉例
后序遍歷代碼(遞歸)/*
* @Description: 二叉樹的后序遍歷(遞歸)
* @Version: V1.0
* @Autor: Carlos
* @Date: 2020-05-18 16:23:57
* @LastEditors: Carlos
* @LastEditTime: 2020-05-30 17:29:38
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define TElemType int
//構(gòu)造結(jié)點(diǎn)的結(jié)構(gòu)體
typedef struct BiTNode{
//數(shù)據(jù)域
TElemType data;
//左右孩子指針
struct BiTNode *lchild,*rchild;
}BiTNode,*BiTree;
/**
* @Description: 初始化樹
* @Param: BiTree *T 結(jié)構(gòu)體指針
* @Return: 無
* @Author: Carlos
*/
void CreateBiTree(BiTree *T){
*T=(BiTree)malloc(sizeof(BiTNode));
(*T)->data=1;
(*T)->lchild=(BiTree)malloc(sizeof(BiTNode));
(*T)->rchild=(BiTree)malloc(sizeof(BiTNode));
(*T)->lchild->data=2;
(*T)->lchild->lchild=(BiTree)malloc(sizeof(BiTNode));
(*T)->lchild->rchild=(BiTree)malloc(sizeof(BiTNode));
(*T)->lchild->rchild->data=5;
(*T)->lchild->rchild->lchild=NULL;
(*T)->lchild->rchild->rchild=NULL;
(*T)->rchild->data=3;
(*T)->rchild->lchild=(BiTree)malloc(sizeof(BiTNode));
(*T)->rchild->lchild->data=6;
(*T)->rchild->lchild->lchild=NULL;
(*T)->rchild->lchild->rchild=NULL;
(*T)->rchild->rchild=(BiTree)malloc(sizeof(BiTNode));
(*T)->rchild->rchild->data=7;
(*T)->rchild->rchild->lchild=NULL;
(*T)->rchild->rchild->rchild=NULL;
(*T)->lchild->lchild->data=4;
(*T)->lchild->lchild->lchild=NULL;
(*T)->lchild->lchild->rchild=NULL;
}
/**
* @Description: 顯示函數(shù)
* @Param: BiTree elem 指向樹的結(jié)構(gòu)體指針
* @Return: 無
* @Author: Carlos
*/
void PrintBiT(BiTree elem){
printf("%d ",elem->data);
}
/**
* @Description: 先序遍歷
* @Param: BiTree T 指針數(shù)組,存放各個節(jié)點(diǎn)的指針
* @Return: 無
* @Author: Carlos
*/
void PreOrderTraverse(BiTree T){
if (T) {
PreOrderTraverse(T->lchild);//訪問該結(jié)點(diǎn)的左孩子
PreOrderTraverse(T->rchild);//訪問該結(jié)點(diǎn)的右孩子
PrintBiT(T);//調(diào)用操作結(jié)點(diǎn)數(shù)據(jù)的函數(shù)方法
}
//如果結(jié)點(diǎn)為空,返回上一層
return;
}
int main() {
BiTree Tree;
CreateBiTree(&Tree);
printf("后序遍歷: \n");
PreOrderTraverse(Tree);
}后序遍歷代碼(非遞歸)/*
* @Description: 二叉樹的后序遍歷(非遞歸)
* @Version: V1.0
* @Autor: Carlos
* @Date: 2020-05-18 16:23:57
* @LastEditors: Carlos
* @LastEditTime: 2020-05-18 16:24:29
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define TElemType int
//top變量時刻表示棧頂元素所在位置
int top=-1;
//構(gòu)造結(jié)點(diǎn)的結(jié)構(gòu)體
typedef struct BiTNode{
//數(shù)據(jù)域
TElemType data;
//左右孩子指針
struct BiTNode *lchild,*rchild;
}BiTNode,*BiTree;
/**
* @Description: 初始化樹
* @Param: BiTree *T 結(jié)構(gòu)體指針數(shù)組
* @Return: 無
* @Author: Carlos
*/
void CreateBiTree(BiTree *T){
*T=(BiTNode*)malloc(sizeof(BiTNode));
(*T)->data=1;
(*T)->lchild=(BiTNode*)malloc(sizeof(BiTNode));
(*T)->rchild=(BiTNode*)malloc(sizeof(BiTNode));
(*T)->lchild->data=2;
(*T)->lchild->lchild=(BiTNode*)malloc(sizeof(BiTNode));
(*T)->lchild->rchild=(BiTNode*)malloc(sizeof(BiTNode));
(*T)->lchild->rchild->data=5;
(*T)->lchild->rchild->lchild=NULL;
(*T)->lchild->rchild->rchild=NULL;
(*T)->rchild->data=3;
(*T)->rchild->lchild=(BiTNode*)malloc(sizeof(BiTNode));
(*T)->rchild->lchild->data=6;
(*T)->rchild->lchild->lchild=NULL;
(*T)->rchild->lchild->rchild=NULL;
(*T)->rchild->rchild=(BiTNode*)malloc(sizeof(BiTNode));
(*T)->rchild->rchild->data=7;
(*T)->rchild->rchild->lchild=NULL;
(*T)->rchild->rchild->rchild=NULL;
(*T)->lchild->lchild->data=4;
(*T)->lchild->lchild->lchild=NULL;
(*T)->lchild->lchild->rchild=NULL;
}
/**
* @Description: 后序遍歷使用的彈棧函數(shù)
* @Param: 無
* @Return: 無
* @Author: Carlos
*/
void Pop( ){
if (top==-1) {
return ;
}
top--;
}
/**
* @Description: 顯示函數(shù)
* @Param: 無
* @Return: 無
* @Author: Carlos
*/
void PrintBiT(BiTree elem){
printf("%d ",elem->data);
}
//增加左右子樹的訪問標(biāo)志
typedef struct SNode{
BiTree p;
int tag;
}SNode;
/**
* @Description: 后序遍歷使用的進(jìn)棧函數(shù)
* @Param: SNode *a 指向樹和標(biāo)志位的結(jié)構(gòu)體的指針 BiTree sdata 進(jìn)棧的元素
* @Return: 無
* @Author: Carlos
*/
void Push(SNode *a,SNode sdata){
a[++top]=sdata;
}
/**
* @Description: 后序遍歷非遞歸算法。后序遍歷是在遍歷完當(dāng)前結(jié)點(diǎn)的左右孩子之后,才調(diào)用操作函數(shù),所以需要在操作結(jié)點(diǎn)進(jìn)棧時,為每個結(jié)點(diǎn)配備一個標(biāo)志位。
* 當(dāng)遍歷該結(jié)點(diǎn)的左孩子時,設(shè)置當(dāng)前結(jié)點(diǎn)的標(biāo)志位為 0,進(jìn)棧;當(dāng)要遍歷該結(jié)點(diǎn)的右孩子時,設(shè)置當(dāng)前結(jié)點(diǎn)的標(biāo)志位為 1,進(jìn)棧。這樣,當(dāng)遍歷完成,該結(jié)點(diǎn)彈棧時,
* 查看該結(jié)點(diǎn)的標(biāo)志位的值:如果是 0,表示該結(jié)點(diǎn)的右孩子還沒有遍歷;反之如果是 1,說明該結(jié)點(diǎn)的左右孩子都遍歷完成,可以調(diào)用操作函數(shù)。
* @Param: 結(jié)構(gòu)體指針數(shù)組
* @Return: 無
* @Author: Carlos
*/
void PostOrderTraverse(BiTree Tree){
//定義一個順序棧
SNode a[20];
//臨時指針
BiTree p;
int tag;
SNode sdata;
p=Tree;
while (p||top!=-1) {
//左孩子進(jìn)棧
while (p) {
//為該結(jié)點(diǎn)入棧做準(zhǔn)備
sdata.p=p;
//由于遍歷是左孩子,設(shè)置標(biāo)志位為0
sdata.tag=0;
//壓棧
Push(a, sdata);
//以該結(jié)點(diǎn)為根結(jié)點(diǎn),遍歷左孩子
p=p->lchild;
}
//取棧頂元素 取左孩子的父節(jié)點(diǎn)
sdata=a[top];
//棧頂元素彈棧
Pop();
p=sdata.p;
tag=sdata.tag;
//右孩子進(jìn)棧
//如果tag==0,說明該結(jié)點(diǎn)還沒有遍歷它的右孩子
if (tag==0) {
sdata.p=p;
sdata.tag=1;
//更改該結(jié)點(diǎn)的標(biāo)志位,重新壓棧
Push(a, sdata);
//以該結(jié)點(diǎn)的右孩子為根結(jié)點(diǎn),重復(fù)循環(huán)
p=p->rchild;
}
//如果取出來的棧頂元素的tag==1,說明此結(jié)點(diǎn)左右子樹都遍歷完了,可以調(diào)用操作函數(shù)了
else{
PrintBiT(p);
p=NULL;
}
}
}
int main(){
BiTree Tree;
CreateBiTree(&Tree);
printf("后序遍歷: \n");
PostOrderTraverse(Tree);
}層次遍歷層次遍歷規(guī)則??按照二叉樹中的層次從左到右依次遍歷每層中的結(jié)點(diǎn)。通過使用隊列的數(shù)據(jù)結(jié)構(gòu),從樹的根結(jié)點(diǎn)開始,依次將其左孩子和右孩子入隊。而后每次隊列中一個結(jié)點(diǎn)出隊,都將其左孩子和右孩子入隊,直到樹中所有結(jié)點(diǎn)都出隊,出隊結(jié)點(diǎn)的先后順序就是層次遍歷的最終結(jié)果。 層次遍歷舉例
層次遍歷代碼/*
* @Description: 二叉樹的層次遍歷
* @Version: V1.0
* @Autor: Carlos
* @Date: 2020-05-20 14:52:38
* @LastEditors: Carlos
* @LastEditTime: 2020-05-30 17:41:48
*/
#include <stdio.h>
#include <stdlib.h>
#define TElemType int
//初始化隊頭和隊尾指針開始時都為0
int front=0,rear=0;
typedef struct BiTNode{
//數(shù)據(jù)域
TElemType data;
//左右孩子指針
struct BiTNode *lchild,*rchild;
}BiTNode,*BiTree;
//采用順序隊列,初始化創(chuàng)建隊列數(shù)組
BiTree a[20];
/**
* @Description: 初始化二叉樹
* @Param: BiTree *T 二叉樹的結(jié)構(gòu)體指針數(shù)組
* @Return: 無
* @Author: Carlos
*/
void CreateBiTree(BiTree *T){
*T=(BiTNode*)malloc(sizeof(BiTNode));
(*T)->data=1;
(*T)->lchild=(BiTNode*)malloc(sizeof(BiTNode));
(*T)->rchild=(BiTNode*)malloc(sizeof(BiTNode));
(*T)->lchild->data=2;
(*T)->lchild->lchild=(BiTNode*)malloc(sizeof(BiTNode));
(*T)->lchild->rchild=(BiTNode*)malloc(sizeof(BiTNode));
(*T)->lchild->rchild->data=5;
(*T)->lchild->rchild->lchild=NULL;
(*T)->lchild->rchild->rchild=NULL;
(*T)->rchild->data=3;
(*T)->rchild->lchild=(BiTNode*)malloc(sizeof(BiTNode));
(*T)->rchild->lchild->data=6;
(*T)->rchild->lchild->lchild=NULL;
(*T)->rchild->lchild->rchild=NULL;
(*T)->rchild->rchild=(BiTNode*)malloc(sizeof(BiTNode));
(*T)->rchild->rchild->data=7;
(*T)->rchild->rchild->lchild=NULL;
(*T)->rchild->rchild->rchild=NULL;
(*T)->lchild->lchild->data=4;
(*T)->lchild->lchild->lchild=NULL;
(*T)->lchild->lchild->rchild=NULL;
}
/**
* @Description: 入隊
* @Param: BiTree *a 二叉樹結(jié)構(gòu)體指針 BiTree node 入隊的節(jié)點(diǎn)
* @Return: 無
* @Author: Carlos
*/
void EnQueue(BiTree *a,BiTree node){
a[rear++]=node;
}
/**
* @Description: 出隊
* @Param: BiTree *node 二叉樹結(jié)構(gòu)體指針數(shù)組
* @Return: 結(jié)構(gòu)體指針
* @Author: Carlos
*/
BiTree DeQueue(BiTree *node){
return a[front++];
}
/**
* @Description: 二叉樹輸出函數(shù)
* @Param: BiTree node 輸出的節(jié)點(diǎn)
* @Return: 無
* @Author: Carlos
*/
void displayNode(BiTree node){
printf("%d ",node->data);
}
int main() {
BiTree tree;
//初始化二叉樹
CreateBiTree(&tree);
BiTree p;
//根結(jié)點(diǎn)入隊
EnQueue(a, tree);
//當(dāng)隊頭和隊尾相等時,表示隊列為空
while(front<rear) {
//隊頭結(jié)點(diǎn)出隊
p=DeQueue(a);
displayNode(p);
//將隊頭結(jié)點(diǎn)的左右孩子依次入隊
if (p->lchild!=NULL) {
EnQueue(a, p->lchild);
}
if (p->rchild!=NULL) {
EnQueue(a, p->rchild);
}
}
return 0;
}??總結(jié):其實(shí)不管是哪種遍歷方式,我們最終的目的就是訪問所有的樹(子樹)的根節(jié)點(diǎn),左孩子,右孩子。那么在訪問的過程中,肯定不能一次訪問并打印完畢。這個時候就需要棧來暫存我們已經(jīng)訪問過的元素。在需要的時候?qū)⑵浯蛴〕鰜砑纯桑ㄎ覀円宰蠛⒆庸?jié)點(diǎn)為基準(zhǔn),先序遍歷是在訪問左孩子節(jié)點(diǎn)之前打印節(jié)點(diǎn),中序遍歷是在左孩子節(jié)點(diǎn)壓棧之后打印節(jié)點(diǎn),后序遍歷是在訪問完左右孩子節(jié)點(diǎn)之后打印節(jié)點(diǎn))。 |
|
|