二叉树Bynary_Tree(2):二叉树的递归遍历
前言
以下的代码实现都以该完全二叉树为例:

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

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的地址吗?

通过在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;
}
二叉树Bynary_Tree(2):二叉树的递归遍历的更多相关文章
- Java数据结构之二叉树的基本介绍与递归遍历
二叉树的基本概念: 正如我们所了解的,树是有很多中形态,但是我们规定,形如每个节点最多只能有两个子节点的一种形如称为二叉树.我们将二叉树中该节点的两个子节点分别称作为:左孩子节点和右孩子节点.该节点称 ...
- C++学习---二叉树的输入及非递归遍历
二叉树的二叉链表存储表示如下 //二叉树的二叉链表存储表示 typedef struct BiTNode { char data;//结点数据域 struct BiTNode* lchild, * r ...
- 数据结构二叉树的递归与非递归遍历之java,javascript,php实现可编译(1)java
前一段时间,学习数据结构的各种算法,概念不难理解,只是被C++的指针给弄的犯糊涂,于是用java,web,javascript,分别去实现数据结构的各种算法. 二叉树的遍历,本分享只是以二叉树中的先序 ...
- 二叉树3种递归和非递归遍历(Java)
import java.util.Stack; //二叉树3种递归和非递归遍历(Java) public class Traverse { /******************一二进制树的定义*** ...
- C++编程练习(17)----“二叉树非递归遍历的实现“
二叉树的非递归遍历 最近看书上说道要掌握二叉树遍历的6种编写方式,之前只用递归方式编写过,这次就用非递归方式编写试一试. C++编程练习(8)----“二叉树的建立以及二叉树的三种遍历方式“(前序遍历 ...
- 二叉树的递归遍历 Tree UVa548
题意:给一棵点带权的二叉树的中序和后序遍历,找一个叶子使得他到根的路径上的权值的和最小,如果多解,那该叶子本身的权值应该最小 解题思路:1.用getline()输入整行字符,然后用stringstre ...
- c/c++二叉树的创建与遍历(非递归遍历左右中,破坏树结构)
二叉树的创建与遍历(非递归遍历左右中,破坏树结构) 创建 二叉树的递归3种遍历方式: 1,先中心,再左树,再右树 2,先左树,再中心,再右树 3,先左树,再右树,再中心 二叉树的非递归4种遍历方式: ...
- JAVA递归、非递归遍历二叉树(转)
原文链接: JAVA递归.非递归遍历二叉树 import java.util.Stack; import java.util.HashMap; public class BinTree { priva ...
- 非递归遍历二叉树Java实现
2018-10-03 20:16:53 非递归遍历二叉树是使用堆栈来进行保存,个人推荐使用双while结构,完全按照遍历顺序来进行堆栈的操作,当然在前序和后序的遍历过程中还有其他的压栈流程. 一.Bi ...
- ZT 二叉树的非递归遍历
ZT 二叉树的非递归遍历 二叉树的非递归遍历 二叉树是一种非常重要的数据结构,很多其它数据结构都是基于二叉树的基础演变而来的.对于二叉树,有前序.中序以及后序三种遍历方法.因为树的定义本身就 是递归定 ...
随机推荐
- SSM框架通过mybatis-generator自动生成代码
一.首先eclipse配置好maven环境,并且创建好一个SSM框架的工程 二.在pom.xml中添加plugin <build> <finalName>ssm_web< ...
- Android WebView 上传各种文件(包括拍照 录像 录音 文件 音乐 等,用到图片或拍照的,可以参考下)
我也是从网上扒下来的,经过多次实验,找到了个好用的.网上能搜到最多的也就是这个解决方案,我英文不好,也没仔细研究,但大多数都是出自这: http://stackoverflow.com/questio ...
- 《java.util.concurrent 包源码阅读》27 Phaser 第一部分
Phaser是JDK7新添加的线程同步辅助类,作用同CyclicBarrier,CountDownLatch类似,但是使用起来更加灵活: 1. Parties是动态的. 2. Phaser支持树状结构 ...
- 晓莲说-何不原创:java 实现二维数组冒泡排序
新手从业路-为自己回顾知识的同时,也希望和大家分享经验: 话不多说,上代码 public class 冒泡排序 { /** * @param admin * @2017.12.4 ...
- selenium 执行js,实现滚动条
今天在写脚本的时候,学习了执行js,实现滚动条,对于scrollTop=10000中这个10000是怎么来的,还不是很了解,先将方法记录一下, 1.滚动条回到顶部: js_up="docum ...
- P2024食物链
题目描述 动物王国中有三类动物 A,B,C,这三类动物的食物链构成了有趣的环形.A 吃 B,B 吃 C,C 吃 A. 现有 N 个动物,以 1 - N 编号.每个动物都是 A,B,C 中的一种,但是我 ...
- PHP 字符串转 bigint 型md5
1 2 3 4 5 6 7 8 /** * 字符串转bigint * @return bigint(string) */ public function md5( ...
- linux用户、组、权限问题
用户.组.权限一.权限:r, w, x1.文件权限: r:可读,可以使用类似cat等命令查看文件内容: w:可写,可以编辑或删除此文件: x: 可执行,eXacutabl ...
- 关于hue安装后出现KeyError: "Couldn't get user id for user hue"的解决方法
首先说明出现此问题的原因是因为你使用的root用户安装了hue,然后在root用户下使用的build/env/bin/supervisor,如下图所示那样: 知道了原因,就容易解决问题了.首先要创建个 ...
- java基础进阶一:String源码和String常量池
作者:NiceCui 本文谢绝转载,如需转载需征得作者本人同意,谢谢. 本文链接:http://www.cnblogs.com/NiceCui/p/8046564.html 邮箱:moyi@moyib ...