zoukankan      html  css  js  c++  java
  • 字符串表达式的计算

    字符串表达式的计算

    步骤:

    (1) 初始化两个栈:运算符栈S1和储存中间结果的栈S2;

    (2) 从左至右扫描中缀表达式;

    (3) 遇到操作数时,将其压入S2;

    (4) 遇到运算符时,比较其与S1栈顶运算符的优先级:

    (4-1) 如果S1为空,或栈顶运算符为左括号“(”,则直接将此运算符入栈;

    (4-2) 比栈顶高,也将运算符压入S1         (注意转换为前缀表达式时是优先级较高或相同,而这里则不包括相同的情况);

    (4-3) 比栈顶低或相同,将S1栈顶的运算符弹出并压入到S2中,再次转到(4-1)与S1中新的栈顶运算符相比较;

    (5) 遇到括号时:

    (5-1) 如果是左括号“(”,则直接压入S1;

    (5-2) 如果是右括号“)”,则依次弹出S1栈顶的运算符,并压入S2,直到遇到左括号为止,此时将这一对括号丢弃;

     (6) 重复步骤(2)至(5),直到表达式的最右边;

     (7) 将S1中剩余的运算符依次弹出并压入S2;

     (8) 依次弹出S2中的元素并输出,结果的逆序即为中缀表达式对应的后缀表达式(转换为前缀表达式时不用逆序)。

       例:1+((2+3)×4)-5

      链接

    java版  |  详见

    import java.util.LinkedList;
    import java.util.List;
    import java.util.Scanner;
    import java.util.Stack;
    
    public class Main {
        public static void main(String[] args) {
            Scanner sc = new Scanner(System.in);
            String s = sc.nextLine();
            sc.close();
            System.out.println(getResult(getPost(s)));
        }
        
        /**
         * 计算后缀表达式的值
         * @param list 后缀表达式
         * @return
         */
        public static int getResult(List<Character> list) {
            Stack<String> stack = new Stack<>();
            for(int i = 0; i < list.size(); i++) {
                char c = list.get(i);
                if(c >= '0' && c <= '9') { //当遇到操作数直接压栈
                    stack.push(c + "");
                }
                else {//当遇到操作符的时候,从栈中弹出两个元素,然后根据运算符的不同做相应的运算,然后把运算结果压栈。
                    int b = Integer.parseInt(stack.pop());
                    int a = Integer.parseInt(stack.pop());
                    if(c == '+') stack.push(a + b + "");
                    else if(c == '-') stack.push(a - b + "");
                    else if(c == '*') stack.push(a * b + "");
                    else stack.push(a / b + "");
                }
            }
            //最终栈中肯定只剩下一个元素,就是计算的结果。
            return Integer.parseInt(stack.pop());
        }
        
        /**
         * 把中缀表达式转为后缀表达式
         * 前提条件:操作数的范围为0-9,操作符为+,-,*,/,以及()
         * @param s 字符串表达式
         * @return 
         */
        public static List<Character> getPost(String s) {
            Stack<Character> stack = new Stack<>(); //保存操作符
            LinkedList<Character> list = new LinkedList<>(); //保存最终的后缀表达式
            for(int i = 0; i < s.length(); i++) {
                char c = s.charAt(i);
                if(c >= '0' && c <= '9') list.add(c); //操作数直接输出到后缀表达式中
                else if(c == '+' || c == '-' || c == '*' || c == '/') { 
                    //把比当前操作符c的优先级高或者等于c的优先级的操作符依次弹出栈并保存到后缀表达式中,直到遇到栈顶操作符的优先级比c低
                    while(!stack.isEmpty()) { 
                        if(compare(stack.peek()) >= compare(c)) {
                            list.add(stack.pop());
                        }
                        else break;
                    }
                    stack.push(c);//当前操作符c入栈
                }
                else if(c == '(') stack.push(c); //左括号直接入栈
                else {
                    //当遇到右括号的时候,把栈中的操作符依次弹出并追加到后缀表达式中,直到遇到左括号停止,并把左括号弹出。
                    while(stack.peek() != '(') { 
                        list.add(stack.pop());
                    }
                    stack.pop();
                }
            }
            //把栈中所有的操作符全部弹出追加到后缀表达式中
            while(!stack.isEmpty())list.add(stack.pop());
            return list;
        }
        
        /**
         * 计算运算符的优先级
         * @param c  运算符
         * @return
         */
        public static int compare(char c) {
            if(c == '+' || c == '-') return 1;
            else if(c == '*' || c == '/') return 2;
            else return 0;
        }
    }
    

      

     c++版

    #define   STACK_MAX      64
    #define   BOTTOM_NUMBER  -1
     
    typedef struct{
       int		TOP;
       const  	int BOTTOM;
       char		STACK_M[STACK_MAX];
    }STACK_BASE_TY;
    
    我们采用数组STACK_M 作为栈的实体,BOTTOM作为栈底,
    使用数组作为栈的实体,那么就可以规定栈底的索引值为“-1”。
    栈从0~STACK_MAX-1正向增长。
    当然我们还要编写栈的操作方法,为了方便管理我们编写一个结构体来管理函数。
    
    typedef struct {
       void (*Initial)      ( STACK_BASE_TY *pStack);
       int  (*Push)         ( STACK_BASE_TY *pStack, int data);
       int  (*Pop)          ( STACK_BASE_TY *pStack, char *pdata);
       char (*GetTopData)   ( STACK_BASE_TY *pStack);
       int  (*GetTopLocate) ( STACK_BASE_TY *pStack);
    }STACK_OPTION_TY;
     
     
    我们规划一下每个函数的功能:
    1.初始化栈,初始化栈的目的是建立一个空栈。即将TOP指针指向BOTTOM。pStack指向要初始化的栈的实体。
    2.压栈,将一个数据的值压入栈顶。返回0,栈满,压入错误;返回1,压栈成功。
    3.出栈,弹出栈顶的数据。*pdata接收出栈数据的值。返回0,栈空,出栈错误;返回1,出栈成功。
    4.获取栈顶数据值,但是栈顶指针不发生变化。
    5.获取栈顶的位置。
     
     
    void initialStack(  STACK_BASE_TY *pStack )
    {
        int i;
        pStack->TOP = -1;
        for( i =0; i< STACK_MAX; i++ ) pStack->STACK_M[i]=0;
    }
     
    int pushStack(  STACK_BASE_TY *pStack, int data )
    {
        pStack->TOP++;
        if( pStack->TOP>=STACK_MAX )
        {
    		pStack->TOP--;
    		return 0;
    	}
    	else
    	{
    		pStack->STACK_M[ pStack->TOP] = data;
    		return 1;
    	}
    }
     
     
    int popStack(  STACK_BASE_TY *pStack, char *pdata )
    {
    	if(pStack->TOP<=pStack->BOTTOM)
    	{
    		return 0;
    	}
    	else
    	{
    		*pdata = pStack->STACK_M[pStack->TOP];
    		pStack->TOP--;
    		return 1;
    	}
    }
     
     
    int  getStackTopLocate(STACK_BASE_TY *pStack)
    {
    	return pStack->TOP;
    }
     
    char  getTopData(  STACK_BASE_TY *pStack )
    {
        return pStack->STACK_M[pStack->TOP];
    }
     
     
    定义两个栈,
    STACK_BASE_TY    statck_option={0,-1,{0,0}};
    STACK_BASE_TY    statck_result={0,-1,{0,0}};
     
    STACK_BASE_TY*  const pOptionStatck = &statck_option;
    STACK_BASE_TY*  const pResultStatck = &statck_result;
     
    statck_option存放运算符号,statck_result存放最终结果。
     
    STACK_OPTION_TY  stackOption = {initialStack,pushStack,popStack,getTopData,getStackTopLocate} ; 
     
    定义一个函数结构体,并且初始化,使得我们可以方便的调用栈的操作方法。
    const char str[] = "(1+2+3)*(4+5)";  测试公式
     
    int main(  )
    {
        unsigned  int i;
        char temp;
        char opCh_0,opCh_1;
        int compPr;
    
        stackOption.Initial(pOptionStatck);
        stackOption.Initial(pResultStatck);
    
        for( i=0;  i<strlen(str); i++)
        {
            switch( str[i])
            {
                case '0':
                case '1':
                case '2':
                case '3':
                case '4':
                case '5':
                case '6':
                case '7':
                case '8':
                case '9':
                    stackOption.Push(pResultStatck,str[i]);
                    break;
                case '+':
                case '-':
                    if( stackOption.GetTopLocate(pOptionStatck) ==-1 )
                    {
                        stackOption.Push(pOptionStatck,str[i]);
                    }
                    else
                    {
                        opCh_0 =  stackOption.GetTopData(pOptionStatck);
                        if( opCh_0=='(')
                        {
                            stackOption.Push(pOptionStatck,str[i]);
                        }
                        else
                        {
          
                            while((stackOption.GetTopLocate(pOptionStatck) !=-1 )&&
                                (opCh_0!='('))
                            {
                                if(stackOption.Pop(pOptionStatck,&opCh_0 )!=0)
                                {
                                    if(opCh_0!='(')
                                    {
                                        stackOption.Push(pResultStatck, opCh_0); 
                                    }
                                }
                            }
                            stackOption.Push(pOptionStatck,str[i] );
                        }
                    }
                    break;
    				
                case '*':  
                case '/':
                    if( stackOption.GetTopLocate(pOptionStatck) ==-1 )
                    {
                        stackOption.Push(pOptionStatck,str[i]);
                    }
                    else
                    {
                        opCh_0 =  stackOption.GetTopData(pOptionStatck);  
                        if(( opCh_0=='(')||(opCh_0=='+')||(opCh_0=='-'))
                        {
                            stackOption.Push(pOptionStatck,str[i]);
                        }
                        else
                        {
                            while((stackOption.GetTopLocate(pOptionStatck) !=-1 )&&
                                (opCh_0!='('))
                            {
    						   opCh_0 = stackOption.GetTopData(pOptionStatck); 
    
    						   if(( opCh_0=='(')||(opCh_0=='+')||(opCh_0=='-'))
    						   {
    
    								break;
    							}
    							else
    							{
    								stackOption.Pop(pOptionStatck,&opCh_0);
    								stackOption.Push(pResultStatck,opCh_0);
    							}
                            }
    						stackOption.Push(pOptionStatck,str[i] );
    					}
    				}
    				break;
    			case '(':
    				stackOption.Push(pOptionStatck,str[i]);
    				break;
    			case ')':
    				if( stackOption.GetTopLocate(pOptionStatck) ==-1 )
    				{
    
    				}
    				else
    				{
    					opCh_0 = stackOption.GetTopData(pOptionStatck);  
    					if( opCh_0=='(')
    					{
    						stackOption.Pop(pOptionStatck,&opCh_0);
    					}
    					else
    					{
    						while((stackOption.GetTopLocate(pOptionStatck) !=-1 )&&
    							(opCh_0!='('))
    						{
    							opCh_0 = stackOption.GetTopData(pOptionStatck); 
    							if( opCh_0!='(')
    							{
    								stackOption.Pop(pOptionStatck,&opCh_0);
    								stackOption.Push(pResultStatck,opCh_0);
    							}
    							else
    							{
    								stackOption.Pop(pOptionStatck,&opCh_0);
    							}
    						}
    					}
    				}
    				break;
    			default:
    				break;
    		}
    	}
    	
    	while(stackOption.Pop(pOptionStatck,&opCh_0)!=0)
    	{
    		stackOption.Push(pResultStatck,opCh_0);
    	}
    	 
    	while(stackOption.Pop(pResultStatck,&opCh_0)!=0)
    	{
    		printf("%c,",opCh_0);
    	}
    	
    	printf("
    ");
    	return 0;
    }
    

      

  • 相关阅读:
    8.18学习日志
    8.17学习日志
    8.15学习日志
    8.14学习日志
    8.13学习日志
    8.12学习日志
    8.11学习日志
    kindle
    xcode 4 安装cocos2d-x 2.1.4
    GUI之CCControlExtension
  • 原文地址:https://www.cnblogs.com/iupoint/p/14306592.html
Copyright © 2011-2022 走看看