Suppose that all the keys in a binary tree are distinct positive integers. A unique binary tree can be determined by a given pair of postorder and inorder traversal sequences. And it is a simple standard routine to print the numbers in level-order. However, if you think the problem is too simple, then you are too naive. This time you are supposed to print the numbers in “zigzagging order” – that is, starting from the root, print the numbers level-by-level, alternating between left to right and right to left. For example, for the following tree you must output: 1 11 5 8 17 12 20 15.
Input Specification:
Each input file contains one test case. For each case, the first line gives a positive integer N (≤30), the total number of nodes in the binary tree. The second line gives the inorder sequence and the third line gives the postorder sequence. All the numbers in a line are separated by a space.
Output Specification:
For each test case, print the zigzagging sequence of the tree in a line. All the numbers in a line must be separated by exactly one space, and there must be no extra space at the end of the line.
Sample Input:
8
12 11 20 17 1 15 8 5
12 20 17 11 15 8 5 1
Sample Output:
1 11 5 8 17 12 20 15
My Analysis:
· 树的 inorder+preorder / inorder+postorder可以唯一确定一个树。(如果节点各不相同)
· 整个树的inorder/preorder/postorder序列都分别具有自相似性。
以postorder+inorder为例,构造方法是:
① postorder的最右结点一定是根结点(root标记),可以在inorder中找到这一根结点。则在inorder序列中,该根结点的左边就是左子树的inorder,右边就是右子树的inorder。
※ 这两个子树的inorder序列具有与整个树的inorder序列完全相似的结构。
※ postorder的倒数第二节点一定是右子树的根节点。它向左带领着右子树的一系列点,为右子树的postorder。再向左是左子树的根节点带领着左子树的postorder。我们不知道两子树的分界在哪,但是我们知道的是每次左移root标记(至下一层右子树的根节点),两束递归会恰好解决问题。
② 为了使用递归,假设已经获得GetTree函数:
Node* GetTree(int* postorder, int* inorder, int start, int end)
该函数可以返回inorder[start:end]的子串所对应的树。
③ 对传入子树的右左两子树都调用该函数(先右后左),可得到右左两子树。加上当前根节点,再拼出当前子树,返回;添加出口:start > end;即完成该递归函数。
My answer:
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#define _CRT_SECURE_NO_DEPRECATE
#define QUEUE_MAX_SIZE 31
#define NOT_FOUND -999
typedef struct node{
int Element;
struct node* Left;
struct node* Right;
struct node* next;
}Node;
Node* GetTree(int* inorder, int* postorder, int start, int end);
int Zigzagorder(Node* t, int** a);
int Rec_GetLevel(Node* base_node, int base_level, Node* target);
bool enqueue(Node* a);
Node* dequeue();
bool IsEmpty();
bool IsFull();
Node* queue[QUEUE_MAX_SIZE];
int front = 0;
int rear = - 1;
int root; //postorder的当前根的索引
int main(void)
{
int N, i, j, start, end, height;
int postorder[31], inorder[31];
Node* t;
scanf("%d", &N);
for (i = 0; i <= N-1; i++) {
scanf("%d", &inorder[i]);
}
root = N - 1;
int** a = (int**)malloc(N * sizeof(int*)); //建立二维数组
for (i = 0; i <= N - 1; i++) { //准备存入树的各层数据
a[i] = (int*)malloc(N * sizeof(int));
}
for (i = 0; i <= N - 1; i++) {
scanf("%d", &postorder[i]);
}
start = 0; end = N - 1;
t = GetTree(postorder, inorder, start, end);
height = Zigzagorder(t, a);
for (i = 0; i <= height - 1; i++) {
if (i % 2 == 0)
for (j = a[i][0]; j >=1 ; j--) {
if (j == 1 && i == height - 1) printf("%d", a[i][j]);
else printf("%d ", a[i][j]);
}
else
for (j = 1; j <= a[i][0]; j++) {
if (j == a[i][0] && i == height - 1) printf("%d", a[i][j]);
else printf("%d ", a[i][j]);
}
}
return 0;
}
int Zigzagorder(Node* t, int** a)
{
Node* cur_node;
int level, i = 0, old_level = -1;
enqueue(t);
while (!IsEmpty()) {
cur_node = dequeue();
level = Rec_GetLevel(t, 1, cur_node);
if (level != old_level) { //每当开始新的一层 level层 对应a[level-1]
old_level = level;
if (level != 1) a[level - 2][0] = i - 1; //在a[level-2][0]处填上一层的节点数
i = 1; //每层节点内容从a[level-1][1]开始存
}
a[level - 1][i++] = cur_node->Element; //将树对应的内容存入二维数组
if(cur_node->Left!=NULL) enqueue(cur_node->Left);
if (cur_node->Right != NULL) enqueue(cur_node->Right);
}
//给最后一层赋a[][0]的值(节点总数)
level++;
a[level - 2][0] = i - 1;
return level - 1; //返回树的高度
}
int Rec_GetLevel(Node* base_node, int base_level, Node* target)
{
if (base_node == NULL)return NOT_FOUND;
if (target == base_node)return base_level;
int level_from_left, level_from_right;
level_from_left = Rec_GetLevel(base_node->Left, base_level + 1, target);
if (level_from_left != NOT_FOUND)return level_from_left;
level_from_right = Rec_GetLevel(base_node->Right, base_level + 1, target);
if (level_from_right != NOT_FOUND)return level_from_right;
return NOT_FOUND;
}
//由postorder和inoreder得到树
//其中用到root全局变量 已在前方定义 其初始在postorder末尾
//start、end为inorder序列起末索引 为了递归函数的一般性
Node* GetTree(int* postorder, int* inorder, int start, int end)
{
if (start > end)return NULL; //出口判断尽量往前放
//开始你把它放在变量定义之后
//造成了神秘的malloc溢出错误
int root_val = postorder[root--];
int i;
Node* RightSubtree, *LeftSubtree;
Node* current = (Node*)malloc(sizeof(Node));
for (i = start; i <= end; i++) {
if (inorder[i] == root_val)break;
}
RightSubtree = GetTree(postorder, inorder, i + 1, end);
LeftSubtree = GetTree(postorder, inorder, start, i - 1);
current->Right = RightSubtree;
current->Left = LeftSubtree;
current->Element = root_val;
return current;
}
bool enqueue(Node* a)
{
if (IsFull())return false;
rear = (rear + 1) % QUEUE_MAX_SIZE;
queue[rear] = a;
return true;
}
Node* dequeue()
{
if (IsEmpty())return NULL;
Node* ret = queue[front];
front = (front + 1) % QUEUE_MAX_SIZE;
return ret;
}
bool IsEmpty()
{
if (front == (rear + 1) % QUEUE_MAX_SIZE)return true;
else return false;
}
bool IsFull()
{
if (front == (rear + 2) % QUEUE_MAX_SIZE)return true;
else return false;
}