精华内容
下载资源
问答
  • 输入一表达式,将其用表达式树表示,并用表达式计算表达式的值。
  • 计算后缀表达式

    千次阅读 2018-08-15 20:02:24
    一、通过栈把中缀表达式转换为后缀表达式的步骤: 从左至右扫描中缀表达式, if(遇到数字){  加入后缀表达式 }else if(遇到 ‘(’ ){  入栈 }else if(遇到 ‘)’ ){  依次将栈中元素出栈并加入到后缀...

    一、通过栈把中缀表达式转换为后缀表达式的步骤:

    从左至右扫描中缀表达式,

    if(遇到数字){

        加入后缀表达式

    }else if(遇到 ‘(’ ){

        入栈

    }else if(遇到 ‘)’ ){

        依次将栈中元素出栈并加入到后缀表达式,直到遇到 ‘(’ 并将其从栈中删除

    }else if(遇到运算符op){

        if(栈顶元是 ‘(’ ){

            op入栈

        }else{

            if(高于栈顶运算符优先级){

                op入栈

            }else{

                依次将比op优先级高的和相等的运算符出栈加入到后缀表达式,

                直到遇到比op优先级低的运算符或左括号(低优先级运算符或左括号不出栈)或栈空为止

                op入栈

            }

        }

    }

    扫描完毕后栈中所有剩下的运算符出栈加入到后缀表达式

     

    二、通过后缀表达式计算表达式的值的步骤:

    顺序扫描表达式的每一项

    if(遇到操作数){

        入栈

    }else if(遇到操作符op){

        连续从栈中退出两个操作数Y和X(先出栈的为Y)

        将 X<op>Y的结果入栈

    }

    表达式扫描完毕后栈顶元素就是所求的结果

     

    三、计算后缀表达式的代码:

    #include <cassert>
    #include <iostream>
    #include <string>
    #include <vector>
    #include <stack>
    #include <map>
    using std::cout;
    using std::endl;
    using std::string;
    using std::vector;
    using std::stack;
    using std::map;
    class CalcExpress
    {
    	private:
    		enum factorTag{LB,RB,NUM,ADD=10,MINU,MULT = 20,DIV,UNARY=30};//()1 +-*/-//类型标记
    		//enum设置默认值10,20是为了区分+- */ -(负号),使得相差较大,便于区别
    		static map<char,enum factorTag> tagPair;//mapTag
    		typedef std::pair<string,enum factorTag> ExpType;//类型,如<'+',ADD>
    		static bool isError;//出错标识
    		//------------TEST
    	public:
    
    		static void display(const string & s,const vector<ExpType> & x){
    			cout<<s<<":"<<endl;
    			for(auto & elem:x){
    				cout<<elem.first<<"\t\t"<<elem.second<<endl;
    			}
    			cout<<endl;
    		}
    
    		static void display(const vector<ExpType> & x){
    			cout<<"----"<<endl;
    			for(auto & elem:x){
    				cout<<elem.first<<"\t\t"<<elem.second<<endl;
    			}
    			cout<<endl;
    		}
    
    		static void test(){
    			string s1("(1+2*-35)/34");
    			string s2("-1/2-10-(-333+1)");
    			string s3("-(153+2*3)/4");
    			string s4("(1+2)*3");
    			string s5 = "1--2*3/(2/-3-5)";
    			vector<ExpType> vecTest;
    			//strToExpress(s1,vecTest);display(s1,vecTest);
    			//strToExpress(s2,vecTest);display(s2,vecTest);
    			//strToExpress(s3,vecTest);display(s3,vecTest);
    			vector<ExpType> inExp,postExp;
    			string s = s5;
    			strToExpress(s,inExp);
    			display(s,inExp);
    			inExpToPostExp(inExp,postExp);
    			display(postExp);
    			double ret = calcExpressProcess(postExp);
    			if(!isError){
    				cout<<"result = "<<ret<<endl;
    			}else{
    				cout<<"process error"<<endl;
    			}
    		}
    		//------------TEST
    
    	public:
    		static double calcExpress(const char * str){
    			if(!str){
    				isError = true;
    				return 0;
    			}
    			string cppString(str);
    			//判断字符串是否是合法表达式
    			if(!isValidExpress(cppString)){
    				isError = true;
    				return 0;
    			}
    			double ret = 0;
    			isError = false;
    			vector<ExpType> express;//数组保存每一个项
    			strToExpress(cppString,express);//将表达式的每一项存到数组
    			ret = calcExpressProcess(express);
    			return ret;
    		}
    	private:
    
    
    		static bool isValidExpress(const string & cppString){//判断表达式是否合法
    			//待补充完整
    			return true;
    		}
    
    		static void strToExpress(const string & cppString,vector<ExpType> & express){//将string转成ExpType表达式类型
    			//(1+2*-3)/34
    			//-1/2-1-(-3+1)
    			//-(1+2*3)/4
    			express.clear();
    			size_t preIdx = 0;
    			size_t size = cppString.size(); 
    			enum factorTag flag;
    			for(size_t i = 0;i<size;++i){
    				preIdx = i;//k记录数字的第一个位置
    				if(cppString[i] == '-'){
    					if(i==0 || (cppString[i-1] != ')' && !::isdigit(cppString[i-1]))){
    						//-作为负号的场景:前面不是数字或者)
    						flag = UNARY;
    					}else{//减号
    						flag = MINU;
    					}
    				}else if(isdigit(cppString[i])){//数字
    					while(i<size && isdigit(cppString[i])){
    						++i;	
    					}
    					--i;
    					flag = NUM;
    				}else{
    					switch(cppString[i]){
    						case '+':
    							flag = ADD;break;
    						case '*':
    							flag = MULT;break;
    						case '/':
    							flag = DIV;break;
    						case '(':
    							flag = LB;break;	
    						case ')':
    							flag = RB;break;
    						default:
    							isError = true;
    							cout<<"express ERROR"<<endl;
    							return;
    					}
    				}
    				express.push_back(ExpType(string(cppString,preIdx,i-preIdx+1),flag));
    			}
    		}
    
    
    		static void inExpToPostExp(const vector<ExpType> & inExp,vector<ExpType> & postExp){
    			postExp.clear();
    			postExp.reserve(inExp.size());
    			stack<ExpType> stk;//栈
    			for(auto & inTerm:inExp){
    				if(inTerm.second == NUM){//数值
    					postExp.push_back(inTerm);
    				}else if(inTerm.second == RB){//右括号
    					while(!stk.empty()){
    						if(stk.top().second == LB){//左括号
    							stk.pop();
    							break;
    						}else{
    							postExp.push_back(stk.top());
    							stk.pop();
    						}
    					}
    				}else if(inTerm.second == LB){//左括号
    					stk.push(inTerm);
    				}else{//运算符
    					while(
    							!stk.empty() && \
    							(\
    							 (inTerm.second <= stk.top().second) || ((inTerm.second - stk.top().second) == 1) \
    							)\
    						 ){//如果栈顶是高优先级或平级运算符
    						postExp.push_back(stk.top());
    						stk.pop();
    					}
    					stk.push(inTerm);
    				}
    			}
    			while(!stk.empty()){
    				postExp.push_back(stk.top());
    				stk.pop();
    			}
    		}
    
    		static double calcExpressProcess(const vector<ExpType> & postExp){
    			stack<double> calcStk;//栈用于记录中间过程的值
    			for(auto & postTerm:postExp){
    				if(postTerm.second == NUM){//数值
    					calcStk.push(stod(postTerm.first));
    				}else{//运算符
    					if(postTerm.second == UNARY){//负号
    						auto & val = calcStk.top();
    						val = -val;
    					}else{//其他双目运算符
    						double num2 = calcStk.top();
    						calcStk.pop();
    						double num1 = calcStk.top();
    						calcStk.pop();
    						if(postTerm.second == DIV){//判断是否发生除零
    							const double limit = 0.000000001;
    							if(num2 >= -1*limit && num2 <= limit){//num2为0
    								isError = true;
    								cout<<"error,Divide zero"<<endl;
    								abort();
    							}
    						}
    						double val = 0;
    						switch(postTerm.second){
    							case ADD:
    								val = num1 + num2;break;
    							case MINU:
    								val = num1 - num2;break;
    							case MULT:
    								val = num1 * num2;break;
    							case DIV:
    								val = num1*1.0 / num2;break;
    							default:
    								isError = true;
    								cout<<"express ERROR"<<endl;
    								return 0;
    						}
    						calcStk.push(val);
    					}
    				}
    			}
    			if(calcStk.size() != 1){//最后栈中剩下的数就是结果
    				isError = true;
    				cout<<"express ERROR"<<endl;
    				return 0;
    			}
    			return calcStk.top();
    		}
    
    };
    bool CalcExpress::isError = false;
    int main(){
    	CalcExpress::test();
    	return 0;
    }
    

     

    展开全文
  • 计算后缀表达式的值

    千次阅读 2019-09-25 09:14:52
    题目描述 ...计算机计算后缀表达式的过程为,从左到右,遍历表达式,如果当前位是数字,那么先将其暂存,继续往后遍历;如果碰到运算符,那么就取出最近暂存的两个数字,并计算出值,然后将该值继续...

    题目描述

    我们经常遇到的数学计算表达式如:(2+1)*3,成为中缀表达式,这种表达式对于我们来说很容易理解,但是计算机容易理解的形式却是后缀表达式,即,将运算符写在两个运算符的后面,如上述中缀表达式的后缀表达式为:21+3*。计算机计算后缀表达式的过程为,从左到右,遍历表达式,如果当前位是数字,那么先将其暂存,继续往后遍历;如果碰到运算符,那么就取出最近暂存的两个数字,并计算出值,然后将该值继续暂存,直到遍历结束,此时输出暂存区的数字即可。

    说明:其中后缀表达式的开头存储在栈顶,后缀表达式的最后一位存储在栈底。

    Java代码如下

    /**
     * Main_HouZui
     * 中缀表达式为 (2+3)*5/25
     * 计算后缀表达式的值,23+5*25/
     */
    import java.util.Stack;
    public class Main_HouZui 
    {
    
        public static int calculate (int first, int second, String operator)
        {
            int result = 0;
            switch(operator)
            {
                case "+":
                    result = first + second;
                    break;
                case "-":
                    result = first - second;
                    break;
                case "*":
                    result = first * second;
                    break;
                case "/":
                    result = first/second;
                    break;
            }
            return result;
        }
        //stack栈中存放的是后缀表达式 23+5*25/
        public static int function(Stack<String> stack)
        {
            // 碰到运算符,那么就取出最近暂存的两个数字,并计算出值,然后将该值继续暂存到result
            Stack<Integer> result = new Stack<Integer>();
            while(!stack.isEmpty())
            {
                String element = stack.pop();//取栈顶元素
                try
                {
                    //将String 的 1 转为 Integer,遇到 String "+"则有异常了,转到catch语句
                    result.push(Integer.valueOf(element));
                }
                catch(Exception e)
                {
                    int b = result.pop();
                    int a = result.pop();
                    result.push(calculate(a, b, element));
                }
            }
            return result.pop();
        }
        public static void main(String[] args) 
        {
            Stack<String> s = new Stack<>();
            s.push("/");
            s.push("25");
            s.push("*");
            s.push("5");
            s.push("+");
            s.push("3");
            s.push("2");
    
            System.out.println(function(s));
        }
    }

     

    展开全文
  • 使用堆栈计算后缀表达式

    千次阅读 2019-01-29 16:01:18
    使用堆栈计算后缀表达式 一、实现栈结构 根据栈的先进后出的特点,很容易设置栈结构的接口:入栈、出栈、判空、size()等。可以用线性表的方法来实现一个栈结构,其实也就两种,用链表或数组实现栈。 但是,在C++...

    使用堆栈计算后缀表达式

    一、实现栈结构

    根据栈的先进后出的特点,很容易设置栈结构的接口:入栈、出栈、判空、size()等。可以用线性表的方法来实现一个栈结构,其实也就两种,用链表或数组实现栈。

    但是,在C++标准库中已经为我们实现了栈结构,而且是按照最高效率、最优的标准实现的,可以放心的使用C++标准库提供的栈结构,以C++一贯的作风,其实现的栈结构是一个栈类型,定义在<stack>头文件中,使用的时候只需要#include该头文件就行。

    根据C++STL的解释,或C++Primer的解释,都把stack类型称为一个容器适配器(配接器),并没有称其为一个容器,尽管如此,你可以把stack看作是一个特殊的容器,所谓适配器(配接器),指的是一种机制,一个容器适配器使一个容器的行为看起来像另外一个容器,这句话是什么意思呢?这是因为C++的容器适配器都是基于基本容器实现的,比如stack就是基于queue实现的(默认,也可以自己显示的指定为vector),这也导致了任何stack的操作接口都是直接调用底层容器的操作来完成的,如stack的push操作(入栈)就是调用queue的push_back操作来完成的。下面给出STL中stack的定义文件:

    template<class _Ty,class _Container = deque<_Ty> >
    	class stack
    	{	// LIFO queue implemented with a container
    public:
    	typedef _Container container_type;
    	typedef typename _Container::value_type value_type;
    	typedef typename _Container::size_type size_type;
    	typedef typename _Container::reference reference;
    	typedef typename _Container::const_reference const_reference;
    
    	static_assert(is_same_v<_Ty, value_type>, "container adaptors require consistent types");
    
    	stack() _NOEXCEPT_COND(is_nothrow_default_constructible_v<_Container>) //strengthened
    		: c()
    		{	// construct with empty container
    		}
    
    	explicit stack(const _Container& _Cont)
    		: c(_Cont)
    		{	// construct by copying specified container
    		}
    
    	template<class _Alloc,
    		class = enable_if_t<uses_allocator_v<_Container, _Alloc>>>
    		explicit stack(const _Alloc& _Al)
    			_NOEXCEPT_COND(is_nothrow_constructible_v<_Container, const _Alloc&>) //strengthened
    		: c(_Al)
    		{	// construct with allocator
    		}
    
    	template<class _Alloc,
    		class = enable_if_t<uses_allocator_v<_Container, _Alloc>>>
    		stack(const stack& _Right, const _Alloc& _Al)
    		: c(_Right.c, _Al)
    		{	// construct by copying specified container
    		}
    
    	template<class _Alloc,
    		class = enable_if_t<uses_allocator_v<_Container, _Alloc>>>
    		stack(const _Container& _Cont, const _Alloc& _Al)
    		: c(_Cont, _Al)
    		{	// construct by copying specified container
    		}
    
    	explicit stack(_Container&& _Cont)
    			_NOEXCEPT_COND(is_nothrow_move_constructible_v<_Container>) // strengthened
    		: c(_STD move(_Cont))
    		{	// construct by moving specified container
    		}
    
    	template<class _Alloc,
    		class = enable_if_t<uses_allocator_v<_Container, _Alloc>>>
    		stack(stack&& _Right, const _Alloc& _Al)
    			_NOEXCEPT_COND(is_nothrow_constructible_v<_Container, _Container, const _Alloc&>) // strengthened
    		: c(_STD move(_Right.c), _Al)
    		{	// construct by moving specified container
    		}
    
    	template<class _Alloc,
    		class = enable_if_t<uses_allocator_v<_Container, _Alloc>>>
    		stack(_Container&& _Cont, const _Alloc& _Al)
    			_NOEXCEPT_COND(is_nothrow_constructible_v<_Container, _Container, const _Alloc&>) // strengthened
    		: c(_STD move(_Cont), _Al)
    		{	// construct by moving specified container
    		}
    
    	void push(value_type&& _Val)
    		{	// insert element at beginning
    		c.push_back(_STD move(_Val));
    		}
    
    	template<class... _Valty>
    		decltype(auto) emplace(_Valty&&... _Val)
    		{	// insert element at beginning
    #if _HAS_CXX17
    		return (c.emplace_back(_STD forward<_Valty>(_Val)...));
    #else /* _HAS_CXX17 */
    		c.emplace_back(_STD forward<_Valty>(_Val)...);
    #endif /* _HAS_CXX17 */
    		}
    
    	_NODISCARD bool empty() const
    		{	// test if stack is empty
    		return (c.empty());
    		}
    
    	_NODISCARD size_type size() const
    		{	// test length of stack
    		return (c.size());
    		}
    
    	_NODISCARD reference top()
    		{	// return last element of mutable stack
    		return (c.back());
    		}
    
    	_NODISCARD const_reference top() const
    		{	// return last element of nonmutable stack
    		return (c.back());
    		}
    
    	void push(const value_type& _Val)
    		{	// insert element at end
    		c.push_back(_Val);
    		}
    
    	void pop()
    		{	// erase last element
    		c.pop_back();
    		}
    
    	const _Container& _Get_container() const
    		{	// get reference to container
    		return (c);
    		}
    
    	void swap(stack& _Right) _NOEXCEPT_COND(_Is_nothrow_swappable<_Container>::value)
    		{	// exchange contents with _Right
    		_Swap_adl(c, _Right.c);
    		}
    
    protected:
    	_Container c;	// the underlying container
    	};
    

     

    二、后缀表达式求值

    以人类的思维,中缀表达式是正常的表达式形式,因为我们已经熟悉了各种运算符号的优先级,知道在一个表达式中第一个求哪一部分的值,最常见的就是先求括号内部,然后再求括号外部,但是这种求值顺序在计算机看来是很麻烦的,最好的办法是我们输入给计算机的表达式不需要知道操作符优先级,计算机只管按照我们输入的表达式从左到右求值即可,这就要用后缀表达式来实现。后缀表达式是针对中缀表达式而言的,大致可以理解为操作符在两个操作数之后,并不是像中缀表达式那样两个操作数之间必须有一个操作符,后缀表达式最大的特点就是没有必要知道任何运算符的优先规则,如下就是一个后缀表达式:

           “23.2 1.43 * 4.43 + 5.32 1.90 * +”

           其中缀表达式为:“23.2*1.43+4.43+5.32*1.90”

           后缀表达式的求值规则为:从左到右扫描后缀表达式,如果遇到一个操作数,将其压入栈中,如果遇到一个操作符,则从栈中弹出两个操作数,计算结果,然后把结果入栈,直到遍历完后缀表达式,则计算完成,此时的栈顶元素即为计算结果。如上的后缀表达式求值过程为:

    1. 初始,栈空
    2. 遇到操作数23.2,入栈
    3. 遇到操作数1.43,入栈
    4. 遇到操作符*,弹出栈中两个元素,计算结果入栈
    5. 遇到操作数4.43,入栈
    6. 遇到操作符+,弹出占中两个元素,计算结果入栈
    7. 遇到操作数5.32,入栈
    8. 遇到操作数1.90,入栈
    9. 遇到操作符*,弹出栈中两个元素,计算结果入栈
    10. 遇到操作符+,弹出占中两个元素,计算结果入栈

    三、C++代码实现

    /*********************后缀表达式求值(直接利用C++STL提供的Stack实现)**************************/
    double postfixExpression(const string &str)
    {
    	stack<double> mystack;    //栈空间
     
    	string s = ".0123456789+-*/";
    	string empty = " ";
    	string numbers = ".0123456789";
    	string c = "+-*/";
     
    	double firstnum;
    	double secondnum;
    	double sum;
     
    	for(unsigned int i=0; i<str.size(); )
    	{
    		string::size_type start = str.find_first_of(s,i);     //查找第一个数字或算术符号
    		string::size_type end = str.find_first_of(empty,i);   //查找第一个空格
    		string tempstr = str.substr(start, end-start);     //取出这一个元素
     
    		//判断元素
    		if(tempstr == "+" || tempstr == "-" || tempstr == "*" || tempstr == "/")
    		{
    			secondnum = mystack.top();    //取当前栈顶元素,由于栈的先进后出特性,当前栈顶元素其实是二元操作符中右侧的操作数,如表达式3-2的后缀表达式为“3 2 -”,这里secondnum取得数就是2
    			mystack.pop();
    			firstnum = mystack.top();
    			mystack.pop();
    			if(tempstr == "+")
    			{
    				sum = firstnum + secondnum;
    				mystack.push(sum);
    			}
    			if(tempstr == "-")
    			{
    				sum = firstnum - secondnum;
    				mystack.push(sum);
    			}
    			if(tempstr == "*")
    			{
    				sum = firstnum * secondnum;
    				mystack.push(sum);
    			}
    			if(tempstr == "/")
    			{
    				sum = firstnum / secondnum;
    				mystack.push(sum);
    			}
    		}
    		else
    		{
    			double num = stod(tempstr);
    			mystack.push(num);
    		}
     
    		//控制迭代
    		i = end + 1;
    	}
    	return mystack.top();
    }
    
    展开全文
  • 有趣的数据结构算法10——利用栈计算后缀表达式的结果解题思路实现代码GITHUB下载连接 在前一天已经利用栈完成2进制到8进制的转换。但是栈的应用方面还有很多,本次我将讲解如何计算后缀表达式的结果。 解题思路 ...

    有趣的数据结构算法10——后缀表达式(PRN)介绍及利用栈计算后缀表达式的结果

    在前一天已经利用栈完成2进制到8进制的转换。但是栈的应用方面还有很多,本次我将讲解如何计算后缀表达式的结果。
    在这里插入图片描述

    解题思路

    后缀表达式(PRN)也叫逆波兰表达式,是在计算机中用于求值的一种方式,其求值过程可以用到栈来辅助存储。
    在通常的表达式中,二元运算符总是置于与之相关的两个运算对象之间,这种表示法也称为中缀表示,如1+2。波兰逻辑学家J.Lukasiewicz于1929年提出了另一种表示表达式的方法,按此方法,每一运算符都置于其运算对象之后,故称为后缀表示,如12+。
    它的优势在于只用两种简单操作,入栈和出栈就可以搞定任何普通表达式的运算。其运算方式如下:
    如果当前字符为变量或者为数字,则压栈,如果是运算符,则将栈顶两个元素弹出作相应运算,结果再入栈,最后当表达式扫描完后,栈里的就是结果。
    中缀表达式转换到后缀表达式公式
    假定待求值的后缀表达式为:1 2 + 5 3 6 + * + 7 - ,其实际上为1+2+5*(3+6)-7。其求值过程如下:
    1、遍历表达式,遇到1和2,压入栈中。此时栈如图所示:

    示例1
    2、接着读到+号,弹出2与1,执行加法运算,得到3,再次入栈。此时栈如图所示:

    示例2
    3、遇到5、3和6,压入栈中。此时栈如图所示:

    示例3
    4、接着读到+号,弹出6与3,执行加法运算,得到9,再次入栈。此时栈如图所示:

    示例4
    5、接着读到*号,弹出9与5,执行加法运算,得到45,再次入栈。此时栈如图所示:

    示例5
    6、接着读到+号,弹出45与3,执行加法运算,得到48,再次入栈。此时栈如图所示:

    示例6
    7、遇到7,压入栈中。此时栈如图所示:

    示例7
    8、接着读到-号,弹出7与48,执行加法运算,得到41,再次入栈。
    9、由于表达式已结束,读出栈内的最后一个元素,就是结果41。

    实现代码

    #include <stdio.h>
    #include <stdlib.h>
    #define Maxsize 10
    typedef double Ele;
    
    struct stack
    {
    	Ele* top;
    	Ele* bottom;
    	int stacksize;
    };
    
    typedef struct stack* Stack;
    
    void init(Stack s){			//初始化栈
    	Ele *p;
    	p = (Ele*)malloc(Maxsize * sizeof(Ele));
    	if (p == NULL){
    		printf("error");
    		exit(1);
    	}
    	s->top = s->bottom = p;
    	s->stacksize = Maxsize;
    }
    
    void PUSH(Stack s, Ele data){		//入栈
    	int length;
    	length = s->top - s->bottom;
    	if (length >= s->stacksize){
    		s->bottom = (Ele*)realloc(s->bottom,(s->stacksize + Maxsize) * sizeof(Ele));
    		if (s->bottom == NULL){
    			printf("内存分配失败\n");
    			exit(1);
    		}
    		s->stacksize = s->stacksize + Maxsize;//更新stacksize的值
    		s->top = s->bottom + length; //更新top的值
    	}
    	*(s->top) = data;
    	s->top++;
    }
    Ele POP(Stack s){					//出栈
    	Ele num;
    	if (s->top == s->bottom){
    		printf("栈内没有元素了!\n");
    		exit(1);
    	}
    	s->top--;
    	num = *(s->top);
    	return num;
    }
    
    int main(){
    	struct stack s;			//定义栈
    	char c = 0,str[10];		//c用于从键盘获取字符,str用于存储每一轮输入的数字,之后会转化成double类型
    	Ele a1, a2, num;		//a1,a2用于栈的运算
    	int i = 0;				//temp量
    
    
    	init(&s);				//初始化栈
    	printf("请输入一个算式:");		
    
    	scanf("%c", &c);		//输入一个字符
    	while (c != '#')
    	{
    		while ((c <= '9' && c >= '0') || c == '.'){	//该部分用于获取一个double类型的数字
    			str[i++] = c;
    			str[i] = '\0';
    			if (i >= 10){
    				printf("输入数据过大");
    				exit(1);
    			}
    			scanf("%c", &c);
    			if (!(c <= '9' && c >= '0') && !(c == '.')){
    				a1 = atof(str);						//该函数用于将字符串转化位double
    				PUSH(&s, a1);
    				i = 0;
    				break;
    			}
    		}
    		switch (c)								//判断是否属于加减乘除
    		{
    		case '+': 
    			a1 = POP(&s);
    			a2 = POP(&s); 
    			PUSH(&s, a2 + a1);
    			break;
    		case '-': 
    			a1 = POP(&s);
    			a2 = POP(&s); 
    			PUSH(&s, a2 - a1);
    			break;
    		case '*': 
    			a1 = POP(&s);
    			a2 = POP(&s); 
    			PUSH(&s, a2 * a1);
    			break;
    		case '/': 
    			a1 = POP(&s);
    			a2 = POP(&s); 
    			PUSH(&s, a2 / a1);
    			break;
    		case ' ':
    			break;
    		case '#':
    			break;
    		default:
    			printf("输入符号错误!\n");
    			break;
    		}
    		scanf("%c", &c);
    	}
    	num = POP(&s);
    	printf("%.3f\n", num);
    
    	return 0;
    }
    

    GITHUB下载连接

    https://github.com/bubbliiiing/Data-Structure-and-Algorithm

    希望得到朋友们的喜欢。
    有问题的朋友可以提问噢。

    展开全文
  • 一个算术表达式是由操作数(operand)、运算符(operator)和括号组成的。...用户可选择需要进行的操纵,包括后缀表达式计算,中缀表达式转为后缀表达式,清屏和退出,界面清晰,操作简便,且有足够的输入合法性检验
  • 计算后缀表达式的值 一道很经典的题目。建议做一下
  • 后缀表达式的概念 后缀表达式又称作逆波兰式,操作符在运算数的后面,所以叫做后缀表达式。例如 1 + 2 * 3的后缀表达式是 1 2 3 * + 。可以 2 3 *看作一个运算数a, 1 a * 也符合运算数 运算数 操作符的格式。 怎么...
  • 在上一篇我们已经说过如何计算中缀表达式了,那么这一篇就来说一下如何来计算后缀表达式的值。 后缀表达式呢,要比中缀表达式的计算要容易得多。 和上一次一样,我们先来分析一下过程应该是什么样子呢? 我这里有一...
  • 【数据结构】计算后缀表达式的值

    千次阅读 2019-01-20 17:33:46
    我们平常使用的计算表达式都是中缀表达式,而输入计算机后会转换为后缀表达式,即计算机只能计算后缀表达式,那么如何将一个中缀表达式转换为一个后缀表达式? 算法 1)从左到右扫描后缀表达式字符串 2)初始化一...
  • 后缀表达式? 正常地计算表达式 <操作数> <操作符> <操作数>. 9+2 结果 11 后缀表达式 <操作数> <操作数> <操作符> 9 2 + 结果 11 复杂一点地后缀表达式 3 4 * 2 5 + - 4 * 2 /...
  • // 请在此添加代码,补全函数ComputePostfix,计算后缀表达式 /********** Begin *********/ int i = 0;//数组下标 T num1 = 0; T num2 = 0; T num = 0; LinkStack* so = LS_Create(); // 创建运算符栈 ...
  • 计算后缀表达式的过程中,你可以根据需要调用以上操作。因为表达式的计算结果可能是浮点数,所以这里将栈的数据元素类型设置为了double类型。 typedef double T; // 数据元素类型 此外,为了计算后缀表达式,我们...
  • 本文实例为大家分享了C语言实现对后缀表达式(逆波兰表达式)的求解代码,供大家参考,具体内容如下 逆波兰表达式: 逆波兰表达式又叫后缀表达式。它是由相应的语法树的后序遍历的结果得到的。 例:5 – 8*(6 + 7) +...
  • C/C++ 实现利用栈计算后缀表达式的值
  • 栈的典型应用——计算后缀表达式 表达式可以分为三种:前缀表达式,后缀表达式,中缀表达式。 中缀表达式是运算符号在两个数字的之间 也就是我们在数学中常常使用的表达式 前缀表达式就是在两个数字之前 ...
  • 本实验取材于浙江大学《数据结构》,计算后缀表达式,关键在于理解堆栈的工作顺序 //堆栈的应用案例--表达式求值 //表达式求值的基本步数 //1当读入的是一个运算数时,把它被压入栈中; //2当读入的是一个运算符时,...
  • 栈的应用之计算后缀表达式

    千次阅读 2018-03-10 15:56:28
    后缀表达式也称逆波兰表达式,为什么要叫逆波兰表达式嘞?当然是因为有一个波兰人发明了波兰表达式,而逆的波兰表达式就被叫做“逆波兰表达式”喽! 我们一般表述一个算式的时候通常为:X+Y,即为:“操作数1 操作...
  • 后缀表达式:就是将运算符挪到操作数后面,但这样的挪动是有规则的,例如上式转换后缀表达式后是这样的:"9 3 1-4*+10 2/+" 中缀转后缀表达式规则: 从左到右遍历中缀表达式中的每一个·数字和符号: 1.如果是...
  • 文章目录后缀表达式求值算法实现(go语言版) 后缀表达式求值 以人类的思维,中缀表达式是正常的表达式形式,因为我们已经熟悉了各种运算符号的优先级,知道在一个表达式中第一个求哪一部分的值,最常见的就是先求括号...
  • 计算后缀表达式——C语言实现

    千次阅读 2018-07-07 17:56:49
    printf("输入后缀表达式:"); while(c1!='#') { c1=getchar(); if(!operate(c1)) { push(s,(float) (c1-48)); } else { b=top(s); pop(s); a=top(s); pop(s); result=cal(a,...
  • 通常人在书写的时候习惯是书写中缀表达式也叫逆波兰式,然而在计算机处理的时候中缀表达式的效率远小于后缀表达式,即操作数在前面,运算符在后面例如: 中缀表达式 A+B 后缀表达式AB+ A+BC------- ABC*+ AB+C*D ...
  • 中缀转后缀规则:从左到右遍历中缀表达式的每个数字和符号,若是数字就输出,即成为后缀表达式的一部分;若是符号,则判断其与栈顶符号的优先级,是右括号或优先级不高于栈顶符号(乘除优先于加减)则栈顶元素依次...
  • 将中缀表达式,转换为后缀表达式和前缀表达式,再分别计算转换后的表达式值,比较两个计算结果,判断转换正确性和计算正确性。 ·编程 (1)读入中缀表达式,表达式的数据可以是实型、整型; (2)转换为后缀表达式...
  • 后缀表达式计算

    2012-03-09 20:52:17
    后缀表达式计算,输入一个后缀表达式利用栈来计算结果
  • 后缀表达式计算原理 规则: 从左到右遍历表达式的每个数字和符号,遇到的是数字就进栈,遇到的是符号,就将栈顶的两个数字依次出栈,进行运算(运算规则:后出栈的数字1 符号 后出栈的数字2 ),再将运算结果...
  • 计算后缀表达式的值:JAVA-Stack实现

    千次阅读 2017-07-25 12:05:16
    计算一个后缀表达式的值,首先想到就是可以利用栈来实现。 当见到一个数时,就把数推入到栈中去。 当见到一个运算符时,就把栈顶的两个元素即数字弹出并删除,计算出结果后,再结果这个数推入到栈中。注意就是,先...
  • 【Java数据结构的实现】之系列三栈的实现(使用栈计算后缀表达式) 上讲介绍了栈的介绍,最后并给出了栈的抽象数据类型 1.1本章学习目标 中、后缀表达式简介 后缀表达式的实现 本文介绍了栈的实例--使用栈计算后缀...
  • 【0】README0.1) 本文旨在总结 中缀表达式转后缀表达式并计算后缀表达式的值 的步骤,并给出源代码实现;【1】中缀到后缀的转换1.1)此方法需要遵循几个规则(Rule): R1)如果读入操作数,则直接放入输出字符串;...
  • 本文实例为大家分享了C++实现中缀表达式转后缀表达式的具体代码,供大家参考,具体内容如下 题目:现有中缀表达式如:1+(2-3)*4+10/5 请用栈的特性编写一个程序,使得程序输出后缀表达式 分析如下: STEP1: 1+(2-3)...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 71,805
精华内容 28,722
关键字:

计算后缀表达式

友情链接: SDL_systimer.rar