二叉树:表达式二叉树转换成中缀式(括弧处理)

84 篇文章 5 订阅
67 篇文章 2 订阅

问题描述 :

内容:(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看出所有的变化,直接找出临界值就行。
如果不妥请留言,你的关注和回复是对我最大的鼓励,谢谢!如果想立即回复,可以加扣扣651378276,一起商量学习进步!!
  • 3
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值