字符二叉树的遍历


对于以上二叉树
先序遍历为(根左右) : ABCDEFG
中序遍历为(左根右) : CBEDAFG
后序遍历为(左右根) : CEDBGFA
层序遍历:(从左往右、从上往下) ABFCDGE

以先序次序输入以上二叉树:
ABC##DE###F#G##

代码实现遍历操作:

#include <iostream>
#include <queue>
using namespace std;typedef struct node
{char data;struct node *lchild;struct node *rchild;
}BTNode,*tree;
tree root = NULL;//按照先序次序输入二叉树的结点,bt为指向根结点的指针,建树需要&
void pre_crt(tree &bt)
{char ch;ch = getchar();if (ch != '#'){bt = new node;//建立根结点bt -> data = ch;pre_crt(bt -> lchild);//建左子树pre_crt(bt -> rchild);//建右子树}else bt = NULL;
}void DLR(tree bt)
{if (bt == NULL) return;//先序遍历(根左右),遍历树不需要&cout << bt -> data;DLR(bt -> lchild);DLR(bt -> rchild);
}void LDR(tree bt)
{if (bt == NULL) return;//中序遍历(左根右)LDR(bt -> lchild);cout << bt -> data;LDR(bt -> rchild);
}void LRD(tree bt)
{if (bt == NULL) return;//后序遍历(左右根)LRD(bt -> lchild);LRD(bt -> rchild);cout << bt -> data;
}//层次遍历,传入根结点
void BTLeversearch(tree bt)
{queue<tree> q;//tree指的是指针,即队列中存储指针if (bt == NULL) return;q.push(bt);//根结点入队while (!q.empty())//队列非空{tree head = q.front();//获取队头元素cout << head -> data;if (head -> lchild) q.push(head -> lchild);if (head -> rchild) q.push(head -> rchild);q.pop();}
}int main()
{pre_crt(root);//创建DLR(root);//先序遍历cout << endl;LDR(root);//中序遍历cout << endl;LRD(root);//后序遍历cout << endl;BTLeversearch(root);cout << endl;return 0;
}

输入
ABC##DE###F#G##
输出
ABCDEFG
CBEDAFG
CEDBGFA
ABFCDGE

二叉树的构造

已知结点的先序序列为ABDGEHCF,中序序列为GDBHEACF。试构造出二叉树。
方法: 如果已知一棵二叉树的先序或者后序序列,就可以首先确定根结点(第一个或者最后一个结点),再根据中序序列确定左右子树如何分布。对于每棵子树,反复的从先序或者后序序列中找出根结点… …
【对于上例,二叉树的根结点为A】
构造出的二叉树如下:

普通树转换成二叉树

二叉树的操作和应用更广泛,在实际使用时,我们经常把普通树转换成二叉树进行操作。如何转换呢?一般方法如下:

  • 第一步:将树中每个结点除了最左边的一个分支保留外,其余分支都去掉;
  • 第二步:从最左边结点开始画一条线,把同一层上的兄弟结点都连起来;
  • 第三步:以整棵树的根结点为轴心,将整棵树顺时针旋转45度。

举例:
下图是一棵普通的树

经过第一步之后,树变为如下形态:

经过第二步之后,树变为如下形态:
注意:只连接兄弟结点即可,故六号结点和七号结点不需要连接

经过第三步之后,树变为如下二叉树形态:

几道例题

例1.一棵完全二叉树的结点总数为18,其叶结点数为©
A.7
B.8
C.9
D.10
解:对于n层二叉树,其最多有2^n - 1个结点。由2 ^ n - 1 = 18,2 ^ 4 - 1 = 15 < 18,2 ^ 5 - 1 = 31 > 18,故n等于5,5层二叉树画图即可。不难发现,有9个叶子结点

例2.对任何一棵二叉树T,设n0、n1、n2分别是度数为0、1、2的顶点数,则下列判断中正确的是 (A)
A.n0 = n2+1
B.n1 = n0+1
C.n2 = n0+1
D.n2 = n1+1
送分题:性质的复习

例3.某二叉树的前序序列和后序序列正好相反,则该二叉树一定是 (B)的二叉树。
A.空或只有一个结点
B.高度等于其结点数
C.任一结点无左孩子
D.任一结点无右孩子
解法一:已知前序序列和后序序列相反

  • 若去掉左子树,DLR=DR,LRD=RD,满足条件
  • 若去掉右子树,DLR=DL,LRD=LD,满足条件
  • C、D中带有一定二字,故排除C、D,A可以直接排除

解法二:对于下面的两棵二叉树,其先序遍历和后序遍历序列均相反,故C、D均可排除。但其都满足高度等于其结点数,故选B

先序遍历:1234
后序遍历:4321

先序遍历:1234
后序遍历:4321

例4.一个二叉树的先序遍历结果和中序遍历结果相同,则其所有非叶子节点必须满足的条件是(B)
A.只有左子树
B.只有右子树
C.节点的度为1
D.节点的度为2
解:
与上题类似,已知先序遍历和中序遍历相同,即DLR=LDR

  • 若去掉右子树(只有左子树),则DL=LD,先序遍历和中序遍历相反,故排除A
  • 若去掉左子树(只有右子树),则DR=DR,先序遍历和中序遍历相同,故选B

例5.下图为一个二叉树,请选出以下不是遍历二叉树产生的顺序序列的选项(BD)
A. ABCDEFIGJH
B. BDCAIJGHFE
C. BDCAIFJGHE
D. DCBJHGIFEA

解:
先序序列(根左右):ABCDEFIGJH
中序序列(左根右):BDCAIFJGHE
后序序列(左右根):DCBIJHGFEA

例6.中缀表达式A-(B+C/D)*E的后缀形式是(D)
A.AB-C+D/E*
B.ABC+D/-E*
C.ABCD/E*+-
D.ABCD/+E*-
提示:后缀表达式的操作符在操作数的后面

例7.中缀表达式1-(2+3)的前缀形式是(A)
A.-1+23
B.-12+3
C.-12+3
D.-+123
提示:前缀表达式的操作符在操作数的前面

二叉树的一些操作

  • 求二叉树结点的个数
  • 求二叉树叶子结点的个数
  • 求二叉树的深度
  • 判断一个结点是否在二叉树中
  • 求第k层结点的个数

代码实现:

#include <iostream>
#include <queue>
using namespace std;typedef struct node
{char data;struct node *lchild;struct node *rchild;
}BTNode,*tree;
tree root = NULL;//先序次序建树
void pre_crt(tree &bt)
{char ch;ch = getchar();if (ch != '#'){bt = new node;bt -> data = ch;pre_crt(bt -> lchild);pre_crt(bt -> rchild);}else bt = NULL;
}//二叉树结点的个数
//二叉树结点的个数=左子树结点个数+右子树结点个数+1 (1为根结点)
int BTNodesize(tree bt)
{if (bt == NULL) return 0;return BTNodesize(bt -> lchild) + BTNodesize(bt -> rchild) + 1;
}//二叉树叶子结点的个数
//二叉树叶子结点的个数=左子树叶子结点个数+右子树叶子结点个数
int BTNodeleaf(tree bt)
{if (bt == NULL) return 0;if (bt -> lchild == NULL && bt -> rchild == NULL) return 1;//叶子结点return BTNodeleaf(bt -> lchild) + BTNodeleaf(bt -> rchild);
}//求二叉树的深度
//二叉树的深度=max(左子树深度,右子树深度)+1 (1为根结点)
int BTDepth(tree bt)
{if (bt == NULL) return 0;int left = BTDepth(bt -> lchild);int right = BTDepth(bt -> rchild);return (left > right) ? (left + 1):(right + 1);
}//判断一个结点x是否在二叉树中
bool BTFind(tree bt,char x)
{bool temp;if (bt == NULL) return false;//树空,返回falseif (bt -> data == x) return true;//递归出口:找到temp = BTFind(bt -> lchild,x);//从左子树中查找xif (temp) return true;temp = BTFind(bt -> rchild,x);//从右子树中查找xif (temp) return true;return false;//没找到
}//求第k层结点的个数
//当前树的第k层等于当前树的左子树的第k-1层(右子树同理)
int BTNodeKLevelSize(tree bt,int k)
{if (bt == NULL) return 0;//空树if (k == 1) return 1;//第一层之有根结点return BTNodeKLevelSize(bt -> lchild,k - 1) + BTNodeKLevelSize(bt -> rchild,k - 1);
}int main()
{pre_crt(root);cout << BTNodesize(root) << endl;//求二叉树结点的个数:7cout << BTNodeleaf(root) << endl;//求二叉树叶子结点的个数:3cout << BTDepth(root) << endl;//求二叉树的深度:4if (BTFind(root,'D')) cout << "FIND" << endl;else cout << "NOT FIND" << endl;//判断一个结点是否在二叉树中cout << BTNodeKLevelSize(root,3) << endl;//求第3层结点的个数3:return 0;
}

(以博客开头的第一棵树为例)

输入
ABC##DE###F#G##
输出
7
3
4
FIND
3

判断一颗二叉树是否为完全二叉树

算法思想:

  • 借助queue< int> q,将各个结点以层序遍历序列进行入队
  • 如果发现q.front()为NULL时,表示读取到了一个空结点,若它后面的结点都是NULL,则表示为完全二叉树
  • 若它后面的结点出现不为NULL的情况,表示为非完全二叉树。

举例:
对于下图的一棵完全二叉树

对其进行层序遍历,得到1-2-5-3-4-null-null,按照这个顺序将结点依次入队,得到队列:

队列中的非NULL结点连续,故其是一棵完全二叉树

对于下图的非完全二叉树

对其进行层序遍历,得到1-2-5-3-4-null-6,按照这个顺序将结点依次入队,得到队列:

队列中的非NULL结点不连续,故其是一棵非完全二叉树

算法基础11 —— 树入门(二叉树的遍历以及构造 + 普通树转换成二叉树 + 例题 + 二叉树的一些操作)相关推荐

  1. 二叉树-树转二叉树 使用队列,编写transfrom函数,将普通树转换成对应的二叉树。

    树转二叉树 使用队列,编写transfrom函数,将普通树转换成对应的二叉树.二叉树的相关定义如下: typedef int DataType; typedef struct Node{DataTyp ...

  2. 树的四种遍历案例和AVL树的旋转的四种情况

    树与二叉树 一, 树的基本术语 树中一个结点的子结点个数称为该结点的度, 树中结点的最大度数称为树的度.如结点B的度为2,结点D的度为3,树的度为3. 度大于0的结点称为分支结点(又称非终端结点),度 ...

  3. 试解PTA《20211122-函数基础练习》,涉及 高精度加法 和 10进制转换成2-16进制问题,有需要的同学来看看吧;

    目录 一.前言 二.例题部分 2.1.进制转换 2.1.1.题解1 2.1.2.题解2 2.2. 函数返回一个整数的反序数 (20 分) 2.2.2 题解 2.3. 大整数A+B (10 分) 2.3 ...

  4. 算法基础2 —— OJ入门以及暴力枚举

    常见的OJ术语 Accepted (AC)-- 成功过题 Wrong Answer (WA) -- 输出结果错,一般是算法有问题,需要重新考虑思路或者其他 Runtime Error (RE) -- ...

  5. 算法基础14 —— 图论入门之弗洛伊德算法(Floyed + Dijkstra + Bellman-Ford + SPFA)

    入门概念 带权图:如下图所示,我们把边带有权值的图称为带权图 可以将边的权值理解为两点之间的距离 一张图中任意两点间会有不同的路径相连 最短路径:最短路径就是指连接两点的这些路径中最短的一条 Floy ...

  6. 二叉树层序遍历递归与非递归_总结归纳:二叉树遍历【递归 amp;amp; 非递归】...

    今天为大家总结了二叉树前中后序遍历的递归与迭代解法: 1. 前序遍历 递归 List list=new ArrayList<>();public ListpreOrder(TreeNode ...

  7. 二叉树层次遍历c语言_每日一道 LeetCode (23):二叉树的层次遍历 II

    ❝ 每天 3 分钟,走上算法的逆袭之路. ❞ 前文合集 每日一道 LeetCode 前文合集 代码仓库 GitHub:https://github.com/meteor1993/LeetCode Gi ...

  8. 二叉树层次遍历python_根据二叉树层序遍历顺序(数组),将其转换为二叉树(Python)...

    1.创建二叉树结点和值 class Node: def __init__(self, value): self.value = value self.left = None self.right = ...

  9. Python基础详解(十三):(视频符号化)将视频转换成ASCII符号形式展示出来

    目录 一. 前言 二. 项目简介 三. 基本要求 四. 代码实现 4.1 安装ffmpeg.exe 4.2 安装you-get库 4.2.1 下载 4.2.2 检查视频信息 4.2.3 下载 mp3 ...

最新文章

  1. 2022-2028年中国版权行业深度调研及投资前景预测报告
  2. 使用 EclEmma 来显示代码覆盖率
  3. 三十四、多线程真的比单线程快?
  4. MySQL 错误 #1113
  5. python两个二维数组加法_对二维数组的多个列进行Numpy平均
  6. 条形图坐标轴_解密咨询报告中常见的双层条形图的制作方法
  7. Java5线程并发库之LOCK(锁)CONDITION(条件)实现线程同步通信
  8. jsp--cookie
  9. oracle定义变量sql赋值_ORACLE获取SQL绑定变量值的方法总结
  10. (数据库系统概论|王珊)第六章关系数据理论-第一节:为什么要研究关系数据理论
  11. linux下双击sh文件夹,Linux系统下如何运行.sh文件的实现
  12. 【Django 2021年最新版教程7】前端html接收后端传递的变量值 渲染
  13. 第1章 SAAS-HRM系统概述与搭建环境
  14. 主板检测卡c5_主板检测卡显示的代码都是什么
  15. 海量图片上传及存储方案
  16. 停止SHA1算法签名证书及时间戳服务尤其是代码签名证书,补丁介绍
  17. 1月1日服务器例行维护公告,1月1日服务器例行维护公告(已完成)
  18. grafana图形化数据展示软件介绍
  19. 记录文件服务器的操作日志
  20. python中的阶乘,python中阶乘怎么表示

热门文章

  1. PyCharm许可证过期解决方案
  2. html文件名解压乱码怎么办,压缩文件解压后乱码怎么办?解压乱码解决办法
  3. Ubuntu16.04系统nvidia显卡上图形界面及OpenGL环境搭建心得
  4. 关于数组名(arr)的理解
  5. 隐私计算之差分隐私-Laplace机制
  6. python:list能像数值一样做运算么?
  7. Java设计模式(03) -- 里氏替换原则
  8. 学英语《每日一歌》之yesterday once more
  9. c++动态数组的优点,创建和删除
  10. scanf_s 用法