题目
题目来源牛客网:https://www.nowcoder.com/practice/4b91205483694f449f94c179883c1fef?tpId=60&&tqId=29483&rp=1&ru=/activity/oj&qru=/ta/tsing-kaoyan/question-ranking
描述
编一个程序,读入用户输入的一串先序遍历字符串,根据此字符串建立一个二叉树(以指针方式存储)。 例如如下的先序遍历字符串: ABC##DE#G##F### 其中“#”表示的是空格,空格字符代表空树。建立起此二叉树以后,再对二叉树进行中序遍历,输出遍历结果。
输入描述:
输入包括1行字符串,长度不超过100。
输出描述:
可能有多组测试数据,对于每组数据, 输出将输入字符串建立二叉树后中序遍历的序列,每个字符后面都有一个空格。 每个输出结果占一行
核心思路
1.首先把树创建出来
只要这个树的前序包含树的所有元素(空节点也在内)便能复原整颗树
前序:根、左子树、右子树
创建树的过程
先建立根,前序遍历的第一个数据就是树的根
再创建根的左孩子,只要没遇到空,就一直创建左孩子(根的左孩子,根的左孩子的左孩子,这样一直创建下去)
根的左子树全部创建完后,就开始创建根的右孩子,然后开始创建右子树
遇到空了说明该节点的左孩子为空,接来下就该节点创建右孩子
创建完后,如果右孩子还有孩子,就先创建左孩子
如果没有则返回创建上一层的右孩子,如果上一层的右孩子还有孩子,就先创建左孩子
如果左孩子还有孩子,就先创建左孩子的左孩子,左孩子的左子树全部创立完后,再创建右孩子
如果没有就直接创建右孩子
创建右孩子后,如果右孩子还有孩子就先创建以右孩子为根节点的左右子树,如果右孩子没有孩子了再创建上一层的右孩子。
由上面构建树的过程我们可以知道,最核心的思路便是先构建根,再构建左子树,最后构建右子树,按这样的思路一层一层递归下去
2.树创建完成后再打印树的中序
中序:左子树、根、右子树
中序输出:先输出左子树,如果左子树全部输出完毕,再输出根,如果根全部输出完毕,再输出右子树。
根的左子树又可以划分为根,左子树,右子树。
根的右子树又可以划分为根、左子树、右子树。
所以可以一层一层递归下去不断输出,直到达到终止条件
中序输出:#c#b##egd#f#a#
代码
#include <stdio.h>
#include <stdlib.h>
typedef char BTDatatype;
struct TreeNode
{
BTDatatype val;
struct TreeNode* left;
struct TreeNode* right;
};
//建树的过程
struct TreeNode* CreateTree(BTDatatype* str,int* pi)
{
//为空则返回
if(str[*pi] == '#')
{
(*pi)++;
return NULL;
}
struct TreeNode* root = (struct TreeNode*)malloc(sizeof(struct TreeNode));
//先建根
root->val = str[(*pi)++];
//再建左子树
root->left = CreateTree(str,pi);
//最后建右子树
root->right = CreateTree(str,pi);
return root;
}
//输出树的中序
void InOrder(struct TreeNode* root)
{
if(root == NULL)
{
return ;
}
InOrder(root->left);
printf("%c ",root->val);
InOrder(root->right);
}
int main()
{
char str[100] = {0};
scanf("%s",str);
int i = 0;
struct TreeNode* root = CreateTree(str,&i);
InOrder(root);
return 0;
}