中缀表达式转后缀表达式 javascript版
下一篇是后缀表达式的求值
完整的中缀转后缀,并求值的代码文件在这里
中缀转后缀表达式的算法概要描述
/** * 中缀表达式转换成 后缀表达式 * * 栈A,后缀串B * 源S,从左往右读入S * 1. 操作数直接添加到B * 2. ( 直接入栈 * 3. ) 从栈A中依次弹出操作符添加到B,直到弹出( * 4. 操作符,如果栈顶元素的优先级比当前高,则弹出栈顶元素添加到B,直到栈顶元素小于当前操作符,操作符入栈A * 5. 函数递归处理 * 6. S读完后,如果栈非空,弹出所有元素依次追加到B * * 中缀 1+2*(6/2+3*2+7*(2*2))+2 * => * 后缀 1262/32*+722**+*+2+ */
测试代码
var nodelist=string_to_nodelist('1+2*(6/2+3*2+7*(2*2))+2'); var post_stock=postfix(nodelist); alert(post_stock.print());
/** 节点定义 **/ function node(i_type/*1 操作数 2. 操作符 3 函数*/,s_value/*字符*/,i_level/* 1 + - 2 * / 3 函数 4 () */) { return {type:i_type,value:s_value,level:i_level,print:function(){return s_value;}}; }//fun /** 栈定义 **/ function stock() { var stock=new Array(); /*入栈*/ function stock_push(s_value) { stock[stock.length]=s_value; }//fun /*出栈*/ function stock_pop() { if( stock.length < 1 ) return null; var value=stock[stock.length-1]; stock.splice(stock.length-1,1);//删除元素 return value; }//fun /*顶部元素*/ function stock_top() { if( stock.length < 1 ) return null; return stock[stock.length-1]; }//fun /*大小*/ function stock_size() { return stock.length; }//fun //for debug function stock_print() { var s=''; for(var i=stock.length-1;i>=0;i--) if( typeof stock[i].print != undefined ) s += stock[i].print(); else s +=stock[i]; return s; }//fun return {push:stock_push,pop:stock_pop,top:stock_top,size:stock_size,print:stock_print}; }//fun
function string_to_nodelist(expression) { var index=0; var node_list=new Array(); var head_2='', head_3=''; //先解析出每个单位 while( index < expression.length ) { head_2=expression.substr(index,2); head_3=expression.substr(index,3); if( ('log'==head_3) || ('cos'==head_3) || ('sin'==head_3)|| ('tan'==head_3) ) { node_list[node_list.length]=new node(3,head_3,3); index+=3; }//if else if( ('ln'==head_2)) { node_list[node_list.length]=new node(3,head_2,3); index+=2; }//if else if( '+' == expression[index] || '-' == expression[index] ) { node_list[node_list.length]=new node(2,expression[index],1); index+=1; } else if( '*' == expression[index] || '/' == expression[index] ) { node_list[node_list.length]=new node(2,expression[index],2); index+=1; } else if( '(' == expression[index] || ')' == expression[index] ) { node_list[node_list.length]=new node(2,expression[index],4); index+=1; } else { var len=1; while( (index+len <expression.length )&&(expression[index+len] <= '9') && (expression[index+len] >= '0') ) { len++; }//while node_list[node_list.length]=new node(1,expression.substr(index,len),0); index += len; }// }//while return node_list; }//fun function postfix(node_list) { var stock_out=new stock();//后缀表达式,用栈表示 从底到上 对应 从左到右 var stock_return =new stock();//返回的后缀表达式,从上到下,对应表达式的左到右 var stock_opr=new stock();//保存转换过程中的运算符栈 var index=0; while( index < node_list.length ) { switch(node_list[index].type) { case 1://#1. 操作数直接添加到S {//操作数 stock_out.push(node_list[index]); index++; break; }//case case 2: { if( '(' == node_list[index].value )//2. ( 直接入栈 stock_opr.push(node_list[index]); else if( ')' == node_list[index].value)//3. ) 从栈A中依次弹出操作符添加到S,直到弹出( { while( (null != stock_opr.top()) && ('(' != (stock_opr.top()).value) ) stock_out.push(stock_opr.pop()); if( (null == stock_opr.top() ) || '(' != (stock_opr.top()).value ) return null;//error stock_opr.pop();//弹出( }//else if else //4. 操作符,如果栈顶元素的优先级比当前高,则弹出栈顶元素添加到S,直到栈顶元素小于或等于当前操作符,操作符入栈A { while( (null != stock_opr.top()) && (('(' != stock_opr.top().value))&&((stock_opr.top()).level >= node_list[index].level) ) stock_out.push(stock_opr.pop()); stock_opr.push(node_list[index]); }//else index++; break; }//case case 3: {//5. 函数递归处理 var sub_nodelist=new Array();//存放函数后面的参数 var left_num=0; var fun=node_list[index].value;//函数 index++; while( (null !=node_list[index]) && ((2 != node_list[index].type) || ('(' ==node_list[index].value )||((left_num>0) )) ) { if( '('== node_list[index].value ) left_num++; if( ')' == node_list[index].value ) left_num--; sub_nodelist[sub_nodelist.length]=node_list[index]; index++; }//while
//这里的calculate 是对后缀表达式的求值实现
var sub_value= calculate(postfix(sub_nodelist));
if( isNaN(sub_value) ) return null; switch( fun) {
/**
* 这里依次处理你需要在四则运算中支持的函数
* 如
* case 'log':
* { * sub_value=Math.log(sub_value); * stock_out.push(new node(1,sub_value,0));//将结果放入 * break; * }//case
**/ default: return null; }//swtich }//case default: break; }//switch }//while //6. S读完后,如果栈非空,弹出所有元素依次追加到S while( null != stock_opr.top() ) stock_out.push(stock_opr.pop()); while( null != stock_out.top()) stock_return.push(stock_out.pop()); return stock_return; }//fun