opr0002S.gif (1652 bytes)问题描述
opr0002S.gif (1652 bytes)问题分析
opr0002S.gif (1652 bytes)程序使用说明
opr0002S.gif (1652 bytes)程序结构

 

问题描述

原问题如下:(From chapter 3, Additional exercises 10)

Programming Project:

    I am sorry I can't find where the project is ! I just hear it from one of my classmate

Enter a string of expression ,you must consturct a tree devide from the string

and calculate the value of this expression

Back to Top

问题分析

 

1:输入一个表达式的字符串流从中识别出各种算术元素 如“+ 变量 整数浮点数。

2:用递归方法构建表达式树

3:树的数值运算找出未知变量,获得它的值,用后序遍历计算值

 

Back to Top

 

程序使用说明

 

wpe6.jpg (33193 bytes)

 

 

 

按钮说明

 

   Enter    : 将编辑框内的表达式读入程序,生成表达式树

   Postorder:   后序遍历

   Inorder:        中序遍历

   Preorder      前序遍历

   Insert Space :   决定生成的遍历式中是否插入空格,因为变量可能为多字符。

   Calculation :   计算表达式值

 

操作过程

    1:编辑器中输入一个表达式

    2:按 Enter 键 

    3:此时表达式处理已经完成,如果表达式正确会有树生成,但未展开

    4: 点击根部,浏览整棵树

    5:按 Preorder  ,Inorder 或Posorder   浏览三种遍历的结果

    6:点击 Calculation 开始表达式数值的计算

    7:程序遇到未知变量会弹出对话框

    8:变量值输入后,程序会自动记录下,下次运算会自动调用

    9:如果想要改动变量列表中变量的值,用鼠标在该变量上双击

 

 

 

 

程序结构

核心数据结构如下:

typedef struct Tree_Struct

{

    CString Node;

    Tree_Struct* left;

    Tree_Struct* right;

}TreeStruct;

核心算法函数如下:

BOOL ConstructTree(TreeStruct *Leaf,CString Expression)

double Calculate(TreeStruct *Leaf)

 

CString Preorder(TreeStruct* Leaf)

CString Postorder(TreeStruct* Leaf)

CString Inorder(TreeStruct* Leaf)

BOOL TestWholeExpression(CString str)

 

 

 

BOOL CTreeDlg::ConstructTree(TreeStruct *Leaf, CString Expression)       

//树的构建函数 , Leaf 是表达式树当前的工作节点 Expression 字符串流

{                         (Go Back to Function List)

    CString str;

    int length; //Expression 的长度

    CString rightExpression; //截取下的右边子串

    CString leftExpression; //截取下的左边子串

 

    TreeStruct* RightLeaf; //右子树节点

    TreeStruct* LeftLeaf; //左子树节点

 

    length=Expression.GetLength();

 

    if (length==0) return false; //如果字符串长度为零 认为输入非法

//这种设定是为防止 “ a + b - ” 这种情况

 

    int Operator; //获得可作为节点的符号的位置

    //返回规则演示

    /*

    (a+b)* (c+d) Operator=3

    a+(b-d) Operator=2

    a Operator=-1;

    (a+b) Operator=-1;

    */

 

    if (!TestWholeExpression(Expression)) return false; //判断表达式中括号是否匹配

    //如果为 “(a+b) “ 类型去括号, 防止无限递归或作为一个变量

    if (Expression[length-1]==')')

    {

        left=FindLeft(Expression,length-1);

        //FindLeft() 是一个核心函数 返回与当前右括号匹配的右括号

        if (left==-1) return false;

        if (left==0) //说明为 “(a+b)” 类型

        Expression=Expression.Mid(1,length-2);

        length=Expression.GetLength();

        if (length==0) return false;

    }

 

    //Find '+' Operator

    Operator=Find(Expression,'+');

    /*Find()是另外的一个重要函数 ,返回要找的字符最靠左边的位置

    但是遇到括号要跳过

    如果找不到返回 –1

    如果发现表达式有语法错误返回 –2 */

  

     if (Operator==-2) return false; //表达式有错误返回 false

 

    if (Operator!=-1)

    {

   //确定左右子表达式

        Cstring temp;

        leftExpression.Format(Lefting(temp,Operator));

        rightExpression.Format(Righting(temp,length-Operator-1));

        //构建树

        Leaf->Node="+";

        RightLeaf=new TreeStruct;

        LeftLeaf=new TreeStruct;

        Leaf->left=LeftLeaf;

        Leaf->right=RightLeaf;

        if (!ConstructTree(RightLeaf,rightExpression)) return false;

        if (!ConstructTree(LeftLeaf,leftExpression)) return false;

        return true;

    }

 

     //Find "-" operator

        .................................

        //Find "*" operator

        ......................................

       //Find "/" operator

        .....................................

  

  

  

    //不允许 “a()b” 这种变量的出现

    if (FindChar(Expression,'(')!=-1) return false;

    if (FindChar(Expression,')')!=-1) return false;

 

    //确定叶节点

    Leaf->Node=Expression;

    Leaf->right=NULL;

    Leaf->left=NULL;

    return true;

}

 

 

 

//表达式的数值计算

double CTreeDlg::Calculate(TreeStruct *Leaf)

{                     (Go Back to Function List)

    CDataDlg da;

    //m_Error 是全局变量记录返回错误类型,与错误列表关连

 

    if (IsOperator(Leaf->Node)) //IsOperator() 判断此节点是否是操作符

    {

        double dl=Calculate(Leaf->left);

        if (m_Error) return 0;

       double dr=Calculate(Leaf->right);

        if (m_Error) return 0;

        return Operation(Leaf->Node,dl,dr);

   

    }

    else

    {

        int index=FindInVariableList(Leaf->Node); //在变量栈中查找

        if (index!=-1)

            return m_Variable[index].data;

        else

        {

                VariableSp++; //变量栈顶指针上移

                m_Variable[VariableSp].variable=Leaf->Node;

                m_Variable[VariableSp].data=(double)(atof(Leaf->Node));

                if (m_Variable[VariableSp].data==0 &&

                    m_Variable[VariableSp].variable!="0")

        {

        da.m_Title.Format("Variable %s",Leaf->Node);

        da.m_Data=0;

        if (da.DoModal()==IDOK)

        {

            m_Variable[VariableSp].data=da.m_Data;

            m_List.InsertItem(VariableSp,m_Variable[VariableSp].variable,1);

            CString temp;

            //itoa(da.m_Data,temp.GetBuffer(100),10);

            _ultoa(da.m_Data,temp.GetBuffer(100),10);

   

            m_List.SetItemText(VariableSp,1,temp);

   

        }

    }

 

    return da.m_Data;

    }

    }

return -1;

}

 

 

 

CString CTreeDlg::Preorder(TreeStruct* Leaf)

//前序遍历

{                    (Go Back to Function List)

    CString ss="";

    if (Leaf==NULL) return ss;

 

    ss=ss+Leaf->Node;

    if (m_bInsertSpace) ss+=' ';

    if (Leaf->left!=NULL)

        ss+=Preorder(Leaf->left);

 

   if (Leaf->right!=NULL)

        ss+=Preorder(Leaf->right);

        return ss;

}

 

CString CTreeDlg::Postorder(TreeStruct *Leaf)

//后序遍历

{                    (Go Back to Function List)

    CString ss="";

    if (Leaf==NULL) return ss;

    if (Leaf->left!=NULL)

        ss+=Postorder(Leaf->left);

 

    if (Leaf->right!=NULL)

        ss+=Postorder(Leaf->right);

 

    ss=ss+Leaf->Node;

    if (m_bInsertSpace) ss+=' ';

 

    return ss;

}

 

CString CTreeDlg::Inorder(TreeStruct *Leaf)

//中序遍历

{                    (Go Back to Function List)

    CString ss="";

    if (Leaf==NULL) return ss;

    if (Leaf->left!=NULL)

        ss+=Inorder(Leaf->left);

 

    if (Leaf->left && m_bInsertSpace) ss+=' ';

        ss=ss+Leaf->Node;

    if (Leaf->right && m_bInsertSpace) ss+=' ';

 

    if (Leaf->right!=NULL)

        ss+=Inorder(Leaf->right); 

    return ss;

}

 

 

 

BOOL CTreeDlg::TestWholeExpression(CString str)

{            (Go Back to Function List)

    int length=str.GetLength();

    int sp=0;

    for (int i=0;i<length;i++)

    {

        if (str[i]=='(') sp++;

        if (str[i]==')') sp--;

    }

    if (sp!=0) return false;

    return true;

}