树-PTA-蛇形输出树[由中序后序构造树][递归求节点层数]

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;
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值