算法思想
按一定的规则和顺序走遍二叉树的所有结点,使每一个结点都被访问一次,而且只被访问一次。由于二叉树是非线性结构,因此,树的遍历实质上是将二叉树的各个结点转换成为一个线性序列来表示
(1)先序遍历:
- 访问根结点
- 先序遍历左子树
- 先序遍历右子树
(2)中序遍历
- 中序遍历左子树
- 访问根节点
- 中序遍历右子树
(3)后序遍历二叉树
- 后序遍历左子树
- 后序遍历右子树
- 访问根节点
示意图
先序遍历
中序遍历
后续遍历
代码实现
// 采用递归算法实现二叉树的三种深度遍历:先序遍历、中序遍历、后序遍历
// 二叉树的存储结构采用的二叉链表
// 例如输入AB##DE##C##,则确定要建立的二叉树
// 采用递归方式先序、中序、后序遍历二叉树
// 采用递归方式统计二叉树中各种结点的个数
#include<iostream>
#include<stdlib.h>
#define OVERFLOW -1
#define OK 1
#define ERROR 0
using namespace std;
typedef int status;
typedef char TElemType;
typedef struct BiTNode {
//二叉树的二叉链表存储结构
TElemType data;//设置数据域
struct BiTNode *lchild, *rchild;//设置左右孩子指针
} BiTNode, *BiTree;
int coutSum0 = 0;//度数为0的结点为
int coutSum1 = 0;//度数为1的结点
int coutSum2 = 0;//度数为2的结点
status Creat(BiTree &t) {
/*创建步骤:
* 扫描字符序列,读入字符ch
* 如果ch是一个‘#’字符,则表明该二叉树为空树,即T为NULL;否则执行
* 1.申请一个节点空间T
* 2.将ch赋值给T->data
* 3.递归创建T的左子树
* 4.递归创建T的右子树
* ABC##DE#G##F###
*/
//先序创建二叉树
char ch;
cin >> ch;
if (ch == '#') t = NULL;
else {
t = new BiTNode;//生成根节点
t->data = ch;//根节点数据域为ch
cout << t->data;
Creat(t->lchild);//递归创建左子树
Creat(t->rchild);//递归创建右子树
}
return 0;
}//Creat
void DLR(BiTree t) {
//先序遍历二叉树
/*若二叉树为空,则空操作;否则
* (1)访问根节点
* (2)先序遍历左子树
* (3)先序遍历右子树
*/
if (t) {
cout << t->data;
DLR(t->lchild);
DLR(t->rchild);
}
}//DLR
void LDR(BiTree t) {
//中序遍历二叉树
/*若二叉树为空,则空操作;否则
* (1)中序遍历左子树
* (2)访问根节点
* (3)中序遍历右子树
*/
if (t) {
LDR(t->lchild);
cout << t->data;
LDR(t->rchild);
}
}//LDR
void LRD(BiTree t) {
//后序遍历二叉树
/*若二叉树为空,则空操作;否则
* (1)后序遍历左子树
* (2)后序遍历右子树
* (3)访问根节点
*/
if (t) {
LRD(t->lchild);
LRD(t->rchild);
cout << t->data;
}
}//LRD
void Destroy(BiTree &t) {
//后序销毁二叉树
/*1.如果采用先序遍历或者中序遍历,销毁根节点后就找不到左右孩子
*2.在销毁的时候需要保存左右孩子的地址。
*/
if (t) {
Destroy(t->lchild);
Destroy(t->rchild);
free(t);
t=NULL;
}
cout << "销毁后二叉树为:" << t << endl;
}//Destroy
int Node0Count(BiTree t) {
//统计二叉树中度为0的结点的个数
// 用先序遍历,判断节点的左右子树全为‘#’,那么其为度为0的结点
if (t) {
if(t->lchild==NULL && t->rchild==NULL){
coutSum0++;
}
Node0Count(t->lchild);
Node0Count(t->rchild);
}
return coutSum0;
}//Node0Count
int Node1Count(BiTree t) {
//统计二叉树中度为1的结点的个数
if (t) {
if ((t->lchild == NULL && t->rchild != NULL) || (t->lchild != NULL && t->rchild == NULL)) {
coutSum1++;
}
Node1Count(t->lchild);
Node1Count(t->rchild);
}
return coutSum1;
}//Node1Count
int Node2Count(BiTree t) {
//统计二叉树中度为2的结点的个数
if (t) {
if (t->lchild != NULL && t->rchild != NULL) {
coutSum2++;
}
Node2Count(t->lchild);
Node2Count(t->rchild);
}
return coutSum2;
}//Node2Count
int main() {
int ch;
BiTree t = NULL;
cout << "命令菜单:\n\t1.建立二叉树\n\t2.先序遍历\n\t3.中序遍历\n\t4.后序遍历\n\t5.统计二叉树各种结点的个数\n\t6.销毁二叉树\n\t7.退出" << endl;
cout << "\n请输入命令:";
cin >> ch;
while (ch != 7) {
switch (ch) {
case 1:
cout << "\n请输入要建立的二叉树中的元素,#代表空树\n";
Creat(t);
cout << "二叉树建立成功\n";
cout << "\n请继续输入命令:";
break;
case 2:
cout << "先序遍历的结果为:";
DLR(t);
cout << "\n\n请继续输入命令:";
break;
case 3:
cout << "中序遍历的结果为:";
LDR(t);
cout << "\n\n请继续输入命令:";
break;
case 4:
cout << "后序遍历的结果为:";
LRD(t);
cout << "\n\n请继续输入命令:";
break;
case 5:
cout << "二叉树中度为0的结点个数为:" << Node0Count(t) << endl;
cout << "二叉树中度为1的结点个数为:" << Node1Count(t) << endl;
cout << "二叉树中度为2的结点个数为:" << Node2Count(t) << endl;
cout << "\n\n请继续输入命令:";
break;
case 6:
Destroy(t);
if (t==NULL){
cout << "二叉树已销毁";
} else cout<<"二叉树没销毁"<<endl;
cout << "\n\n请继续输入命令:";
break;
default:
cout << "\n输入命令出错,请重新输入命令:";
}
cin >> ch;
}
return 0;
}//main