6-3 jmu-ds-表达式树 (25 分)

  • 输入一行中缀表达式,转换一颗二叉表达式树,并求解.
  • 表达式只包含+-*/运算符,操作数只有一位,且为整数(有兴趣同学可以考虑负数小数,两位数做法)。按照先括号,再乘除,后加减的规则构造二叉树。
  • 如图所示是"1+(2+3)*2-4/5"代数表达式对应二叉树,用对应的二叉树计算表达式的值。
    转换二叉树如下:

###输入要求
输入一行字符串
###输出要求
输出结算结果,如遇到除0,提示divide 0 error!

函数接口定义:

void InitExpTree(BTree &T,string str) ; //建表达式的二叉树
double EvaluateExTree(BTree T);//计算表达式树

T:二叉树
str:输入的表达式

裁判测试程序样例:

#include<iostream>
#include<string>
#include<stack>
using namespace std;
typedef struct BiTNode{                             //二叉树的二叉链表存储表示
    char data;
    struct BiTNode *lchild,*rchild;
}BTNode,*BTree;
void InitExpTree(BTree &T,string str) ; //建二叉表达式树 
double EvaluateExTree(BTree T);//计算表达式树 
char Precede(char t1,char t2) ;//比较t1,t2运算符优先级函数 
int In(char c) ;//判断c是否运算符 
void CreateExpTree(BTree &T,BTree a,BTree b,char ch);//建简单二叉树 
void DestroyBTree(BTree bt);//销毁树 
int main() 
 {
   string str;
   BTree T;
   getline(cin,str);
   InitExpTree(T,str);          //创建表达式树
   cout<<EvaluateExTree(T);             //输出值
   DestroyBTree(T);
   return 0;
 }
char Precede(char t1,char t2) 
 { /*判断两符号的优先关系 */
    char f;
    switch(t2)
    {
        case '+': if(t1=='('||t1=='#')  f='<';
                  else  f='>';
                  break;
        case '-': if(t1=='('||t1=='#')  f='<';
                  else  f='>';
                  break;
        case '*':if(t1=='*'||t1=='/'||t1==')') f='>';
                 else f='<';
                 break;
    case '/':if(t1=='*'||t1=='/'||t1==')') f='>';
                     else  f='<';
                     break;
        case '(': if(t1!=')')  f='<';
                    break;
        case')': if(t1=='(') f='=';
        else f='>';
           break;
    case'#':  if(t1=='#') f='=';
             else f='>';
   }
    return f;
 }
int In(char c) 
 { /* 判断c是否为运算符 */
   switch(c)
   {
      case '+':
      case'-':
      case'*':
      case '/':
      case'#':
      case '(':
      case')':return 1;break;
      default:return 0;
   }
 }
void CreateExpTree(BTree &T,BTree a,BTree b,char ch)
{           //简单二叉树的创建
    T=new BTNode;
    T->data=ch;
    T->lchild=a;
    T->rchild=b;
}
void DestroyBTree(BTree bt)//销毁树
{
    if(bt!=NULL)
    {
      DestroyBTree(bt->lchild);
      DestroyBTree(bt->rchild);
      delete bt;    
    }
}
/* 请在这里填写答案 */

输入样例:

1+2*3

输出样例:

7

这题涉及的知识点比较多

思路:

输入str=1+(2+3)*2-4/5

中序in=1+2+3*2-4/5(对应是表达树的中序遍历)

后序la=123+2*+45/-(对应树的后序遍历)

然后中序后序求表达树

计算树就是后序遍历尾递归结果求值。

除数是0就exit(0);

代码里面有测试代码,去掉注释可以看过程。

 

 

#include<iostream>
#include<string>
#include<stack>
using namespace std;
typedef struct BiTNode {                             //二叉树的二叉链表存储表示
    char data;
    struct BiTNode* lchild, * rchild;
}BTNode, * BTree;


//---------------------------------------------------//
#include<bits/stdc++.h>
#define node BiTNode
#define x data
#define lc lchild
#define rc rchild
//必须吐槽集美作业
void last(node* p)//测试函数
{
    if (p)
    {
        last(p->lc);
        last(p->rc);
        cout << p->data;
    }
    else
    {
        return;
    }
}
void inorder(node* p)//测试函数
{
    if (p)
    {
        inorder(p->lc);
        
        cout << p->data;
        inorder(p->rc);
    }
    else
    {
        return;
    }
}
int in2[1000];
int la2[1000];
string str2;
void getsuf(string& s, string str)
{
    stack<char>sta;
    stack<int>sta2;
    int idx = 0;
    int cnt = 0;
    while (idx < str.size())
    {
        if (isdigit(str[idx]))
        {
            s += str[idx];
            la2[cnt] = idx;cnt++;
        }
        else if (str[idx] == '+' || str[idx] == '-')
        {
            while (!sta.empty() && sta.top() != '(')
            {
                s += sta.top();sta.pop();
                la2[cnt] = sta2.top();cnt++;sta2.pop();
            }
            sta.push(str[idx]);
            sta2.push(idx);
        }
        else if (str[idx] == '*' || str[idx] == '/' || str[idx] == '(')
        {
            sta.push(str[idx]);
            sta2.push(idx);
        }
        else if (str[idx] == ')')
        {
            while (sta.top() != '(')
            {
                s += sta.top();sta.pop();
                la2[cnt] = sta2.top();cnt++;sta2.pop();
            }
            sta.pop();
            sta2.pop();
        }
        idx++;
    }
    while (!sta.empty())
    {
        s += sta.top();sta.pop();
        la2[cnt] = sta2.top();cnt++;sta2.pop();
    }
}
string la;
string in;

int n;
int find(int num,int l,int r)
{
    for (int i = r;i >= l;i--)//因为有重复结点,要用下标确定唯一性
        if (in2[i] == num)
            return i;
}
void build(node*& now, int l, int r, int idx)//lr是中序的范围
{//中序找长度,后序找位置,idx是后序对于的字符下标

    if (l > r || idx >= n)
    {
        now = NULL;
        return;
    }
    now = new node;now->lchild = NULL;now->rchild = NULL;
    now->x = str2[la2[idx]];
   // cout << la2[idx] << endl;
    int pos = find(la2[idx],l,r);
    if (pos>r||l==r)
        return;
    int len = r - pos;
    //cout << "右" << endl;
    build(now->rc, pos + 1, r, idx + 1);
    //cout << "左" << endl;
    build(now->lc, l, pos - 1, idx + 1 + len);
    //cout << "退" << endl;
}
void InitExpTree(BTree& T, string str)
{
    str2 = str;
    T = NULL;//T->lchild = NULL;T->rchild = NULL;
    int cnt = 0;
    for (int i = 0;i < str.size();i++)
    {
        if (str[i] != '(' && str[i] != ')')
        {
            in += str[i];
            in2[cnt] = i;cnt++;
        }
    }
    getsuf(la, str);
    n = la.size();
    //cout << "suffix:" << la << endl;
    reverse(la.begin(), la.end());
    reverse(la2, la2+n);
    build(T, 0, n - 1, 0);
   // last(T);cout << endl;
   // inorder(T);cout << endl;
}
double EvaluateExTree(BTree T)
{
    if (isdigit(T->data))
    {
        //cout << "返回值:" << T->data - '0' << endl;
        return T->data - '0';
    }
    double res1 = EvaluateExTree(T->lchild);
    double res2 = EvaluateExTree(T->rchild);
   // cout << "计算:" <<res1<< T->data <<res2<< endl;
    if (T->data == '+')
        return res1 + res2;
    else if (T->data == '-')
        return res1 - res2;
    else if (T->data == '*')
        return 1.0 * res1 * res2;
    else if (T->data == '/')
    {
        if (res2 == 0)
        {
            cout << "divide 0 error!";
            exit(0);
        }
        return 1.0 * res1 / res2;
    }


}
#undef node 
#undef x 
#undef lchild 
#undef rchild 


//---------------------------------------------------//
int main()
{
    string str;
    BTree T;
    getline(cin, str);
    InitExpTree(T, str);          //创建表达式树
    cout << EvaluateExTree(T);             //输出值
    return 0;
}
char Precede(char t1, char t2)
{ /*判断两符号的优先关系 */
    char f;
    switch (t2)
    {
    case '+': if (t1 == '(' || t1 == '#')  f = '<';
            else  f = '>';
        break;
    case '-': if (t1 == '(' || t1 == '#')  f = '<';
            else  f = '>';
        break;
    case '*':if (t1 == '*' || t1 == '/' || t1 == ')') f = '>';
            else f = '<';
        break;
    case '/':if (t1 == '*' || t1 == '/' || t1 == ')') f = '>';
            else  f = '<';
        break;
    case '(': if (t1 != ')')  f = '<';
        break;
    case')': if (t1 == '(') f = '=';
           else f = '>';
        break;
    case'#':  if (t1 == '#') f = '=';
           else f = '>';
    }
    return f;
}
int In(char c)
{ /* 判断c是否为运算符 */
    switch (c)
    {
    case '+':
    case'-':
    case'*':
    case '/':
    case'#':
    case '(':
    case')':return 1;break;
    default:return 0;
    }
}
void CreateExpTree(BTree& T, BTree a, BTree b, char ch)
{           //简单二叉树的创建
    T = new BTNode;
    T->data = ch;
    T->lchild = a;
    T->rchild = b;
}
void DestroyBTree(BTree bt)//销毁树
{
    if (bt != NULL)
    {
        DestroyBTree(bt->lchild);
        DestroyBTree(bt->rchild);
        delete bt;
    }
}
/* 请在这里填写答案 */

 

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值