开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 21 天,点击查看活动详情
Day50 2023/02/24
难度:简单
题目
请设计一个算法,将给定的表达式树(二叉树)转换为等价的中缀表达式(通过括号反映操作符的计算次序)并输出。例如,当下列两棵表达式树作为算法的输入时:
输出的等价中缀表达式分别为(a+b)(c(-d))和(a*b)+(-(c-d))。
示例
输入:*+a##b##*c##-#d## (图一左边二叉树的先序遍历序列)
输出:((a+b)*(c*(-d)))
说明:将二叉树表达式转化成中缀表达式的形式
思路
将一棵二叉树转化成中缀表达式只需要按照中序遍历的方式访问一遍二叉树,同时在每次访时,遍历左子树前加左括号,遍历右子树前加右括号。
关键点
- 一定要理解中缀表达式其实就等于二叉树中序遍历的序列,其中为了表示出表达式的优先级,只需要在遍历左子树前加左括号,遍历右子树前加右括号。
if (T == nullptr) return;这行代码是为了防止递归时报空指针错误。
算法实现
c++代码实现-递归法
#include <iostream>
using namespace std;
//定义二叉树节点
typedef struct BNode {
char data; // 数据域
BNode* left, *right; // 指针域
BNode(int val) : data(val), left(nullptr), right(nullptr){}; // 构造函数
} BNode, *BTree;
/**
* @function 按照先序遍历的方式创建二叉树
* @param T 结构体 表示待创建的二叉树
*/
void createBTree(BTree& T) {
char data;
cin >> data;
if(data == '#') T =nullptr;
else {
T = new BNode(data);
createBTree(T->left);
createBTree(T->right);
}
}
/**
* @function 将一颗二叉树按照中缀表达式的规则输出
* @param T 结构体 表示待转化的二叉树
*/
void BTreeToE(BTree& T) {
if (T == nullptr) return;
if (!T->left && !T->right) cout << T->data; // 判断是否为叶节点,递归出口,意味着最深层是叶节点
else {
cout << "("; // 遍历左子树之前,先输出(
BTreeToE(T->left); // 遍历左子树
cout << T->data; // 根节点
BTreeToE(T->right); // 遍历右子树
cout << ")"; // 遍历完右子树之后,输出 )
}
}
//测试一下
int main () {
BTree T;
createBTree(T);
cout << "转换成的中缀表达式为:";
BTreeToE(T);
}
- 时间复杂度 --- 遍历二叉树全部节点,其中n为二叉树节点个数
- 空间复杂度 --- 最坏情况下二叉树呈现链状,这是递归栈深度等于二叉树节点个数n
总结
- 二叉树的基本操作中充斥着大量的递归遍历的变型。