一般我们在做计算器程序的时候,只能让用户输入两个数值计算,但是如果用户的表达式非常复杂呢?如:50-20*80/2-10-5*11,用户需要根据运算符的优先级来依次输入数值进行计算。那么,有没有一个简单点的方法,用户直接输入整个表达式,程序自动判断运算符优先级进行计算,最后得出结果呢?后来在网上查找了一下,发现要实现这个功能,必须要使用栈来实现,于是重新学习了数据结构的知识,根据栈的原理使用javascript完成了这个功能。补充一下,在javascript中,其实提供了一个eval()函数可以实现这个功能,eval()函数本身要强大得多,它可以把一个字符串当作一段程序来执行;这里只模拟它实现计算的底层原理代码。eval()更详细的功能可以参考API文档。
<!DOCTYPE>
<html>
<head>
<title> 使用栈实现 </title>
<meta charset="utf-8"/>
<script type="text/javascript">
function MyStack(){
this.stackTop = -1;// 栈的指针
this.stackSize = 50;// 栈的容量
this.stack = new Array();
// 入栈操作
this.push = function(val){
if(this.stackTop == this.stackSize-1){
alert("栈已经满了");
}
this.stackTop++;
this.stack[this.stackTop] = val;
}
// 出栈操作
this.pop = function(){
if(this.stackTop == -1){
alert("栈内没有数据");
}
var stackTopVal = this.stack[this.stackTop];
this.stackTop--;
return stackTopVal;
}
// 显示栈内的数据
this.show = function(){
if(this.stackTop == -1){
alert("栈内没有数据");
}
for(var i = this.stackTop; i>-1; i--){
alert(this.stack[i]);
}
}
// 判断当前字符是数值还是运算符
this.isOper = function(cha){
if(cha == "+" || cha == "-" || cha == "*" || cha == "/"){
return true;
}else{
return false;
}
}
// 判断栈是否为空
this.isEmpty = function(){
if(this.stackTop == -1){
return true;
}else{
return false;
}
}
// 获取运算符的优先级
this.PRI = function(cha){
if(cha == "*" || cha == "/"){
return 1;
}else if(cha == "+" || cha == "-"){
return 0;
}
}
// 获取栈顶的字符
this.getTop = function(){
return this.stack[this.stackTop];
}
// 计算函数
this.result = function(num1,num2,oper){
var res = 0;
switch(oper){
case '+':
res = Number(num2) + Number(num1);// 数据必须先要转换
break;
case '-':
res = Number(num2) - Number(num1);
break;
case '*':
res = Number(num2) * Number(num1);
break;
case '/':
res = Number(num2) / Number(num1);
break;
}
return res;
}
}
// 定义两个栈:数值栈和运算符栈
var valueStack = new MyStack();
var operStack = new MyStack();
function Count(){
var exp = document.getElementById("exp").value;
var index = 0;// 扫描指针
//var cha = exp.substr(index, 1);
//alert(cha);
while(true){
// 取出字符
var cha = exp.substr(index, 1);
// 判断cha
if(operStack.isOper(cha)){
// 是运算符,判断运算符栈是否为空
if(operStack.isEmpty()){
// 放入运算符栈
operStack.push(cha);
}else{
// 判断运算符的优先级
var chaPRI = operStack.PRI(cha);
var stackPRI = operStack.PRI(operStack.getTop());
if(chaPRI <= stackPRI){
// 从数值栈出栈两个数值
var num1 = valueStack.pop();
var num2 = valueStack.pop();
// 再从运算符栈出栈一个运算符
var oper = operStack.pop();
// 调用计算函数
var res = operStack.result(num1, num2, oper);
// 把结果放入数值栈
valueStack.push(res);
// 把当前运算符放入运算符栈
operStack.push(cha);
}else{
operStack.push(cha);
}
}
}else{
// 是数值,放入数值栈
valueStack.push(cha);
}
// 让扫描指针指向下一个字符
index++;
// 判断是否扫描完毕,扫描完毕,break.
if(index == exp.length){
break;
}
}
// 如果运算符栈不空就一直计算
while(!operStack.isEmpty()){
// 从数值栈出栈两个数值
var num1 = valueStack.pop();
var num2 = valueStack.pop();
// 再从运算符栈出栈一个运算符
var oper = operStack.pop();
// 调用计算函数
var res = operStack.result(num1, num2, oper);
// 把结果放入数值栈
valueStack.push(res);
}
// 在退出循环后,数值栈中留下的数值,就是最终结果
alert(exp+'结果='+valueStack.getTop());
}
</script>
</head>
<body>
<input type="text" id="exp" value="1+2*3+2"/>
<input type="button" value="计算" onClick="Count();"/>
</body>
</html>