题意
(原题目为英文题,这里不放原题,只放题目大意)
二叉树有n个结点(结点编号为 0 ~ n-1),给出每个结点的编号,把该二叉树反转(把每个节点的左右子树进行交换),输出反转后的二叉树的层序遍历序列和中序遍历序列。反转效果如下图:
输入样例
下面的输入样例可以表示出上图左边的那棵二叉树:
- 第一行给出正整数8,表示结点个数为8;
- 下面8行按顺序分别给出结点0、1、2、3、4、5、6、7的左右结点,“-” 表示结点为空。
8
1 -
- -
0 -
2 7
- -
- -
5 -
4 6
输出样例
输出的两行分别为反转后的树的层序遍历序列和中序遍历序列。
3 7 2 6 4 0 5 1
6 5 7 4 3 2 0 1
思路
- 本题结点的编号是连续的并且结点的个数不多,因此可以使用二叉树的静态写法,即用数组的下标表示每一个结点,数组的元素为结构体node,用来存放每一个结点的左右结点。
- 本题最关键的操作就是反转二叉树。其实很简单,只需要在输入每个结点的左右子结点的时候,将左边输入的数赋值给对应node的右子结点,右边输入的数赋值给对应node的左子结点即可。
代码
#include <iostream>
#include <queue>
using namespace std;
const int maxn = 101;
int n, num = 0;
//用来标示每个下标所对应的结点是否是根结点
bool not_root[maxn] = {false};
struct node
{
int left, right;
}nodes[maxn];
//题目要求每一行输出的最后不能有空格,用该函数可以控制输出格式
void print_node(int x)
{
cout<<x;
num++;
if(num < n)
cout<<" ";
else
cout<<endl;
}
//中序遍历
void mid_order(int root)
{
if(root == -1)
return;
mid_order(nodes[root].left);
print_node(root);
inorder(nodes[root].right);
}
//层序遍历
void level_order(int root)
{
queue<int> q;
q.push(root);
while(!q.empty())
{
//取出队首元素,以访问其左右结点
int tmp = q.front();
//队首元素读取完要退出队列
q.pop();
print_node(tmp);
//下面注意要用tmp访问nodes数组,不能用root
if(nodes[tmp].left != -1) q.push(nodes[tmp].left);
if(nodes[tmp].right != -1) q.push(nodes[tmp].right);
}
}
//将输入的从字符转化为结点编号,结点为空时用-1代替
int convert(char c)
{
//将输入的 “-” 转化为整数-1
if(c == '-')
return -1;
else
//输入过的结点说明是其他结点的子结点,肯定不是根结点
not_root[c - '0'] = true;
return c - '0';
}
//寻找根结点
int find_root()
{
for(int i = 0; i < n; i++)
{
if(!not_root[i])
return i;
}
}
int main()
{
char l, r;
cin>>n;
for(int i = 0; i < n; i++)
{
cin>>l>>r;
//反转二叉树,只需要将每个结点的左右子结点互换即可
nodes[i].left = convert(r);
nodes[i].right = convert(l);
}
int root = find_root();
level_order(root);
//全局变量num是两个遍历函数共用的,第二种方式使用之前要将num重新置0
num = 0;
mid_order(root);
return 0;
}