A1102. Invert a Binary Tree
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
1 #include<cstdio> 2 #include<iostream> 3 #include<stack> 4 #include<string.h> 5 #include<queue> 6 using namespace std; 7 typedef struct NODE{ 8 int lchild, rchild; 9 int data; 10 }node; 11 node tree[11]; 12 int N, notRoot[11] = {0,0}; 13 void postReverse(int root){ 14 if(root == -1) 15 return; 16 if(tree[root].lchild != -1) 17 postReverse(tree[root].lchild); 18 if(tree[root].rchild != -1) 19 postReverse(tree[root].rchild); 20 swap(tree[root].lchild, tree[root].rchild); 21 } 22 void levelOrder(int root, int &cnt){ 23 queue<int> Q; 24 if(root != -1){ 25 Q.push(root); 26 } 27 while(Q.empty() == false){ 28 int index = Q.front(); 29 Q.pop(); 30 cnt++; 31 if(cnt == N){ 32 printf("%d", tree[index].data); 33 }else{ 34 printf("%d ", tree[index].data); 35 } 36 if(tree[index].lchild != -1) 37 Q.push(tree[index].lchild); 38 if(tree[index].rchild != -1) 39 Q.push(tree[index].rchild); 40 } 41 } 42 void inOrder(int root, int &cnt){ 43 if(root == -1) 44 return; 45 if(tree[root].lchild != -1) 46 inOrder(tree[root].lchild, cnt); 47 cnt++; 48 if(cnt == N) 49 printf("%d", tree[root].data); 50 else printf("%d ", tree[root].data); 51 if(tree[root].rchild != -1) 52 inOrder(tree[root].rchild, cnt); 53 } 54 int main(){ 55 char c1, c2; 56 scanf("%d", &N); 57 for(int i = 0; i < N; i++){ 58 scanf("%*c%c %c", &c1, &c2); 59 if(c1 == '-'){ 60 tree[i].lchild = -1; 61 }else{ 62 tree[i].lchild = c1 - '0'; 63 notRoot[c1 - '0'] = 1; 64 } 65 if(c2 == '-'){ 66 tree[i].rchild = -1; 67 }else{ 68 tree[i].rchild = c2 - '0'; 69 notRoot[c2 - '0'] = 1; 70 } 71 tree[i].data = i; 72 } 73 int root = 0; 74 for(int i = 0; i < N; i++) 75 if(notRoot[i] == 0){ 76 root = i; 77 break; 78 } 79 int cnt = 0; 80 postReverse(root); 81 levelOrder(root, cnt); 82 printf("\n"); 83 cnt = 0; 84 inOrder(root, cnt); 85 cin >> N; 86 return 0; 87 }
总结:
1、本题要求先对二叉树进行反转(左变成右),再层序和中序输出。由于二叉树的后序遍历是先访问左右子树,再访问根节点,与逆转具有相同的性质。逆转要求在左右子树都已经逆转之后,再将这两颗子树交换位置。因此逆转二叉树可以用后序遍历实现。
2、对于给数字编号、给出每个节点的左右孩子编号的输入数据,最好使用静态二叉树。将节点都保存在一个node数组中,仅仅对数组的下标进行操作。
3、静态二叉树寻找root:使用数组notRoot坐标记,在读入节点时,如果将其孩子节点标记为notRoot。输入完毕后遍历数组寻找root节点。
4、由于%c会将上一行的 \n 读入,所以每行之前要吸收 \n, 两个字符之间还要匹配空格。可以 scanf("%*c%c %c", &c1, &c2); 其中%*c会读入一个字符,但被忽略,接收参数的是后两个。