利用树求解算术表达式的值

#include <stdio.h>
#include <string.h>
#include <malloc.h>
//#include "btree.h"
#define MaxSize 100
#include<stdlib.h>
typedef struct Node
{
    char data;
    struct Node *lchild;
    struct Node *rchild;
}BTNode,*BTree;
//用s[i]到s[j]之间的字符串,构造二叉树的表示形式
BTNode *CreateTree(char s[],int i,int j)
{
    BTNode *p;
    int k,plus=0,posi;
    if (i==j) //i和j相同,意味着只有一个字符,构造的是一个叶子节点
    {
        p=(BTNode *)malloc(sizeof(BTNode)); //分配存储空间
        p->data=s[i]; //值为s[i]
        p->lchild=NULL;
        p->rchild=NULL;
        return p;
    }
    //以下为i!=j的情况
    for (k=i; k<=j; k++)
        if (s[k]=='+' || s[k]=='-')
        {
            plus++;
            posi=k; //最后一个+或-的位置
        }
        if (plus==0) //没有+或-的情况(因为若有+、-,前面必会执行plus++)
            for (k=i; k<=j; k++)
                if (s[k]=='*' || s[k]=='/')
                {
                    plus++;
                    posi=k;
                }
                //以上的处理考虑了优先将+、-放到二叉树较高的层次上
                //由于将来计算时,运用的是后序遍历的思路
                //处于较低层的乘除会优先运算
                //从而体现了“先乘除后加减”的运算法则
                //创建一个分支节点,用检测到的运算符作为节点值
                if (plus!=0)
                {
                    p=(BTNode *)malloc(sizeof(BTNode));
                    p->data=s[posi]; //节点值是s[posi]
                    p->lchild=CreateTree(s,i,posi-1); //左子树由s[i]至s[posi-1]构成
                    p->rchild=CreateTree(s,posi+1,j); //右子树由s[poso+1]到s[j]构成
                    return p;
                }
                else //若没有任何运算符,返回NULL
                    return NULL;
}

int find_split(char express[], int start, int end)
{
    int tag = -1;

if (express[start] == '(' && express[end] == ')')
    {
        ++start;
        --end;
    }

int is_in_braket = 0;
    int more_grade = 0;
    for (int i = start; i <= end; i++)
    {
        if (express[i] == '(')
            ++is_in_braket;
        else if (express[i] == ')')
            --is_in_braket;

if ((express[i] == '+' || express[i] == '-')
            && is_in_braket == 0)
        {
            more_grade = 1;
            tag = i; //无break, 找最后一个符合条件的运算符, 取顶级的+和-
        }
        else if ((express[i] == '*' || express[i] == '/')
            && more_grade == 0
            && is_in_braket == 0)
        {
            tag = i; //无break, 找最后一个符合条件的运算符
        }
    }
    return tag;
}

BTree Creat_Btree( char *express, int start, int end)
{
    BTree pTree = NULL;

if (start == end)
    {
        pTree = (BTree)malloc(sizeof(BTNode));
        pTree->data = express[start];
        pTree->lchild = NULL;
        pTree->rchild = NULL;
    }
    else
    {   //递归调用, 各自创建左右的表达式的对应二叉树
        int tag = find_split(express, start, end);
        if (tag < 0)
        {
            printf("1.invalid express, exit.\n");
            exit(-1);
        }
        else
        {
            pTree = (BTree)malloc(sizeof(BTNode));
            pTree->data = express[tag];
        }
        if (express[start] == '(' && express[end] == ')')
        {
            ++start;
            --end;
        }
        pTree->lchild = Creat_Btree(express, start, tag - 1);
        pTree->rchild = Creat_Btree(express, tag + 1, end);
    }
    return pTree;
}
double post_traverser_calc(BTree pTree)
{
    if (pTree == NULL)
        return -1;
    else if ('0' <= pTree->data &&pTree->data <= '9')
        return pTree->data - '0';
    else if(pTree->data=='+')
        return post_traverser_calc(pTree->lchild) + post_traverser_calc(pTree->rchild);
    else if(pTree->data=='-')
        return post_traverser_calc(pTree->lchild) - post_traverser_calc(pTree->rchild);
    else if(pTree->data=='*')
        return post_traverser_calc(pTree->lchild) * post_traverser_calc(pTree->rchild);
    else if(pTree->data=='/')
        return post_traverser_calc(pTree->lchild) / post_traverser_calc(pTree->rchild);
}

double CalcuValue(BTNode *b)
{
    double v1,v2;
    if (b==NULL)
        return 0;
    if (b->lchild==NULL && b->rchild==NULL) //叶子节点,应该是一个数字字符(本项目未考虑非法表达式)
        return b->data-'0'; //叶子节点直接返回节点值,结点中保存的数字用的是字符形式,所以要-'0'
    v1=CalcuValue(b->lchild); //先计算左子树
    v2=CalcuValue(b->rchild); //再计算右子树
    switch(b->data) //将左、右子树运算的结果再进行运算,运用的是后序遍历的思路
    {
    case '+':
        return v1+v2;
    case '-':
        return v1-v2;
    case '*':
        return v1*v2;
    case '/':
        if (v2!=0)
            return v1/v2;
        else
            abort();
    }
}
void TreePrint(BTree T,int level) 
/*按树状打印的二叉树*/ 
{   
    int i;
    if(T==NULL)                    /*如果指针为空,返回上一层*/ 
        return;
    TreePrint(T->rchild,level+1);/*打印右子树,并将层次加1*/ 
    for(i=0;i<level;i++)            /*按照递归的层次打印空格*/ 
        printf("   ");
    printf("%c\n",T->data);        /*输出根结点*/ 
    TreePrint(T->lchild,level+1);/*打印左子树,并将层次加1*/ 
}
void DestroyBTree(BTree *T)
/*销毁二叉树操作*/
{
    if(*T)                             /*如果是非空二叉树*/
    {
        if((*T)->lchild)
            DestroyBTree(&((*T)->lchild));
        if((*T)->rchild)
            DestroyBTree(&((*T)->rchild));
        free(*T);
        *T=NULL;
    }
}
int main()
{
    BTNode *b;
    char s[MaxSize]="1+2*3-4/5";
    printf("算术表达式%s\n",s);
    /*
    b=CreateTree(s,0,strlen(s)-1);

printf("对应二叉树:\n");
    TreePrint(b,0);
    printf("\n表达式的值:%g\n",CalcuValue(b));
    DestroyBTree(&b);
    */

double result=0;
    BTree express_tree = Creat_Btree(s, 0, strlen(s)-1);
    result=post_traverser_calc(express_tree);
    printf("后缀表达式:");
    post_traverser_calc(express_tree);
    printf("\n");
    printf("表达式结果为:%.2f\n", result);

return 0;
}

利用树求解算术表达式的值相关推荐

  1. 【数据结构】栈的应用-算术表达式求值#数据结构实验任务书

    实验题目:栈的应用-算术表达式求值 正文 实验环境: Visual C++ 2010 实验目的: 1.掌握栈的定义及实现: 2.掌握利用栈求解算术表达式的方法. 实验内容: 通过修改完善教材中的算法3 ...

  2. 算术表达式求值的程序设计与实现_数据结构课程设计

    以下内容可且仅可供参考,如有错误欢迎指正. 部分思路借鉴算术表达式求值(C语言栈)_夜何其的博客-CSDN博客_c语言利用栈求解算术表达式侵删致歉 <算术表达式求值的程序设计与实现>题目要 ...

  3. 数据结构—— 基于二叉树的算术表达式求值

    实验五 基于二叉树的算术表达式求值 数据结构--中序表达式求值(栈实现) 实验目的: 1.掌握二叉树的二叉链表存储表示和二叉树的遍历等基本算法. 2.掌握根据中缀表达式创建表达式树的算法 3.掌握基于 ...

  4. 栈实现算术表达式求值

    算术表达式求值 利用栈求解的一个典型的问题是算术表达式求值,例如:"3+4*2-(1+1)#",这样的表达式计算,在计算过程中,不是读到一个运算就立即计算,而是要与后面的运算符进行 ...

  5. 【Java】基于栈的算术表达式求值

    定义异常类 public class ExpressionException extends RuntimeException {private static final long serialVer ...

  6. 《Algorithms》—— Dijkstra 的双栈算术表达式求值算法

    想当年学数据结构的时候,一直觉得这个是我一辈子都搞不懂的一个东西.现在看看...还挺简单的... 重点在于如何解析由括号.运算符和数字组成的字符串,并按照正确的顺序完成各种初级算术操作.利用了两个栈( ...

  7. 算术表达式求值演示(C/C++实现)

    算术表达式求值演示 问题描述:表达式计算是实现程序设计语言的基本问题之一,也是栈的应用的典型例子.设计一个程序,演示用算符优先法对算术表达式求值的过程. 基本要求:以字符序列的形式从键盘输入语法正确的 ...

  8. 用算符优先法对算术表达式求值(六)

    18.11.23 这是一道最近刚上的实验课的题目.... 基于C语言,欢迎指正 实验要求 掌握栈在解决实际问题中的应用,设计一个程序,演算用算符优先法对算术表达式求值的过程,利用算符优先关系,实现对算 ...

  9. 算术表达式求值(C语言栈)

    题目:算术表达式求值 题目描述:表达式计算是实现程序设计语言的基本问题之一,也是栈的应用的一个典型例子.设计一个程序,演示用运算符优先法对算数表达式求值的过程. 基本要求:以字符序列的形式从终端输入语 ...

最新文章

  1. 【VMCloud云平台】SCO(四)流程准备
  2. QN8027性能调试
  3. 【错误记录】Android Studio 编译信息输出乱码
  4. Python中join()方法和os.path.join()方法
  5. NFS - MIPS架构下构建NFS共享目录服务
  6. 程序员的数学--排列组合(2)
  7. 使用msm文件创建msi
  8. 字体图标 —— IconMoon
  9. HDU 5371 Manacher Hotaru's problem
  10. 对“流形”最好的讲解在维基
  11. 信息熵--决策树的建立算法ID3中使用
  12. 表单验证 靠name获取
  13. JS 幻灯片代码(含自动播放)
  14. Postman 设置环境变量 个人记录
  15. 【深度理解】如何评价GAN网络的好坏?IS(inception score)和FID(Fréchet Inception Distance)
  16. w ndows7旗舰版镜像下载,win7旗舰版32位原版iso
  17. Gerrit 安装lfs插件
  18. keil symbol外部符号定义
  19. 机构投资者大举入场,促使BTC上涨? | 一周问答热议
  20. 人工智能在减灾遥感中的应用

热门文章

  1. axure命令行_Axure完成前端开发可行性探索
  2. 安卓一个方法多处调用_一个隐藏在方法集和方法调用中且易被忽略的小细节
  3. php加图片源码_PHP添加文字水印或图片水印的水印类完整源代码与使用示例
  4. mysql 生成数列_PHP生成器的创建和使用
  5. Shell脚本实现生成SSL自签署证书
  6. Ubuntu用户设置文件说明
  7. 炸金花的JS实现从0开始之 -------现在什么都不会(1)
  8. JAVA-初步认识-第十一章-异常-概述
  9. Scala编程入门---数组操作之数组转换
  10. 数据挖掘介绍以及模型参数详解