文章目录
问题描述 :
内容:(1)请参照链表的ADT模板,设计二叉树并逐步完善的抽象数据类型。(由于该环境目前仅支持单文件的编译,故将所有内容都集中在一个源文件内。在实际的设计中,推荐将抽象类及对应的派生类分别放在单独的头文件中。参考教材、课件,以及网盘中的链表ADT原型文件,自行设计二叉树的ADT。)
注意:二叉树ADT的基本操作的算法设计很多要用到递归的程序设计方法。
(2)ADT的简单应用:使用该ADT设计并实现若干应用二叉树的算法设计。
应用:要求设计一个算法,将表达式二叉树转换成原始的中缀表达式(括号恢复)。二叉树的存储结构的建立参见二叉树应用1。
注意:假定输入的中缀表达式为合法的表达式。仅考虑有小括弧的场合。运算符包括+、-、*、/,运算数为整数(不局限于个位数)。
参考函数原型:
(1)表达式二叉树转换成中缀式 (外壳部分,用户函数)
//表达式二叉树转换成中缀式
template<class ElemType>
void BianryTree_Infix(BinaryTree<ElemType> &T, string &inffix); //inffix:转换获得的中缀表达式字符串
(2)表达式二叉树转换成中缀式 (递归部分,用户函数)
//表达式二叉树转换中缀表达式
template<class ElemType>
void BianryTree_Infix_Cursive(BinaryTreeNode<ElemType> *root, string &inffix);
辅助函数:
(1)判断是否为运算符(用户函数)
//判断是否为运算符
bool isoperator( char op ){
switch(op){
case '+':
case '-':
case '*':
case '/':
case '(':
case ')':
return true;
default:
return false;
}
}
(2)求运算符的优先级(用户函数)
//求运算符的优先级
int getOperPri(char op)
{
switch(op)
{
case '(':
return 1; break;
case '+':
case '-':
return 2; break;
case '*':
case '/':
return 3; break;
default:
return 0;
}
}
输入说明 :
第一行:表示无孩子或指针为空的特殊分隔符
第二行:二叉树的先序序列(结点元素之间以空格分隔)
输出说明 :
第一行:中缀表达式字符串(不带空格)
输入范例 :
#
* - + + 12 # # 14 # # 3 # # / 400 # # / 30 # # * 10 # # 5 # # 62 # #
输出范例 :
(12+14+3-400/(30/(10*5)))*62
思路分析
-
这和那个后序遍历生成二叉树,然后转成带括号的中缀式不是很像吗?传送门
-
所以先把那个代码拿过来跑一下!
效果如下
实际答案
- 显而易见的,±*/四个符号不是都满足交换律的,所以针对不满足交换律的减法和除法,要给它一个方向性
- 根据上图可以看出,如果是只要是减法或者乘法的右子树是与其优先级同样的,或者比其低的,都要加括号,这就很好办了
代码实现
bool InOrderRur(BinaryTreeNode *root,bool (*visit)(BinaryTreeNode *temp)){
if(root) {
char temp=' ',left= ' ',right=' ';
if(root->GetLChild() &&root->GetRChild()){
temp = root->getData().at(0);
left = root->GetLChild()->getData().at(0);
right = root->GetRChild()->getData().at(0);
}
if(isoperator(left)
&& getOperPri(left)<getOperPri(temp)){
cout<<"(";
InOrderRur(root->GetLChild(),visit2);
cout<<")";
}
else{
InOrderRur(root->GetLChild(),visit2);
}
visit2(root);
if(isoperator(right)
&& getOperPri(right)<getOperPri(temp)){
cout<<"(";
InOrderRur(root->GetRChild(),visit2);
cout<<")";
}else if((temp == '-' && isoperator(right)) &&(getOperPri(temp) >= getOperPri(right))){
cout<<"(";
InOrderRur(root->GetRChild(),visit2);
cout<<")";
}else if(temp == '/' && isoperator(right)){
cout<<"(";
InOrderRur(root->GetRChild(),visit2);
cout<<")";
}
else{
InOrderRur(root->GetRChild(),visit2);
}
return true;
}
return false;
}
事故现场
第一次提交
- 谁能跟我讲发生了什么?卧槽,这道题是难度为难的题目吗?给我高兴坏了,真的高兴坏了!肯定是老师看错了,绝对的!!!
分析与总结
- 还是一开始出发的思路找对了,后面就好做了。除此之外,自己要在纸上想好大概的思路,再去完成,不是啥都没有就开始做的。
- 关于很多数字的细节问题,如果一瞬间想不清楚,就不要想,上机debug看出所有的变化,直接找出临界值就行。