题目描述
根据给定的二叉树结构描述字符串,输出该二叉树按照中序遍历结果字符串。中序遍历顺序为:左子树,根结点,右子树。输入描述
由大小写字母、左右大括号、逗号组成的字符串:
1、字母代表一个节点值,左右括号内包含该节点的子节点。
2、左右子节点使用逗号分隔,逗号前为空则表示左子节点为空,没有逗号则表示右子节点
为空。
3、二叉树节点数最大不超过100。
注:输入字符串格式是正确的,无需考虑格式错误的情况。输出描述
输出一个字符串,为二叉树中序遍历各节点值的拼接结果。示例:
输入:a{b{d,e{g,h{,I}}},c{f}}
输出:dbgehiafc
一、问题分析
首先读题,仔细看描述中的内容,发现需求是
1.根据给定的二叉树结构描述字符串,输出该二叉树按照中序遍历结果字符串。
2.中序遍历顺序为:左子树,根节点,右子树。
3.输入描述:由大小写字母、左右大括号、逗号组成的字符串:
(1)字母代表一个节点值,左右括号内包含该节点的子节点。
(2)左右子节点使用逗号分隔,逗号前为空则表示左子节点为空,没有逗号则表示右子节点为空
(3)二叉树节点数最大不超过100
注:输入字符串格式是正确的,无需考虑格式错误的情况。
4.输出描述:输出一个字符串,为二叉树中序遍历各节点值的拼接结果。
二、解题思路
1.首先先确定题目的意思,
示例中的树应该是这样的
2.中序遍历(In - order Traversal)的意思是对于二叉树中的每个节点,先访问其左子树,然后访问根节点,最后访问右子树。这种方式可以按照从小到大(如果节点存储的数据是可比较大小的数值)或者某种特定的逻辑顺序来访问二叉树中的节点,具体顺序取决于节点值的排序和树的结构。
3.比如
这棵树的节点值分别为1(根节点)、2(左子节点)、3(右子节点)
按照中序遍历的规则,首先访问左子树,也就是节点2。然后访问根节点1,最后访问右子树的节点3。所以中序遍历的结果就是2、1、3。
4.再看一个稍微复杂一点的二叉树,节点值为4(根节点),左子树节点为2和1,右子树节点值为6和7,树的结构如下:
中序遍历过程:先访问左子树2,对于左子树2,又要先访问其左子树4,然后访问左子树的根节点(节点2)。接着访问整棵树根节点1。最后访问右子树3,对于右子树3,先访问其左子树(节点5),然后访问右子树的根节点(节点3)。
所以中序遍历的结果是4、2、1、5、3。
5.再来查看我们的示例中的树:
中序遍历过程:(从根节点a)先访问左子树b,对于左子树d又要先访问其左子树d,然后访问其根节点(b),然后访问b的右子树e,对于e我们又要先访问其左子树g,然后访问g的根节点e,然后访问e的右子树h,由于h没有左子树,我们访问完h之后还需要访问h的右子树I,然后我们访问b的根节点(a),然后我们访问a的右子树c,对于右子树c我们又要先访问c的左子树f,于是访问完f我们访问c
于是得到顺序dbgehiafc
6.如何读取二叉树?我们可以定义一个结构体用来表示二叉树的每一个节点
typedef struct TreeNode {
char val[20]; // 其中包含树的值
struct TreeNode* left; // 表示其左子树
struct TreeNode* right; // 表示其右子树
} TreeNode;
7.如何从输入构建二叉树?
比如示例中的输入是a{b{d, e{g,h{,I}}},c{f}}
// 我们一开始先接收整个树的根节点,然后是大括号,大括号中,逗号左边的是左子树,逗号右边的是右子树,如果逗号左边为空,证明左子树为空子树,如果没有都好,则证明右子树为空。
// 我们可以写一个buildTree函数,返回的是我们创建好的树的根节点,需要传入的参数是字符串s和s的索引值的指针(通过指针传递来更新位置)
TreeNode* buildTree(const char* s, int* idx) {
// 如果我们已经遍历到最后(遇到字符串结束符号)我们返回NULL;
if(s[*idx] == '\0') return NULL;
// 否则的话我们为树的结点分配内存,分配的内存大小就是树结点结构体的大小就可以了
TreeNode* root = (TreeNode*)malloc(sizeof(TreeNode));
// 我们定义一个temp用来存放节点名称,tempidx用来临时存放节点名的索引值
char temp[100];
int tempidx = 0;
while(isalpha(s[*idx])) {
temp[tempidx++] = s[*idx];
(*idx)++;
}
temp[tempidx] = '\0';
strcpy(root->val, temp);
// 之后我们为该节点添加左右子树,
// 如果遇到左大括号,证明我们下面可能跟了左子树,我们递归调用bulidTree函数如果没有左大括号证明我们可能没有子节点,返回
if(s[*idx] == '{') {
(*idx)++;
root->left = bulidTree(s, idx);
} else {
root->left = NULL;
return root;
}
// 如果遇到逗号,说明后面跟的是右子树
if(s[*idx] == ',') {
(*idx)++;
root->right = buildTree(s, idx);
} else {
root->right = NULL;
}
// 如果遇到右大括号,我们将索引值增加1,然后返回当前节点,
if(s[*idx] == '}') {
(*idx)++;
}
return root;
}
8.中序遍历二叉树函数
void inorderTraversal(TreeNode* root, char* result) {
if(root == NULL) return;
inorderTraversal(root->left, result);
strcat(result,root->val);
inorderTraversal(root->right,result);
}
9.我们声明一个函数用来释放二叉树占用的内存避免内存泄露
void freeTree(TreeNode* node) {
if(node == NULL) return;
freeTree(node->left);
freeTree(node->right);
free(node);
}
10.主程序
int main() {
char input[1000];
scanf("%s", input);
int idx = 0;
TreeNode* root = buildTree(input, &idx);
char result[1000] = {0};
inorderTraversal(root, result);
printf("%s\n", result);
freeTree(root);
return 0;
}
三、具体步骤
使用的语言是C
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// 首先我们定义树的节点结构
typedef struct TreeNode {
char val[100];
struct TreeNode* left;
struct TreeNode* right;
} TreeNode;
TreeNode* buildTree(const char* s, int* idx) {
// 如果我们读取到字符串末尾我们返回NULL
if(s[*idx] == '\0') return NULL;
// 为新的根节点分配内存
TreeNode* root = (TreeNode*)malloc(sizeof(TreeNode));
// 如果遇到字母,说明这是节点的名字
if(isalpha(s[*idx])) {
char temp[100];
int tempidx = 0;
while(isalpha(s[*idx])) {
temp[tempidx++] = s[*idx];
(*idx)++;
}
temp[tempidx] = '\0';
strcpy(root->val, temp);
}
// 如果遇到左大括号,证明有子节点,否则我们认为没有左子节点
if(s[*idx] == '{') {
(*idx)++;
root->left = buildTree(s, idx);
// printf("%s的左子树是%s\n", root->val, root->left->val);
} else {
// printf("%s的左子树是空\n", root->val);
root->left = NULL;
return root;
}
// 如果遇到逗号,说明有右子节点,否则我们认为没有右子节点
if(s[*idx] == ',') {
(*idx)++;
if(isalpha(s[*idx])) {
root->right = buildTree(s, idx);
}
// printf("%s的右子树是%s\n", root->val, root->right->val);
} else {
root->right = NULL;
}
// 如果遇到右大括号,证明左右子节点都已经构建好,我们将索引值向后移
if(s[*idx] == '}') {
(*idx)++;
}
return root;
}
void inorderTraversal(TreeNode* root, char* result) {
if(root == NULL) return;
inorderTraversal(root->left, result);
strcat(result, root->val);
inorderTraversal(root->right, result);
}
void freeTree(TreeNode* root) {
if(root == NULL) return;
freeTree(root->left);
freeTree(root->right);
free(root);
}
int main() {
char input[1000];
scanf("%s", input);
int idx = 0;
TreeNode* root = buildTree(input, &idx);
char result[1000] = {0};
inorderTraversal(root, result);
printf("%s\n", result);
freeTree(root);
return 0;
}