zoukankan      html  css  js  c++  java
  • 每天一道算法题(26)——输入字符串表达式求值

    题目: 

          输入字符串,求输出的值。输入的均为整形,要求包含运算符

             例如输入: "24*1 +(4+6)*2+ (4-3*2) *( 4+6-9+(11-3*4)*2 +2)* 10+ 20 -3* 2 *4 +2"

                    输出结果:20

             要求:对于多余空格字符完好的鲁棒性,函数原型:void process(const char* input, int &output)

     

    思想:

             1. 首先,介绍基本数值运算(不包含括号运算符)算法。例如计算“13+7*2*1-15-2*8+2”。先定义三个变量,整形left,right分别表示左,右操作数,定义bool变量flag。遍历字符串,初始为true。设定字符串指针为*str。 基本算法为左操作数记录当前结果,右操作数更新新的操作数。这里涉及到对下一个操作符号的试探,则四者者的变动为:


           分析:

                     (1)该算法不回溯,只一次性遍历一遍字符串

                     (2)左右操作数不同时更新。且每一步都更新二者之一。

                     (3)若当前操作符为乘法操作,继续更新右操作数。

                     (4)当前操作为加减操作,则根据flag记录的前一操作符(true为加,false为减),更新左操作数=左操作数(flag?+:-)右操作数


            2.本算法是上一算法的改进。这里使用递归法,将括号表达式也看作一个操作数。若遇到括号表达式,使用函数找出括回的位置,去掉括前和括回符号,递归调用主函数process,优先计算出括号表达式字符串里面的计算值。其它操作与上叙算法相同。



    代码:

            (1)int getNum(const char* & input)。当判断出某个字符串开头为数字,则计算出该数字,并移动字符串的指针至数字表达式的下一位置

            (2)int calculate(const char* & input)。当判断出某个字符串开头为‘(’。找出括回,递归调用运算字符串值计算主函数process,计算出括号里面表达式的值。同时涉及到更新指针至括号表达式的下一位置。

            (3)int getValue(const char*& input)。获得下一个操作数的值,这个操作数可能是数值字符串,也可能是括号表达式

            (4)int process(const char* start,const char* end)。重载函数,运算字符串值计算主函数process。

    //获得当前字符串某个操作数的值并且移动节点指针指向下一个位置
    int getNum(const char* & input){
    		if(input==NULL)
    		      return 0;
    		int result=0;
    		while('0'<=*input&&*input<='9'){
    			result=10*result+*input-'0';
    			input++;
    		}
    		return result;
    }
    
    int process(const char* start,const char* end);
    int calculate(const char* &start){//当遇到一个括号表达式时,通过递归法,获得当前括号内的值
    	if(*start!='('||!start)
    		return 0;
    	int count1=0; int count2=0;
    	int result=0;
    	const char* p=start;
        while(*p){
    	   if(*p=='(')
    		   count1++;
    	   else if(*p==')')
    		   count2++;
    	   if(count2==count1)//括前和括回的个数相等,即找到匹配的括回
    		   break;
    	   p++;//获得括回的位置
       }
       start++;p--;//去掉括号,
       result= process(start,p);//递归调用process获得括号里表达式字符串的值。
       start=p+2;//,更新指针,指向括回的下一个位置
       return result;
    }
    
    //获得表达式的值,可能是一个数值表达式,也可能是某个括号表达式
    int getValue(const char* &start){
    	  if(!*start)
    		  return 0;
    
    	  while(*start==' ')
    	     start++;
    
    	 if(*start>='0'&&*start<='9')//某个数字
    			return getNum(start);
    	else if(*start=='(')//括号表达式,计算括号的值
    		    return  calculate(start);
    	else
    	       return 0;
    }
    
    //输入需要计算字符串的首位指针
    int process(const char* start,const char* end){
    	if(start>=end)
    		return 0;
    	int left,right;
    	left=right=0;//左右操作数
    	bool flag=true;//true表示+,false表示-
    	while(start<=(end+1)){//遍历整个字符串
    			if(*start=='('){
    				right=getValue(start);//将括号表达式也作为一个独立的操作数获取
    			}
    			//当前操作符为‘+’,‘-’,则可以根据前一操作符的正负(flag标定)更新左操作数,并移动指针
    			else if(*start=='+'){
    				if(flag)
    					left=left+right;
    				else
    					left=left-right;
    				flag=true;
    				start++;
    			}
    			else if(*start=='-'){
    				if(flag)
    					left=left+right;
    				else
    					left=left-right;
    				flag=false;
    				start++;
    			}
    			//当获得某个右操作数后,发现当前操作符为‘*’
    			//则立即获得后一个操作数(有可能是一个括号表达式)并进行乘法运算,持续更新右操作数
    			else if(*start=='*'){
    				start++;
    				right=right*getValue(start);//继续计算右操作数,因为乘法的优先级较大
    			}
    			//指针指向某个数字,直接获取当前数字,并且更新右操作数
    			else if(*start>='0'&&*start<='9')
    				right=getValue(start);
    			else if(start==end+1){//已经计算到字符串末尾,最后一次计算结果
    				if(flag)
    					left=left+right;
    				else
    					left=left-right;
    				start++;
    			}
    		   else 
    				start++;//中间的空格,略过
    	}
    	return left;
    }
    
    //函数原型
    void process(const char* input, int &output){
    	if(!input)
    		output=0;
    	output=process(input,input+strlen(input)-1);//重载函数
    }

          由于在主函数和右操作数获取函数均包含了空格字符检测,因此本算法对于多余空格鲁棒。同时,对于空白字符也鲁棒。





                    点击链接 获得【红杏出墙】插件,翻墙上网无压力!谷歌搜索无压力!





           

             

  • 相关阅读:
    hdu1238 Substrings
    CCF试题:高速公路(Targin)
    hdu 1269 迷宫城堡(Targin算法)
    hdu 1253 胜利大逃亡
    NYOJ 55 懒省事的小明
    HDU 1024 Max Sum Plus Plus
    HDU 1087 Super Jumping! Jumping! Jumping!
    HDU 1257 最少拦截系统
    HDU 1069 Monkey and Banana
    HDU 1104 Remainder
  • 原文地址:https://www.cnblogs.com/engineerLF/p/5392999.html
Copyright © 2011-2022 走看看