二叉树的前序遍历、中序遍历、后续遍历和层序遍历

2023-11-05

题目

L2-004 这是二叉搜索树吗? (25 分)

L2-006 树的遍历 (25 分)

L2-011 玩转二叉树 (25 分)

L2-035 完全二叉树的层序遍历 (25 分)

L3-010 是否完全二叉搜索树 (30 分)

代码

L2-004 这是二叉搜索树吗? (25 分)

// https://pintia.cn/problem-sets/994805046380707840/problems/994805070971912192
#include<bits/stdc++.h>
using namespace std;
const int N = 1100;
int n, a[N];
vector <int> v;

void dfs (int l, int r, int mir) {
	if (l > r) return ;
	int rt = a[l];
	int p = l+1, q = l+1;
	if (!mir) { // 非镜像
		while (p <= r && a[p] < rt) p ++, q ++; // 找到第一个大于等于根节点的,也就是右子树的开头
		while (q <= r && a[q] >= rt) q ++; // 找到右子树的结尾的后一个
	} else {
		while (p <= r && a[p] >= rt) p ++, q ++;
		while (q <= r && a[q] < rt) q ++;
	}
	dfs (l+1, p-1, mir);
	dfs (p, q-1, mir);
	v.push_back (rt); // 直接按照后续遍历的顺序保存;先dfs左右子树后再将根节点加入v中;如果中序遍历,只需要改变push_back语句与dfs语句的次序即可
}

void print () {
	puts ("YES");
	cout << v[0];
	for (int i = 1;i < v.size();i ++)
		cout << ' ' << v[i];
}

int main()
{
	int n;
	cin >> n;
	for (int i = 1;i <= n;i ++) cin >> a[i];
	
	dfs (1, n, 0);
	
	if (v.size () == n) { // 如果v中包含了n个元素,说明n个数全部加入
		print ();
		return 0;
	}
	
	v.clear ();
	dfs (1, n, 1);
	
	if (v.size() == n) print ();
	else puts ("NO");

	return 0;
}

L2-006 树的遍历 (25 分)

题解

#include<bits/stdc++.h>
using namespace std;

vector <int> v;

int a[50], b[50], n, left_val[50], right_val[50]; // left_val[x] 表示值为x的根左子树树根的值 

int dfs (int l1, int r1, int l2, int r2) { // 记忆化搜索 // [l1,r1]表示递归的后序遍历序列的索引范围,[l2,r2]表示递归的中序遍历的索引范围 
	
	if (l1 > r1 || l2 > r2) return 0; // 递归边界 
	
	int root = a[r1], p = l2;	
	while (p <= r2) { // 找到中序遍历中根所在的索引 
		if (b[p] == root) break;
		p ++;
	}
	int left_sum = p - l2; // 左子树节点数 
	left_val[root] = dfs (l1, l1+left_sum-1, l2, p-1); // left_subtree // [l1, l1+left_sum-1] 表示后序遍历序列中左子树的索引范围
	right_val[root] = dfs (l1+left_sum, r1-1, p+1, r2); // right_subtree
	return root;
}

void bfs (int x) {
	queue <int> q;
	q.push (x);
	while (q.size ()) {
		int t = q.front ();
		q.pop ();
		v.push_back (t);
		if (left_val[t]) q.push (left_val[t]);
		if (right_val[t]) q.push (right_val[t]);
	}	
}

int main()
{
	cin >> n;
	for (int i = 1;i <= n;i ++) cin >> a[i];
	for (int i = 1;i <= n;i ++) cin >> b[i];
	
	dfs (1, n, 1, n);
	
	bfs (a[n]);
	
	cout << v[0];
	for (int i = 1;i < v.size();i ++)
	cout << ' ' << v[i];

	return 0;
}

L2-011 玩转二叉树 (25 分)

#include<bits/stdc++.h>
using namespace std;
const int N = 50;

int n, a[N], b[N];
int right_subtree_root[N<<1], left_subtree_root[N<<1];

int dfs (int l1, int r1, int l2, int r2) {
	if (l1 > r1 || l2 > r2) return 0;
	
	int rt = b[l2];
	int p = l1;
	while (p <= r1 && a[p] != rt) p ++;
	
	right_subtree_root[rt] = dfs (l1, p-1, l2+1, l2+p-l1); // 镜像,dfs左子树,但是赋值给rt的右子树数组 
	left_subtree_root[rt] = dfs (p+1, r1, l2+p-l1+1, r2); // 前序遍历数组左子树和右子树索引范围的判定,是根据中序遍历得到左子树元素个数和右子树元素个数 
	return rt;
}

void bfs (int x) {
	vector <int> v;
	queue <int> q;
	q.push (x);
	while (q.size()) {
		int t = q.front ();
		v.push_back (t);
		q.pop ();
		if (left_subtree_root[t]) q.push (left_subtree_root[t]); // 因为在dfs时已经进行过镜像操作了,所以这里就先左子树数组再右子树数组 
		if (right_subtree_root[t]) q.push (right_subtree_root[t]);
	}
	
	cout << v[0] ;
	for (int i = 1;i < v.size();i ++) cout << ' ' << v[i];
}

int main()
{
	cin >> n;
	for (int i = 1;i <= n;i ++) cin >> a[i]; // mid
	for (int i = 1;i <= n;i ++) cin >> b[i]; // before
	
	dfs (1, n, 1, n);
	
	bfs (b[1]);
	
	return 0;
}

L2-035 完全二叉树的层序遍历 (25 分)

充分利用了完全二叉树索引的性质,第i个节点的左孩子保存在a[2*i]中,右孩子保存在a[2*i+1]中,所以我们可以根据后续遍历递归输入。

这个方法太棒了!

#include<bits/stdc++.h>
using namespace std;
const int N = 100;

int n, tree[N];

void build (int x) {
	if (x > n) return ; 
	build (x << 1);
	build (x << 1 | 1);
	cin >> tree[x];
}

int main()
{
	cin >> n;
	build (1);	
	cout << tree[1];
	for (int i = 2;i <= n;i ++)
	cout << ' ' << tree[i];
	return 0;
}

我写的:(繁琐)

只要思想就是递归确定左子树和右子树元素个数,左子树元素个数就是左子树完美时的元素个数-左子树缺少的元素个数,缺少的元素个数主要看根节点的右子树,也就是该左子树的兄弟子树,如果整个树缺少元素的个数大于右子树完美时最后一层的元素个数,说明左子树也缺少元素了,缺少的元素个数就是二者的差值。

#include<bits/stdc++.h>
using namespace std;
const int N = 100;
vector <int> v;
queue <int> q;
int n, a[N];
int left_subtree_root[N<<1], right_subtree_root[N<<1];

int dfs (int l, int r) {
	if (l > r) return 0;
	
	int num = r-l+1;
	int dp = int (log2(num)); // 从0开始
	int lack = (1 << (dp+1)) - 1 - num; // 相较于完美二叉树,此完全二叉树最后一层缺多少个节点
	int last_layer_num = (1<<dp); // 深度为dp的树的最后一层最多元素个数 
	int left_subtree_num = (1<<dp) - 1 - max (0, lack - last_layer_num/2); // 该子树的左子树元素个数 
	
	left_subtree_root[r] = dfs (l, l + left_subtree_num - 1);
	right_subtree_root[r] = dfs (l + left_subtree_num, r-1); 
	return r;
}

void layer_order (int x) {
	q.push (x);
	while (q.size()) {
		int t = q.front ();
		q.pop ();
		v.push_back (a[t]);
		if (left_subtree_root[t]) q.push(left_subtree_root[t]);
		if (right_subtree_root[t]) q.push(right_subtree_root[t]);
	}
	
	cout << v[0];
	for (int i = 1;i < v.size();i ++)
		cout << ' ' << v[i];
}

int main()
{
	cin >> n;
	for (int i = 1;i <= n;i ++) cin >> a[i];
	
	dfs (1, n);
	
//	for (int i = 1;i <= n;i ++) cout << left_subtree_root[i] << ' ' <<right_subtree_root[i] << endl;
	
	layer_order (n);
	
	return 0;
}

L3-010 是否完全二叉搜索树 (30 分)

搜索二叉树插入元素的过程:

  1. 树空,则插入到根节点位置;
  2. 树非空,与根节点比较,如果大于根节点的值则递归进入右子树,否则进入左子树。
#include<bits/stdc++.h>
using namespace std;
const int N = 100;

int n, x, cnt;
int tr[N];

int main()
{
	cin >> n;
	for (int i = 1;i <= n;i ++) {
		cin >> x;
		int p = 1;
		while (tr[p] != 0) {
			if (x > tr[p]) p = (p << 1);
			else p = (p << 1 | 1);
		}
		tr[p] = x;
	}	
	
	for (int i = 1; ;i ++) {
		if (tr[i]) {
			cnt ++;
			if (cnt == 1) cout << tr[i];
			else cout << ' ' << tr[i];
		}
		if (cnt == n) {
			cout << endl;
			if (i == n) puts ("YES");
			else puts ("NO");
			return 0;
		}
	}
		
	return 0;
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

二叉树的前序遍历、中序遍历、后续遍历和层序遍历 的相关文章

随机推荐

  • Raspberry Pi和Python OpenCV人工神经网络和卷积神经网络演示及其机器学习微型框架

    首先 主要讨论和演示机器学习中使用的基本数据模型及其演示 其次开始的深度学习讨论 然后 探讨 ANN 和 CNN 如何预测结果 例如 当呈现未知图像时 CNN 将尝试将其识别为属于它已被训练识别的类别之一 Raspberry Pi机器学习
  • 十三、Ubuntu18.04下配置C++版本的mediapipe

    十三 Ubuntu18 04下配置C 版本的mediapipe 1 官方教程 2 记录我的配置过程 2 1 安装Bazelisk 2 2 安装mediapipe库 2 3 安装OpenCv和FFmpeg 2 4 运行helloworld C
  • Airtest简单使用及采坑记录

    下载地址 http airtest netease com 打开方式 打开下载的文件夹 找到AirtestIDE exe双击即可打开 连接手机 USB连接方式 将电脑与手机用USB连接 打开手机开发者模式的USB调试 右上角出现设备信息后点
  • 【云原生之Docker实战】使用docker搭建Chemex资产管理系统

    云原生之Docker实战 使用docker搭建Chemex资产管理系统 一 Chemex介绍 1 Chemex简介 2 Chemex特点 二 检查dokcer版本 三 创建mysql容器 四 测试数据库连接 五 下载chemex镜像 六 创
  • 让AD 自动导出 3D效果照片到项目文件路径下,方便查看

    让AD自动在项目目录下生成PCB的3D照片 分辨率 设为最高 视图可以自定义或者从上到下俯视 颜色配置默认绿色 也可以选择当前视图 确定即可 这样查看起来非常方便 不用再打开文件查看了
  • 数据库设计(一对一,一对多,多对多)关联查询

    表与表之间的关系 1 一对一 需要两个表 当然做项目时为了省空间 通常只建一个表 如果要实现一对一的查询 可以建两个视图 示例如下 1 建物理表 初始化数据 CREATE TABLE person id INT NAME VARCHAR 1
  • 什么是CSMA/CD

    英文全称 Carrier Sense Multiple Access Collision Detection 载波侦听多路访问 冲突检测协议 CSMA CD 这种协议已广泛应用于局域网中 是广播型信道中采用一种随机访问技术的竞争型访问方法
  • windows下更改鼠标滚轮方向

    本来鼠标滚轮的方向无所谓 正确 与否 win下和mac下方向相反 只要习惯即可 但从win下切换到mac后 本来是想把鼠标方向调成跟win下一致 结果这么一反转 连多指手势的 左右 都反了 苹果 算你狠 于是我只有习惯所谓的 自然 滚动 习
  • 二维数组定义

    二维数组定义 1 方法一 int a new int m for int i 0 i
  • XD插件PhotoSplash2的用法

    1 安装 略 2 在画布上插入5个矩形 3 全部选中 并点击插件photosplash2 4 查询框中输入 flower 自动按照选中的矩形数量 选择照片 按 Apply 5 photos 5 效果
  • 如何面试Python 后端工程师(持续更新)

    看到 如何面试Python后端工程师 这个问题下一位大牛罗列的问题 感觉挺有价值 现在记在这里 找出这些问题的答案 持续更新 一 语言 1 推荐一本看过最好的python书籍 拉开话题好扯淡 目前所知道的 看过的就是 Python 核心编程
  • drop、truncate和delete的区别

    drop truncate和delete的区别 1 DELETE语句执行删除的过程是每次从表中删除一行 并且同时将该行的删除操作作为事务记录在日志中保存以便进行进行回滚操作 TRUNCATE TABLE 则一次性地从表中删除所有的数据并不把
  • 直接插入排序(C)

    直接插入排序 算法描述 所谓直接插入排序 就是从插入第1个数值开始 存在第0位 直至插入第n个数值 当插入第n个数值时 前面n 1个数值已经是排好序的 插入完第n个数值时排序结束 假设 数据集合为N 有n个数据 i 1 为第1个数值 第一步
  • 关于Qt 中update()和repaint()的区别

    void QWidget repaint int x int y int w int h bool erase TRUE 槽 通过立即调用paintEvent 来直接重新绘制窗口部件 如果erase为真 Qt在paintEvent 调用之前
  • RPM安装和卸载

    rpm 是redhat公司出的一个包管理工具 redhat package manager由于我们这是虚拟机 它有光驱 我们可以把光驱挂载一下mount dev cdrom mnt cd mnt lscd packages 这个目录下红色的
  • 支付宝数字化经营能加盟吗?真实情况原来是这样!(深度好文)

    去年支付宝的刷脸支付之火相信大家都知道 项目是个好项目 就是被那批做微商会销的人玩坏了 他们硬是把刷脸支付玩成了一个传销骗局 导致现在人家一说刷脸支付创业项目 就说是个骗局 连正规公司都受到了牵连 典型的一粒老鼠屎坏了锅粥 虽然刷脸支付肯定
  • Pygame 官方文档 - pygame.key

    pygame key 与键盘相关的 Pygame 模块 pygame key get focused 当窗口获得键盘的输入焦点时返回 True pygame key get pressed 获取键盘上所有按键的状态 pygame key g
  • c++复制省略

    复制省略问题 问题背景 工作背景 在工作过程中间 由于团队已经使用gcc7编译器并且支持c 17标准的使用 我们在大量代码内使用了tuple结合结构化绑定的代码来替代之前的返回结构体的模式 使用引用传递出参的模式 下面是几个模式的案例 返回
  • 虚拟服务器共用,vm共享虚拟主机(vmware共享的虚拟机)

    共享虚拟机 是网络中有多台VMware Workstation 在其中启用 共享虚拟机 功能后 假设这台主机为A 其他安装VMware Workstation 的主机 假设主机为B 1 使用共享文件夹 不稳定 容易保存失败2 电脑A扩展屏幕
  • 二叉树的前序遍历、中序遍历、后续遍历和层序遍历

    题目 L2 004 这是二叉搜索树吗 25 分 L2 006 树的遍历 25 分 L2 011 玩转二叉树 25 分 L2 035 完全二叉树的层序遍历 25 分 L3 010 是否完全二叉搜索树 30 分 代码 L2 004 这是二叉搜索