JavaScript栈应用:中缀转后缀表达式及求值实现
本文详解JavaScript中栈在表达式求值中的应用。通过栈结构处理操作符优先级,将中缀表达式转换为后缀表达式,并遍历后缀式进行数值计算。文章提供完整代码示例,解析入栈出栈逻辑及边界处理,适用于数据结构学习与算法实现参考。
栈在表达式求值中的应用概述
本文通过具体实例,深入解析JavaScript中栈数据结构在表达式求值问题上的应用,旨在为读者提供清晰的参考与学习思路。
接下来探讨一个经典的表达式求值场景,其核心难点在于操作符优先级的处理。日常书写多为中缀表达式,存在复杂的优先级规则;而后缀表达式则消除了这些优先级歧义。下文将对比两种表达式的差异。
中缀表达式示例:a*b+c*d-e/f 后缀表达式示例:ab*cd*+ef/-
中缀表达式转后缀表达式的栈逻辑
从中缀表达式转换为后缀形式具有一定难度,但利用栈的数据结构特性可以高效实现。下面详细阐述这一转换背后的核心逻辑。
在转换过程中,若遇到非操作符字符,直接将其追加到后缀表达式的存储结果中。
当遇到左括号“(”时,将其压入栈内,仅当匹配到右括号“)”时才弹出。 遇到右括号“)”时,将栈顶至左括号“(”之间的所有操作符依次弹出,并追加到存储结果中。 对于“*”和“/”等高优先级操作符,需判断栈顶操作符的优先级是否低于当前操作符。 若栈顶优先级较低,则当前操作符直接入栈;若栈顶优先级较高或相等,则将栈顶操作符弹出并加入结果,随后当前操作符入栈。 字符串遍历结束后,将栈内剩余的操作符依次弹出,追加至存储结果中,完成转换。
为便于理解,以上述例子再次演示转换过程:a*b+c*d-e/f
初始阶段,“a”和“b”被存入结果区,“*”压入栈,此时栈内仅含“*”。 遇到“+”时,因“*”优先级高于“+”,故“*”弹出至结果区,“+”入栈,结果区变为“ab*”,栈内变为“+”。 随后遇到“c”,直接存入结果区,结果区更新为“ab*c”,栈内仍为“+”。 接着遇到“*”和“d”,因栈顶“+”优先级低于“*”,故“*”入栈,栈内变为“+*” ,结果区更新为“ab*cd”。 再遇到“-”,因栈顶“*”优先级高于“-”,故“*”和“+”依次弹出至结果区,“-”入栈,结果区变为“ab*cd*+”。 后续步骤逻辑一致,不再赘述。
JavaScript转换代码实现
下面使用JavaScript代码实现上述转换逻辑。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
<script type="text/javascript">
function midTOLast(a){
var a_len=a.length;
var myArray=new Array();
b='';
for(var i=0;i<a_len;i++){
switch (a[i]){
case '(':
{
myArray.push(a[i]);
break;
}
case ')'://如果是)则将栈中左括号之前的对象弹出
{
if(myArray.length==0){
return false;
}
temp=myArray.pop();//非空,弹出对象
while(temp!='('){//只要不是左括号,则全部弹出
b+=temp;//并输出到后缀表达式中
if(myArray.length==0){//保证栈为空
break;
}
temp=myArray.pop();
}
break;
}
case '*':
case '/':
{
if(myArray.length==0){//如果栈为空则直接入栈
myArray.push(a[i]);
}else{
temp=myArray[myArray.length-1];
if(temp=='+'||temp=='-'){//如果遇到高的,则遇到的继续入栈
myArray.push(a[i]);//遇到的入栈
}
}
break;
}
case '+':
case '-':
{
if(myArray.length==0){//如果栈为空则直接入栈
myArray.push(a[i]);
}else{
temp=myArray[myArray.length-1];
if(temp=='/'||temp=='*'){//如果遇到低的,则栈中的出栈,遇到的入栈
while(myArray.length!=0){
temp=myArray.pop();//栈中的出栈
b+=temp;//保存到存储空间
}
myArray.push(a[i]);//遇到的入栈
}
}
break;
}
default:
{
b+=a[i];
break;
}
}
}
//最后将栈中剩下的操作符输出
while(myArray.length!=0){
temp=myArray.pop();
b+=temp;
}
return true;
}
var x="a*b+c*d-e/f";
midTOLast(x);
alert(b);//ab*cd*+ef/-
</script>
</body>
</html>
需注意,上述程序可能存在细微缺陷,但核心思想已清晰呈现。
后缀表达式的数值计算原理
接下来讲解如何基于后缀表达式计算最终数值结果。
将中缀表达式转化为后缀表达式后,如何进一步计算?仍以该例子为例说明。
中缀表达式:a*b+c*d-e/f 后缀表达式:ab*cd*+ef/-
基本计算思路如下:
遍历后缀表达式字符串,若遇到非操作符字符(如数字或变量),直接压入栈中;若遇到操作符,则从栈中弹出两个元素进行相应运算,并将计算结果重新压入栈内。重复此过程直至遍历结束,此时栈中剩余的唯一值即为表达式的最终结果。
JavaScript计算代码实现
对应的JavaScript实现代码如下:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
<script type="text/javascript">
function getValue(a){
var a_len=a.length,
myArray=new Array();
for(var i=0;i<a_len;i++){
switch (a[i])
{//遇到数值则直接入栈
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
{
myArray.push(a[i]);
break;
}
case '+':
{//遇到操作符则出栈两个元素进行对应操作
temp=myArray.pop()+myArray.pop();
myArray.push(temp);//再将结果入栈
temp=null;
break;
}
case '-':
{
s=myArray.pop();
temp=myArray.pop()-s;
myArray.push(temp);
s=null;temp=null;
break;
}
case '*':
{
temp=myArray.pop()*myArray.pop();
myArray.push(temp);//再将结果入栈
temp=null;
break;
}
case '/':
{
s=myArray.pop();
temp=myArray.pop()/s;
myArray.push(temp);
s=null;temp=null;
break;
}
}
}
return myArray.pop();//算出结果
}
var a="12*34*+36/-";//1*2+3*4-3/6
var b=getValue(a);//13.5
alert(b);
</script>
</body>
</html>
栈的应用场景广泛,还包括进制转换、行编辑程序处理、迷宫求解等,此处不再逐一展开。
更多关于JavaScript相关技术感兴趣的读者,可查阅本站专题:《JavaScript数据结构与算法技巧总结》、《JavaScript数学运算用法总结》、《JavaScript排序算法总结》、《JavaScript遍历算法与技巧总结》、《JavaScript查找算法技巧总结》及《JavaScript错误与调试技巧总结》。
希望本文所述内容能对您的JavaScript程序设计有所帮助。
JS处理含Emoji或中文的字符串转数组乱码问题
2026-11-05 16:12:28
JS怎么使用展开运算符合并对象
2026-11-05 14:42:18
ES6+环境下判断JS对象为空的简洁写法
2026-11-05 12:12:23
怎么通过replacer函数自定义JS中JSON的格式化输出
2026-11-05 11:19:44
JS正则表达式基础:字面量与RegExp构造函数的区别及常用元字符
2026-11-05 11:16:58
