二叉树Bynary_Tree(2):二叉树的递归遍历

时间:2022-10-25 23:12:47

前言


  以下的代码实现都以该完全二叉树为例:

  二叉树Bynary_Tree(2):二叉树的递归遍历

声明结构体


typedef struct node
{
char ch;
struct node *lchild;
struct node *rchild;
}TreeNode,*Tree; //注意区别,例如TreeNode X1与*Tree X2,X1为结构体变量,X2为结构体指针变量

创建树


  二叉树Bynary_Tree(2):二叉树的递归遍历

  1.采用前序创建

  2.若某子结点为不存在,则将其置为NULL,方法为:判断输入的字符是否为' * ',若为* ,则置当前结点为NULL

  3.递归创建子结点

void Create_pro(Tree* T)
{
char ch;
scanf("%c", &ch); //需一次性输入所有字符,若分行输入,由于缓冲区问题,多出的空格将一直递归下去
if (ch == '*')
{
*T = NULL;
}
else
{
*T = (Tree)malloc(sizeof(TreeNode));
(*T)->ch = ch;
Create_pro(&((*T)->lchild));
Create_pro(&((*T)->rchild));
}
}

  这里遇到的scanf缓冲区问题可移步:http://bbs.csdn.net/topics/390284350?page=1

删除二叉树


void ClearTree(Tree *T)
{
if (!*T)
{
return;
} ClearTree(&(*T)->lchild);
ClearTree(&(*T)->rchild);
free(*T);
*T = NULL;
}

前(根)序遍历


  先访问根结点,再分别前序遍历左、右两棵子树。前序遍历的结果是:ABCDEF

void Show_pro(Tree t)
{
if(!t)
return;
printf("%c ",t->ch);
Show_pro(t->lchild);
Show_pro(t->rchild);
}

中(根)序遍历


  先中序遍历左子树,然后再访问根结点,最后再中序遍历遍历右子树。中序遍历的结果是:CBADEF

void Show_mid(Tree t)
{
if(!t)
return;
Show_mid(t->lchild);
printf("%c ",t->ch);
Show_mid(t->rchild);
}

后(根)序遍历


  先后序遍历左子树,然后后序遍历右子树,最后访问根结点。后序遍历的结果是:CBEFDA

void Show_back(Tree t)
{
if(!t)
return;
Show_back(t->lchild);
Show_back(t->rchild);
printf("%c ",t->ch);
}

层次遍历


  先按深度划分层,深度为1的对应树的第一层,深度为二的对应树的第二层...以此类推。然后逐层访问结点。

  除层次遍历外的三种遍历的设计核心思想为栈,后进先出,因此想到递归。而层次遍历是队列,先进先出,我采用循环队列去解决。具体的算法设计如下:

    1.定义一个队列Tree q[MAX]存储队列数据,头变量front与尾变量rear存储首尾位置,规定front == rear时队列为空。

    2.初始化,令 front = 0 ,rear = 0

    3.入队操作。将树T存入q[rear]中,即T入队,然后 rear = (rear+1)%MAX ,保持rear在0到MAX中循环

    4.输出结点数据。同时判断子结点中数据的存在情况,子结点不为NULL,则再进行入队操作

    5.出队操作。front = (front+1)%MAX;

void Show_level(Tree T)
{
Tree q[MAX]; //队列
Tree p; //当前结点
int front;
int rear; //初始化
front =0;
rear =0; if(T)
{
q[rear] = T;
rear = (rear+1)%MAX;
} while(front != rear)
{
p = q[front];
printf("%c ",p->ch);
if(p->lchild)
{
q[rear] = p->lchild;
rear = (rear+1)%MAX;
}
if(p->rchild)
{
q[rear] = p->rchild;
rear = (rear+1)%MAX;
}
front = (front+1)%MAX;
}
}

  层次遍历模块中有一个难点,即是入队操作,如何将树并入队列呢?我们想到将若根结点并入队列,那么整棵树便并入队列了。然而,就必须考虑一个问题,根结点的地址就是T的地址吗?

  二叉树Bynary_Tree(2):二叉树的递归遍历

  通过在create_tree时将每一次申请的结点地址打印出来,并在创建完毕后在main函数里printf一次T的地址,实际结果如图,根结点地址果然是T的地址,那么我们就可以用根结点入队来实现整棵树入队的操作了,同时也可得到一个结论:递归建树,根结点地址即是树的地址。

判断树是否为空树


void IsTreeEmpty(Tree T)
{
if(T)
printf("Tree is not empty\n");
else
printf("Tree is empty\n");
}

  

源代码


/*************************************************************************
> File Name: Binary tree
> Author: Bw98
> Mail: 786016746@qq.com
> Blog: www.cnblogs.com/Bw98blogs/
> Created Time: SUN 16th Jul. 2017
************************************************************************/
#include<stdio.h>
#include<stdlib.h>
#define MAX 100
typedef struct node
{
char ch;
struct node *lchild;
struct node *rchild;
}TreeNode,*Tree; void InitTree(Tree *T); //树初始化
void Create_pro(Tree *T); //创建一棵树并输入相应元素
void Show_pro(Tree t); //先(根)序遍历输出
void Show_mid(Tree t); //中(根)序遍历输出
void Show_back(Tree t); //后(根)序遍历输出
void Show_level(Tree T); //层次遍历输出
void IsTreeEmpty(Tree T); //检测树是否为空
void ClearTree(Tree *T); //清除树 int main()
{
Tree t;
InitTree(&t);
printf("输入前序遍历序列(输入'*'时,该树结点为空)\n");
Create_pro(&t);
Show_pro(t);
Show_mid(t);
Show_back(t);
Show_level(t);
IsTreeEmpty(t);
ClearTree(&t);
IsTreeEmpty(t);
return 0;
} void InitTree(Tree *T)
{
*T =NULL;
} void Create_pro(Tree* T)
{
char ch;
scanf("%c", &ch);
if (ch == '*')
{
*T = NULL;
}
else
{
*T = (Tree)malloc(sizeof(TreeNode));
(*T)->ch = ch;
Create_pro(&((*T)->lchild));
Create_pro(&((*T)->rchild));
}
} void Show_pro(Tree t)
{
if(!t)
return;
printf("%c ",t->ch);
Show_pro(t->lchild);
Show_pro(t->rchild);
} void Show_mid(Tree t)
{
if(!t)
return;
Show_mid(t->lchild);
printf("%c ",t->ch);
Show_mid(t->rchild);
} void Show_back(Tree t)
{
if(!t)
return;
Show_back(t->lchild);
Show_back(t->rchild);
printf("%c ",t->ch);
} void Show_level(Tree T)
{
Tree q[MAX]; //队列
Tree p; //当前结点
int front;
int rear; //初始化
front =0;
rear =0; if(T)
{
q[rear] = T;
rear = (rear+1)%MAX;
} while(front != rear)
{
p = q[front];
printf("%c ",p->ch);
if(p->lchild)
{
q[rear] = p->lchild;
rear = (rear+1)%MAX;
}
if(p->rchild)
{
q[rear] = p->rchild;
rear = (rear+1)%MAX;
}
front = (front+1)%MAX;
}
} void IsTreeEmpty(Tree T)
{
if(T)
printf("Tree is not empty\n");
else
printf("Tree is empty\n");
} void ClearTree(Tree *T)
{
if (!(*T))
{
return;
} ClearTree(&(*T)->lchild);
ClearTree(&(*T)->rchild);
free(*T);
*T = NULL;
}