爱问知识人 爱问教育 医院库

有一个数值表达式,生成树,并以三种遍历方式输出树,最后求值

首页

有一个数值表达式,生成树,并以三种遍历方式输出树,最后求值

表达式中只有数字、加、减、乘、除和括号,要求用二叉树解决,要可以计算表达式的值……

提交回答

全部答案

    2018-05-21 04:37:37
  •   /*
    你是指数值表达式求值吗?是的话就看看吧……
    这是去年的二月份写的了……时间过得真快……
    呃……跑题了……
    这份是精简的,原来的包括阶乘、幂、解析函数啊什么的、不过对于你的题目要求有点过于庞大……
    如果要原版的话就追问提出吧……
    嗯……这份代码为了计算准确是以最右面的同级运算符作为建树的起点、所以生成的树比较特殊……
    前序遍历和后序遍历也不是标准的波兰式、逆波兰式了……
    当然中序遍历也不是原来的式子了,这主要决定于建树时的方法了……
    Linux GCC 3。
      4。5 下运行通过……
    */
    //#include // 要 Linux 或 MS-WIN MinGW 的话注释掉
    #include
    #include
    using namespace std;
    #define invalid_argument // 要 MS-WIN MS-VC 的话注释掉
    // note:
    // 2009-1-1 立项
    // 2009-1-27 复工
    // 2009-2-6 添加角、弧、梯度制度转换
    // 2009-2-7 beta 1
    // 基本的四则运算
    #define OPERATORS_PLUS 0x000001
    #define OPERATORS_MINUS 0x000002
    #define OPERATORS_MUTIPLE 0x000003
    #define OPERATORS_DIVIDE 0x000004

    class expression
    {
    private:
    public:
    double m_value; // 该节点经计算后的结果
    int m_operator; // 该节点操作符
    expression *m_left; // 左子树
    expression *m_right; // 右子树
    private:
    std::string delete_bracket( const std::string p_exp ); //如果如果表达式处于括号内,则去掉括号
    bool make_tree( const std::string p_exp ); // 生成二叉树,用下面的函数作为生成条件
    bool find_plus_minus( char *p_pexp ); // 将一个表达式分解成三部分,第一部分包含第一个加数或被减数,第二部分为操作符[ -],余下的做为第三部分
    bool find_mutiple_divide_mod( char *p_pexp ); // 将一个因式分解成三部分,第一部分包含第一个因数或被除数,第二部分为操作符[*/%],余下的做为第三部分
    // 将操作符字符串转换为操作符常量
    inline int operatorstr2type( const char *p_pstr, int &p_operator_length );
    inline int operatorstr2type( const char *p_pstr );
    public:
    expression( void );
    expression( const std::string p_exp );
    double get_result( void ); // 得到结果
    double get_result( const std::string p_exp ); // 计算并返回结果
    virtual ~ expression( void );
    void release( );
    void parse( const std::string p_exp );
    int preorder( void );
    int inorder( void );
    int postorder( void );
    public:
    };
    expression::expression( void )
    {
    m_left = NULL;
    m_right = NULL;
    m_value = 0。
      0f;
    m_operator = 0;
    }
    expression::~expression( void )
    {
    release( );
    }
    void expression::release( void )
    {
    if( m_left )
    {
    delete m_left;
    m_left = 0;
    }
    if( m_right )
    {
    delete m_right;
    m_right = 0;
    }
    }
    expression::expression( const std::string p_exp )
    {
    m_left = NULL;
    m_right = NULL;
    m_value = 0。
      0f;
    m_operator = 0;
    parse( p_exp );
    }
    void expression::parse( const std::string p_exp )
    {
    // 解析表达式
    release( );
    if( strlen( p_exp。
      c_str( ) ) == 0 )
    {
    // 若是空串,则值为0,返回
    m_value = 0。0f;
    return;
    }
    if( !make_tree( p_exp ) ) // 建树,检查是否可以被分解成两个部分,如果可分,则分解过程中不断产生新的子树
    {
    // 若不可分,应该就是数值了,此时整个表达式有可能在括号里面,所以应该先去括号再取值。
      
    m_value = atof( delete_bracket( p_exp )。c_str( ) );
    }
    }
    std::string expression::delete_bracket( const std::string p_exp )
    {
    // 去括号
    char ch = 0;
    int pos = 0;
    int bracket_count = 0; // 括号计数器,遇'('加1,遇')'减1
    if( p_exp[0] != '(' )
    {
    while( p_exp[pos] )
    {
    ch = p_exp[pos ];
    if( ( ch '9' && ch 'Z' ) ) && ( ch != ' ' && ch != '-' && ch != '*' && ch != '/' && ch != '\' && ch != '%' && ch != '^' && ch != '!' && ch != '(' && ch != ')' && ch != '。
      ' && ch != ' ' ) )
    throw invalid_argument( string( "表达式中的有错误!在 " ) ch string( " 附近" ) );
    }
    return p_exp; // 最左边不是左括号,所以不能去括号
    }
    pos = 0;
    while( bracket_count == 0 )
    {
    // 找到第一个左括号
    ch = p_exp[pos ];
    if( ch == 0 )
    return p_exp; // 没有找到左括号
    if( ch == '(' )
    bracket_count ; // 找到左括号,结束循环
    }
    // 现在肯定有左括号'(',并且括号计数值是1,现在找右括号
    while( bracket_count != 0 )
    {
    ch = p_exp[pos ];
    if( ch == 0 ) // 没有找到匹配的括号
    throw invalid_argument( string( "表达式中的括号不匹配!" ) );
    if( ch == '(' )
    bracket_count ;
    if( ch == ')' )
    bracket_count--;
    }
    if( p_exp[pos] != 0 )
    // 找到了右括号,而且没有到结尾,说明表达式不全在一对括号内,这时不应该去括号,而应该返回原表达式串
    return p_exp;
    else
    // 整个表达式全在一对括号内,去掉两端的括号,返回去掉两端括号之后的表达式串
    return p_exp。
      substr( 1, p_exp。length( ) - 2 );
    }
    bool expression::make_tree( std::string p_exp )
    {
    // 开始建树
    size_t len = strlen( p_exp。
      c_str( ) );
    if( len == 0 )
    {
    // 表达式为空时
    m_value = 0。0;
    return true; // 已完成建树的过程
    }
    size_t start = 0;
    // 去空格
    while( p_exp[start] == ' ' )
    start ;
    while( p_exp[len - 1] == ' ' )
    len--;
    p_exp = p_exp。
      substr( start, len - start ); // 去掉空格之后的新串
    return find_plus_minus( ( char * ) delete_bracket( p_exp。c_str( ) )。
      c_str( ) );
    // 加减试下
    }
    bool expression::find_plus_minus( char *p_pexp )
    {
    int bracket_count = 0; // 括号计数器
    char *pch = p_pexp; //用于遍历表达式
    char *pop = 0; // 指向找到的操作符
    while( *pch )
    {
    if( *pch == '(' )
    {
    bracket_count ;
    while( bracket_count > 0 && ( *pch ) )
    {
    pch ;
    if( *pch == ')' )
    --bracket_count;
    if( *pch == '(' )
    bracket_count;
    } // 跳过括号
    }
    else if( *pch == ' ' || *pch == '-' )
    pop = pch; // 指向最后一个操作符,生成子二叉树时,前面的都在左子树上
    pch ;
    }
    if( pop )
    {
    // 找到了加或减操作符,以操作符为界分为左右两部分
    std::string sl, sr;
    sl。
      append( p_pexp, pop - p_pexp );
    sr。append( pop 1, pch - pop );
    m_operator = operatorstr2type( pop ); // 设置该节点的操作符
    if( this->m_operator == -1 )
    throw invalid_argument( string( "表达式中有错误!在 / - 附近" ) );
    m_left = new expression( sl ); // 生成左子树
    m_right = new expression( sr ); // 生成右子树
    return true; //返回真值, 表示已完成建树的过程
    }
    else
    // 没有找到加减运算符,再找乘除模运算符,并返回它的结果
    return find_mutiple_divide_mod( p_pexp );
    }
    bool expression::find_mutiple_divide_mod( char *p_pexp )
    {
    int bracket_count = 0; // 括号计数器
    char *pch = p_pexp; //用于遍历表达式
    char *pop = 0; // 指向找到的操作符
    while( *pch )
    {
    if( *pch == '(' )
    {
    bracket_count ;
    while( bracket_count > 0 && ( *pch ) )
    {
    pch ;
    if( *pch == ')' )
    --bracket_count;
    if( *pch == '(' )
    bracket_count;
    } // 跳过括号
    }
    else if( *pch == '*' || *pch == '/' || *pch == '%' || *pch == '\' )
    pop = pch; // 指向最后一个操作符,生成子二叉树时,前面的都在左子树上
    pch ;
    }
    if( pop )
    {
    // 找到了乘、除或模操作符,以操作符为界分为左右两部分
    string sl, sr;
    sl。
      append( p_pexp, pop - p_pexp );
    sr。append( pop 1, pch - pop );
    m_operator = operatorstr2type( pop ); // 设置该节点的操作符
    if( this->m_operator == -1 )
    throw invalid_argument( string( "表达式中有错误!在*//\/%附近" ) );
    m_left = new expression( sl ); // 生成左子树
    m_right = new expression( sr ); // 生成右子树
    return true; // 返回真值, 表示已完成建树的过程
    }
    else
    return false;
    }

    double expression::get_result( void )
    { // HUGE_VAL
    // 也就是简单的中序遍历就可以了
    switch ( this->m_operator )
    {
    case OPERATORS_PLUS:
    m_value = m_left->get_result( ) m_right->get_result( );
    break;
    case OPERATORS_MINUS:
    m_value = m_left->get_result( ) - m_right->get_result( );
    break;
    case OPERATORS_MUTIPLE:
    m_value = m_left->get_result( ) * m_right->get_result( );
    break;
    case OPERATORS_DIVIDE:
    m_value = m_left->get_result( ) / m_right->get_result( );
    break;
    default:
    break;
    }
    return m_value;
    }
    // 直接计算给出的表达式的值,并返回
    double expression::get_result( const std::string p_pexp )
    {
    parse( p_pexp );
    return get_result( );
    }
    inline int expression::operatorstr2type( const char *p_pstr, int &p_operator_length )
    {
    // 四则运算以及模、幂、阶乘
    if( *p_pstr == ' ' )
    {
    p_operator_length = 1;
    return OPERATORS_PLUS;
    }
    else if( *p_pstr == '-' )
    {
    p_operator_length = 1;
    return OPERATORS_MINUS;
    }
    else if( *p_pstr == '*' )
    {
    p_operator_length = 1;
    return OPERATORS_MUTIPLE;
    }
    else if( *p_pstr == '/' )
    {
    p_operator_length = 1;
    return OPERATORS_DIVIDE;
    }
    return -1;
    }
    inline int expression::operatorstr2type( const char *p_pstr )
    {
    int agent = 0;
    return this->operatorstr2type( p_pstr, agent );
    }
    int expression::preorder( void )
    {
    static char op[][2] = { "", " ", "-", "*", "/" };
    if( this->m_operator )
    cout m_operator] m_value preorder( );
    if( m_right )
    m_right->preorder( );
    return 0;
    }
    int expression::inorder( void )
    {
    if( m_left )
    m_left->preorder( );

    static char op[][2] = { "", " ", "-", "*", "/" };
    if( this->m_operator )
    cout m_operator] m_value preorder( );
    return 0;
    }
    int expression::postorder( void )
    {
    if( m_left )
    m_left->preorder( );
    if( m_right )
    m_right->preorder( );
    static char op[][2] = { "", " ", "-", "*", "/" };
    if( this->m_operator )
    cout m_operator] m_value << ' ';
    return 0;
    }
    int main( int argc, char *argv[] )
    {
    char exp[] = "1 2 - 3";
    expression exptree;
    exptree。
      parse( exp );
    cout << "Pre-order: ";
    exptree。preorder( );
    cout << endl << "In-order: ";
    exptree。
      inorder( );
    cout << endl << "Post-order: ";
    exptree。postorder( );
    cout << endl << exp << " = " << exptree。
      get_result( );
    return 0;
    }。

    s***

    2018-05-21 04:37:37

类似问题

换一换

相关推荐

正在加载...
最新问答 推荐信息 热门专题 热点推荐
  • 1-20
  • 21-40
  • 41-60
  • 61-80
  • 81-100
  • 101-120
  • 121-140
  • 141-160
  • 161-180
  • 181-200
  • 1-20
  • 21-40
  • 41-60
  • 61-80
  • 81-100
  • 101-120
  • 121-140
  • 141-160
  • 161-180
  • 181-200
  • 1-20
  • 21-40
  • 41-60
  • 61-80
  • 81-100
  • 101-120
  • 121-140
  • 141-160
  • 161-180
  • 181-200
  • 1-20
  • 21-40
  • 41-60
  • 61-80
  • 81-100
  • 101-120
  • 121-140
  • 141-160
  • 161-180
  • 181-200

热点检索

  • 1-20
  • 21-40
  • 41-60
  • 61-80
  • 81-100
  • 101-120
  • 121-140
  • 141-160
  • 161-180
  • 181-200
返回
顶部
帮助 意见
反馈

确定举报此问题

举报原因(必选):