The following is from Max Howell @twitter:
Google: 90% of our engineers use the software you wrote (Homebrew), but you can’t invert a binary tree on a whiteboard so fuck off.
Now it’s your turn to prove that YOU CAN invert a binary tree!
Input Specification:
Each input file contains one test case. For each case, the first line gives a positive integer N (≤10) which is the total number of nodes in the tree – and hence the nodes are numbered from 0 to N−1. Then N lines follow, each corresponds to a node from 0 to N−1, and gives the indices of the left and right children of the node. If the child does not exist, a - will be put at the position. Any pair of children are separated by a space.
Output Specification:
For each test case, print in the first line the level-order, and then in the second line the in-order traversal sequences of the inverted tree. There must be exactly one space between any adjacent numbers, and no extra space at the end of the line.
Sample Input:
8
1 -
- -
0 -
2 7
- -
- -
5 -
4 6
Sample Output:
3 7 2 6 4 0 5 1
6 5 7 4 3 2 0 1
题意理解
给定以序号代表结点的二叉树,输出这个二叉树的反转层序遍历和反转中序遍历
数据结构
因为n个结点用序号0到n-1代表,所以考虑用相对于链表更加简单的静态链表来实现二叉树,即一个结构体数组。
struct Node{
int left;//设置非法值为-1
int right;
}BiTree[maxn];
解题思路
- 所谓反转二叉树就是原二叉树的左右镜像
- 输入中未出现的结点便是根结点,需要设置一个数组来标记出现的结点,输入结束后遍历此数组,未被标记的结点即为根节点
- 反转二叉树的层序遍历借助STL中队列实现,相当于原二叉树的层序遍历中左右孩入队顺序对调
- 反转二叉树的中序遍历用递归方法实现,相当于对原二叉树中序遍历的左右遍历顺序对调
注意事项
- 输入的结点为一个数和符号,所以用字符保存,存入静态链表数组时注意将char型变量转换为int型。注意用scanf实现字符输入是,空格和换行符都会被%c接收。
scanf("%d", &n);
for(i = 0; i < n; i++){
getchar();
scanf("%c %c", &c1, &c2);
...
}
- 题目要求输出最后一个元素后无空格,所以最好先将结果存入数组再输出,不要在实现遍历的时候直接输出,避免复杂判断
int levelorder[maxn];
int inorder[maxn];
- 注意中序遍历的写法,递归基是结点序号为非法值-1,递归调用都要写在if语句里面
void inorderOfInvert(int Root){
int p = Root;
int left = BiTree[p].left;
int right = BiTree[p].right;
if(p!=-1){
inorderOfInvert(right);
inorder[cnt++] = p;
inorderOfInvert(left);
}
}
完整代码
#include <cstdio>
#include <queue>
using namespace std;
const int maxn = 11;
struct Node{
int left;
int right;
}BiTree[maxn];
int flag[maxn] = {0};//标志结点有无在输入的时候出现,用于找根节点
queue<int> q;
int levelorder[maxn];
int inorder[maxn];
int cnt = 0;
void leveloderOfInvert(int Root){
int left, right;
int p;
q.push(Root);
while(!q.empty()){
p = q.front();
levelorder[cnt++] = p;
q.pop();//记得出队列操作,避免死循环
left = BiTree[p].left;
right = BiTree[p].right;
if(right!=-1)//反转的层序遍历右孩先入队
q.push(right);
if(left!=-1)
q.push(left);
}
}
void inorderOfInvert(int Root){
int p = Root;
int left = BiTree[p].left;
int right = BiTree[p].right;
if(p!=-1){
inorderOfInvert(right);
inorder[cnt++] = p;
inorderOfInvert(left);
}
}
int main(){
int n;
char c1,c2;
scanf("%d", &n);
int i;
for(i = 0; i < n; i++){
getchar();
scanf("%c %c", &c1, &c2);
if(c1 != '-'){
BiTree[i].left = c1 - '0';
flag[c1-'0'] = 1;//标记此数据出现
}
else BiTree[i].left = -1;
if(c2 != '-'){
BiTree[i].right = c2- '0';
flag[c2-'0'] = 1;
}else BiTree[i].right = -1;
}
int root;
for(root = 0; root < n; root++){
if(flag[root]==0)
break;
}
leveloderOfInvert(root);
for(i = 0; i < n; i++){
if(i>0)printf(" ");
printf("%d",levelorder[i]);
}
printf("\n");
cnt = 0;//记得在两次遍历之间改变下标全局变量
inorderOfInvert(root);
for(i = 0; i < n; i++){
if(i>0)printf(" ");
printf("%d",inorder[i]);
}
return 0;
}