算法基础11 —— 树入门(二叉树的遍历以及构造 + 普通树转换成二叉树 + 例题 + 二叉树的一些操作)
字符二叉树的遍历
对于以上二叉树
先序遍历为(根左右) : 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 —— 树入门(二叉树的遍历以及构造 + 普通树转换成二叉树 + 例题 + 二叉树的一些操作)相关推荐
- 二叉树-树转二叉树 使用队列,编写transfrom函数,将普通树转换成对应的二叉树。
树转二叉树 使用队列,编写transfrom函数,将普通树转换成对应的二叉树.二叉树的相关定义如下: typedef int DataType; typedef struct Node{DataTyp ...
- 树的四种遍历案例和AVL树的旋转的四种情况
树与二叉树 一, 树的基本术语 树中一个结点的子结点个数称为该结点的度, 树中结点的最大度数称为树的度.如结点B的度为2,结点D的度为3,树的度为3. 度大于0的结点称为分支结点(又称非终端结点),度 ...
- 试解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 ...
- 算法基础2 —— OJ入门以及暴力枚举
常见的OJ术语 Accepted (AC)-- 成功过题 Wrong Answer (WA) -- 输出结果错,一般是算法有问题,需要重新考虑思路或者其他 Runtime Error (RE) -- ...
- 算法基础14 —— 图论入门之弗洛伊德算法(Floyed + Dijkstra + Bellman-Ford + SPFA)
入门概念 带权图:如下图所示,我们把边带有权值的图称为带权图 可以将边的权值理解为两点之间的距离 一张图中任意两点间会有不同的路径相连 最短路径:最短路径就是指连接两点的这些路径中最短的一条 Floy ...
- 二叉树层序遍历递归与非递归_总结归纳:二叉树遍历【递归 amp;amp; 非递归】...
今天为大家总结了二叉树前中后序遍历的递归与迭代解法: 1. 前序遍历 递归 List list=new ArrayList<>();public ListpreOrder(TreeNode ...
- 二叉树层次遍历c语言_每日一道 LeetCode (23):二叉树的层次遍历 II
❝ 每天 3 分钟,走上算法的逆袭之路. ❞ 前文合集 每日一道 LeetCode 前文合集 代码仓库 GitHub:https://github.com/meteor1993/LeetCode Gi ...
- 二叉树层次遍历python_根据二叉树层序遍历顺序(数组),将其转换为二叉树(Python)...
1.创建二叉树结点和值 class Node: def __init__(self, value): self.value = value self.left = None self.right = ...
- Python基础详解(十三):(视频符号化)将视频转换成ASCII符号形式展示出来
目录 一. 前言 二. 项目简介 三. 基本要求 四. 代码实现 4.1 安装ffmpeg.exe 4.2 安装you-get库 4.2.1 下载 4.2.2 检查视频信息 4.2.3 下载 mp3 ...
最新文章
- 2022-2028年中国版权行业深度调研及投资前景预测报告
- 使用 EclEmma 来显示代码覆盖率
- 三十四、多线程真的比单线程快?
- MySQL 错误 #1113
- python两个二维数组加法_对二维数组的多个列进行Numpy平均
- 条形图坐标轴_解密咨询报告中常见的双层条形图的制作方法
- Java5线程并发库之LOCK(锁)CONDITION(条件)实现线程同步通信
- jsp--cookie
- oracle定义变量sql赋值_ORACLE获取SQL绑定变量值的方法总结
- (数据库系统概论|王珊)第六章关系数据理论-第一节:为什么要研究关系数据理论
- linux下双击sh文件夹,Linux系统下如何运行.sh文件的实现
- 【Django 2021年最新版教程7】前端html接收后端传递的变量值 渲染
- 第1章 SAAS-HRM系统概述与搭建环境
- 主板检测卡c5_主板检测卡显示的代码都是什么
- 海量图片上传及存储方案
- 停止SHA1算法签名证书及时间戳服务尤其是代码签名证书,补丁介绍
- 1月1日服务器例行维护公告,1月1日服务器例行维护公告(已完成)
- grafana图形化数据展示软件介绍
- 记录文件服务器的操作日志
- python中的阶乘,python中阶乘怎么表示