编译原理-中缀表达式转后缀表达式(逆波兰式)

中缀表达式转后缀表达式(逆波兰式)算法,后缀表达式求值算法

 

3 + 4 * 5 - 6;
OS	DS
	3
+	3
+	34
*+	34
*+	345
+	345*
-	345*+
-	345*+6
	345*+6-


插入运算符 o 时,

如果优先级 o>OS[0],

则:遇到')'时,o2 = OS.shift(),DS.push(o2),DS.shift(),否则OS.unshift(o);

否则o2 = OS.shift(),DS.push(o2),OS.unshift(o),连续判断,直到OS[0]优先级>o;


例

   
  3 + 4 / ( 25 - ( 6 * 5 ) )  * 8 #

1
  3 + 4 / ( 25 - ( 6 * 5 ) )  * 8 #
  ↑
  OS       	DS
                   3
 
2
  3 + 4 / ( 25 - ( 6 * 5 ) )  * 8 #
    ↑
  OS       	DS
   +              3
 
3
  3 + 4 / ( 25 - ( 6 * 5 ) )  * 8 #
      ↑
  OS       	DS
   +              3 4

4
  3 + 4 / ( 25 - ( 6 * 5 ) )  * 8 #
        ↑
  OS       	DS
   / 
   +              3 4

5
  3 + 4 / ( 25 - ( 6 * 5 ) )  * 8 #
          ↑
  OS       	DS
   (
   / 
   +               3 4

6
  3 + 4 / ( 25 - ( 6 * 5 ) )  * 8 #
            ↑
  OS       	DS
   (
   / 
   +               3 4 25

7
  3 + 4 / ( 25 - ( 6 * 5 ) )  * 8 #
               ↑
  OS       	DS
   -
   (
   / 
   +               3 4 25

8
  3 + 4 / ( 25 - ( 6 * 5 ) )  * 8 #
                 ↑
  OS       	DS

   (
   -
   (
   / 
   +               3 4 25

9
  3 + 4 / ( 25 - ( 6 * 5 ) )  * 8 #
                   ↑
  OS       	DS
   (
   -
   (
   / 
   +               3 4 25 6


10
  3 + 4 / ( 25 - ( 6 * 5 ) )  * 8 #
                     ↑
 
  OS       	DS
   *
   (
   -
   (
   / 
   +               3 4 25 6

11
  3 + 4 / ( 25 - ( 6 * 5 ) )  * 8 #
                       ↑
  OS       	DS
  
   *
   (
   -
   (
   / 
   +               3 4 25 6 5

12
  3 + 4 / ( 25 - ( 6 * 5 ) )  * 8 #
                         ↑
  OS       	DS
   -
   (
   / 
   +               3 4 25 6 5 *

12
  3 + 4 / ( 25 - ( 6 * 5 ) )  * 8 #
                           ↑
  OS       	DS
   / 
   +               3 4 25 6 5 * -

13
  3 + 4 / ( 25 - ( 6 * 5 ) )  * 8 #
                              ↑
  OS       	DS
   * 
   +               3 4 25 6 5 * - /

14
  3 + 4 / ( 25 - ( 6 * 5 ) )  * 8 #
                                ↑
  OS       	DS
   * 
   +               3 4 25 6 5 * - / 8


15
  3 + 4 / ( 25 - ( 6 * 5 ) )  * 8 #
                                  ↑
  OS       	DS
                  3 4 25 6 5 * - / 8 * +

 <script type="text/javascript">

 

//中缀表达式转后缀表达式
var ie2se = function(mExp){
	var exp2array = function(exp){
		var ret = [];
		exp.replace(/([^\d])|(\d*)/g,function(s,a,b){if(a){ret.push(a);}if(b){ret.push(b)}});
		return ret.slice(0);
	};
	//将中缀表达式打散为数组形式
	var remExp = exp2array(mExp);
	//运算符栈和数据栈
	var OS = [],DS = [];
	//换算运算符优先级
	var r = /(?:([+-])|([*\/])|([\(\)]))/;
	var getPRI = function(o){
		r.test(o);
		return RegExp.$2?1:RegExp.$3?2:0;
	};
	var tmpItem = null,OSTop = null,pti = 0,ptt = 0;
	while(remExp.length){
		//取剩余表达式中第一个元素
		tmpItem = remExp.shift();
		OSTop = OS[0];
		if(isNaN(tmpItem)){//运算符
			pti = getPRI(tmpItem);
			ptt = getPRI(OSTop);
			if(pti>ptt){//优先级高于OS[0]
				if(tmpItem!=')'){//运算符不是右括号
					OS.unshift(tmpItem);
				}else{
					DS.push(OS.shift());
					OS.shift();//丢掉'(';
				}
			}else{//优先级低于或等于OS[0]
				//循环判断,直至OS[0]优先级大于当前运算符
				while(OS.length&&OS[0]!='('&&pti<=getPRI(OS[0])){
					DS.push(OS.shift());
				}
				OS.unshift(tmpItem);
			}
		}else{//数据
			DS.push(tmpItem);
		}
	}
	//剩余表达式为空后,将OS栈的元素都push到DS栈
	while(OS.length){DS.push(OS.shift());}
	return DS.slice(0);
};

//后缀表达式求值
var suffix_compute = function(suffixExp){
	var ret = suffixExp.slice(0);
	while(ret.length>1){
		var idx = 0;//第一个运算符出现的位置
		for(var i=0;i<ret.length;i++){if(isNaN(ret[i])){idx = i-2;break;}}
		//取出该位置前及其前两个元素
		var a = ret.splice(idx,1);
		var b = ret.splice(idx,1);
		var o = ret.splice(idx,1);
		//计算
		var e = eval('('+a+')'+o+'('+b+')');
		//计算结果插入到该位置
		ret.splice(idx,0,e);
	}
	return ret[0];
};

var me = '3+4/(25-(6*5))*8';
var se = ie2se(me);
var d = suffix_compute(se);
document.write('<h3>中缀表达式转后缀表达式计算结果:</h3>'+me+' = '+eval(me)+'<br/>'+se+' = '+d);
</script>

 



评论: 0 | 引用: 0 | 查看次数: 1830
发表评论
昵 称:
密 码: 游客发言不需要密码.
内 容:
验证码: 验证码
选 项:
虽然发表评论不用注册,但是为了保护您的发言权,建议您注册帐号.
字数限制 1000 字 | UBB代码 关闭 | [img]标签 关闭