IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> 信息学奥赛一本通 1368:对称二叉树(tree_c) -> 正文阅读

[C++知识库]信息学奥赛一本通 1368:对称二叉树(tree_c)

【题目链接】

ybt 1368:对称二叉树(tree_c)
根据测试,可以认为输入的序列长度小于等于500

【题目考点】

1. 二叉树 顺序存储结构

  • 第1结点为树的根结点
  • 第i结点的左孩子编号为2i,右孩子编号为2i+1
  • 第i结点的双亲结点编号为i/2(整除运算)。
    设数组tree,tree[i]表示第i结点的值。
    适合存储满二叉树与完全二叉树

【解题思路】

题目给的输入的序列是二叉树的顺序存储结构,
设数组tree,tree[i]表示用顺序存储结构保存二叉树第i结点的值。
那么输入的第i个字符就是tree[i]的值。
这里可以使用每次循环读入一个字符的方法,当读入EOF时停止读入。也可以先读入整个字符串,再做赋值。为tree数组设值。
设标志位isSym表示该树是否是对称的。
遍历整棵树(使用哪种遍历方法都可以),看每个结点的左右孩子,如果左右孩子中有1个是空结点而另一个不是,那么整棵树就不是对称的。遍历完所有结点后,可以确定该树是否是对称的。
注意在遍历顺序存储结构的树的时候,临时求出的下标可能会很大(因为每次都会乘以2),所以数组尽量开得大一些(比如最后一个结点的地址是1000,那么要把数组长度开成2000多),也可以先记录整个顺序存储结构tree数组中最后一个元素的下标tn,如果访问到的下标超过tn,那么这次访问无意义,直接返回。

本题也可以使用链式存储结构完成。题目给定的顺序存储结构字符序列,实际就是树的带空结点的层次遍历序列。可以模拟层次遍历的过程来设置结点间的关系。

在遍历时,以先序遍历为例,如果使用递归的方法做遍历,那么需要把表示该树是否对称的量声明成全局变量。如果使用非递归的方法做遍历,就可以使用函数的返回值来表示该树是否对称,效率更高。

【题解代码】

解法1:顺序存储结构 递归

#include <bits/stdc++.h>
using namespace std;
#define N 1005
char tree[N];//树的顺序存储结构,初值都为'\0',tree[i]:第i结点的值,如果为'\0'表示这里为空。
//tree[2*i]:第i结点的左孩子的值,tree[2*i+1]:第i结点右孩子的值
int tn;//tree数组最后一个元素的下标,应该保证N > 2*tn 
bool isSymmetric(int r)//判断以r为根结点的树是否是对称的 
{
	if(tree[r] == '\0')//如果遍历到空结点,那么是对称的 
		return true;
	if(tree[2*r] == '\0' && tree[2*r+1] != '\0' || 
		tree[2*r] != '\0' && tree[2*r+1] == '\0')//如果左子树空但右子树不空,或右子树空但左子树不空 
		return false;
	return isSymmetric(2*r) && isSymmetric(2*r+1);//左右子树都是对称的,该树才是对称的 
}
int main()
{
	char c;
	while((c = cin.get()) != EOF)//二叉树的顺序存储结构字符串读入tree 
	{
		if(c == '#' || c == '\n')//遇到'#'或换行符,都转为0 
			tree[++tn] = '\0';
		else
			tree[++tn] = c;
	}
	cout << (isSymmetric(1) ? "Yes" : "No");
	return 0;
} 

解法2:顺序存储结构 递归先序遍历

#include <bits/stdc++.h>
using namespace std;
#define N 105
char tree[N];//树的顺序存储结构,初值都为'\0',tree[i]:第i结点的值,如果为'\0'表示这里为空。
//tree[2*i]:第i结点的左孩子的值,tree[2*i+1]:第i结点右孩子的值
int tn;//tree数组最后一个元素的下标 
bool isSym = true;//是否对称 
void preOrder(int r)
{
	if(r > tn || tree[r] == '\0' || isSym == false)//如果超出了有效下标范围,或遍历到空结点,或已经确定是不对称的了,那么不用再遍历了 
		return;
	if(tree[2*r] == '\0' && tree[2*r+1] != '\0' || 
		tree[2*r] != '\0' && tree[2*r+1] == '\0')//如果左子树空但右子树不空,或右子树空但左子树不空 
	{
		isSym = false;//不对称
		return;
	}
	preOrder(2*r);//遍历左子树
	preOrder(2*r+1);//遍历右子树 
}
int main()
{
	char c;
	while((c = cin.get()) != EOF)//二叉树的顺序存储结构字符串读入tree 
	{
		if(c == '#' || c == '\n')//遇到'#'或换行符,都转为0 
			tree[++tn] = '\0';
		else
			tree[++tn] = c;
	}
	preOrder(1);
	cout << (isSym ? "Yes" : "No");
	return 0;
} 

解法3:链式存储结构 非递归先序遍历

#include <bits/stdc++.h>
using namespace std;
#define N 1005
struct Node
{
	char val;
	int left, right;
};
Node node[N];
int p;
string s;
int si;
int createTree()
{
	char c;
	queue<int> que;
	int np = ++p, lp, rp;
	node[np].val = s[si++];
	que.push(np);
	while(que.empty() == false)
	{
		int u = que.front();
		que.pop();
		c = s[si++];//如果已经取到末尾,c为'#',否则c取s[si] 
		if(c == '#' || si == s.length())
			lp = 0;
		else
		{
			lp = ++p;
			node[lp].val = c;
		}
		c = s[si++];
		if(c == '#' || si == s.length())
			rp = 0;
		else
		{
			rp = ++p;
			node[rp].val = c;
		}
		node[u].left = lp;
		node[u].right = rp;
		if(si < s.length())//如果没有遍历完,那么新结点入队 
		{
			que.push(lp);
			que.push(rp);
		}
	}
	return np;
}
bool isSymmetric(int r)//非递归先序遍历 判断以r为根结点的树是不是对称的 
{
	stack<int> stk;
	stk.push(r);
	while(stk.empty() == false)
	{
		int u = stk.top();
		stk.pop();
		if(node[u].left == 0 && node[u].right != 0 ||
			node[u].left != 0 && node[u].left == 0)
			return false;
		if(node[u].right != 0)
			stk.push(node[u].right);
		if(node[u].left != 0)
			stk.push(node[u].left);
	}
	return true;
}
int main()
{
	cin >> s;
	int root = createTree();
	cout << (isSymmetric(root) ? "Yes" : "No");
	return 0;
}
  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2022-11-05 00:06:35  更:2022-11-05 00:08:40 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/19 5:06:39-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码