栈应用二(表达式求值)

问题;设计一个程序,演示用算符优先法对算术表达式求值的过程。利用算符优先关系,实现对算术四则混合运算表达式的求值。
(1)输入的形式:表达式,例如3+2*6-4
     包含的运算符只能有‘+‘ 、‘-‘ 、‘*‘ 、‘/‘(目前还不兼容括号) ;
(2)输出的形式:运算结果,例如3+2*6-4=11;

(3)程序所能达到的功能:对表达式求值并输出;示例:①3+2*6-4 ②30+20*6-80 ③2*7-3*5-3

思路:1.程序扫描表达式,一个一个的扫描
2.当发现这个字符是数字的时候,直接入数栈(需要处理多位数字字符)
3.如果发现是运算符
3.1如果符号栈为空,就直接入符号栈
3.2如果符号栈不为空,就要判读。如果当前运算符的优先级小于等于符号栈顶的这个运算符的优先级,就计算,并把计算结果入数栈,然后把当前符号入栈(兼容多个减号一起出现,计算先后顺序的问题)
3.3如果符号栈不为空,就要判读。如果当前运算符的优先级大于符号栈顶的这个运算符的优先级,就入栈
4.当扫描完毕后,就依次弹出数栈和符号栈的数据,并计算,最终留在数栈的值,就是运算结果。

代码:

  1 <?php
  2 //栈的应用 表达式求值:3+2*6-2
  3 class Stack
  4 {
  5     private $top=-1;//默认是-1, 表示该栈是空的
  6     private $max_size = 100;//栈的最大容量
  7     private $stack = array();
  8
  9     /**
 10      * 入栈
 11      */
 12     public function push($val)
 13     {
 14         if($this->top == $this->max_size-1)//栈满
 15         {
 16             return false;
 17         }
 18         $this->top++;
 19         $this->stack[$this->top] = $val;
 20     }
 21
 22     /**
 23      * 出栈
 24      */
 25     public function pop()
 26     {
 27         if($this->top == -1)//栈空
 28         {
 29             return false;
 30         }
 31         $value = $this->stack[$this->top];
 32         $this->top--;
 33         return $value;
 34     }
 35
 36     /**
 37      * 取栈顶元素
 38      */
 39     public function get_top()
 40     {
 41         if($this->top == -1)
 42         {
 43             return false;
 44         }
 45         return $this->stack[$this->top];//返回栈顶的元素,只取,但是不出栈
 46     }
 47
 48     /**
 49      * 判断是否为空栈
 50      */
 51     public function is_empty()
 52     {
 53         if($this->top == -1)
 54         {
 55             return true;
 56         } else {
 57             return false;
 58         }
 59     }
 60
 61     /**
 62      * 判断是不是一个运算符
 63      */
 64     public function is_oper($ch)
 65     {
 66         if($ch==‘+‘ || $ch==‘-‘ || $ch==‘*‘ || $ch==‘/‘)
 67         {
 68             return 1;
 69         } else {
 70             return 0;
 71         }
 72     }
 73
 74     /**
 75      * 判断运算符的优先级
 76      * *和/为1 +和-为0 括号后面改进
 77      */
 78     public function PRI($ch)
 79     {
 80         if($ch==‘*‘ || $ch==‘/‘)
 81         {
 82             return 1;
 83         } else if($ch==‘+‘ || $ch==‘-‘){
 84             return 0;
 85         }
 86     }
 87
 88     /**
 89      * 计算的函数
 90      */
 91     public function get_result($num1, $num2, $oper)
 92     {
 93         $res = 0;
 94         switch($oper){
 95             case ‘+‘:
 96                 $res = $num1 + $num2;
 97                 break;
 98             case ‘-‘:
 99                 $res = $num2 - $num1;//注意顺序
100                 break;
101             case ‘*‘:
102                 $res = $num1 * $num2;
103                 break;
104             case ‘/‘:
105                 $res = $num2 / $num1;//注意顺序
106                 break;
107         }
108         return $res;
109     }
110 }
111
112 /**
113  * 计算(参数校验省略)
114  */
115 function calculator($operStack, $numsStack, $exp)
116 {
117     $index = 0;//$index就是一个扫描标记
118     $len = strlen($exp);
119     $nums = ‘‘;//用于拼接多位数的字符串
120     while(true)
121     {
122         $ch = substr($exp, $index, 1);//从$exp里的$index位置取出一个字符
123         $is_oper = $operStack->is_oper($ch);
124         if($is_oper)//判断$ch是不是运算符
125         {
126             //说明是运算符
127             /**
128              * 1.如果符号栈为空,就直接入栈;
129              * 2.如果符号栈不为空,如果当前运算符的优先级小于等于符号栈顶运算符的优先级,就计算,并把计算结果入数栈,
130              *   然后把当前符号入符号栈;
131              * 3.如果符号栈不为空,如果当前运算符的优先级大于符号栈顶运算符的优先级,就入栈
132              */
133             if($operStack->is_empty())
134             {
135                 $operStack->push($ch);
136             } else {
137                 //判断当前符号跟栈顶符号的运算符优先级
138                 $chPRI = $operStack->PRI($ch);
139                 //只要你准备入符号栈的运算优先级小于等于当前栈栈顶的运算优先级,就一直计算
140                 //直到这个条件不满足,才把当前的符号入符号栈
141                 //并且只要符号栈不为空
142                 while(!$operStack->is_empty() && $chPRI<=$operStack->PRI($operStack->get_top()))//处理2*7-3*5-3这种情况
143                 {
144                     //计算
145                     //从数栈里面依次出两个数
146                     $num1 = $numsStack->pop();
147                     $num2 = $numsStack->pop();
148
149                     //再从符号栈里取出一个运算符
150                     $oper = $operStack->pop();
151                     $res = $operStack->get_result($num1, $num2, $oper);
152
153                     //$res入栈  当前操作符入栈
154                     $numsStack->push($res);
155                 }
156                 $operStack->push($ch);
157             }
158         } else {
159             $nums .= $ch;//处理多位数字
160             //判断数字是否是最后一个,是:直接入栈;否:接着判断下一个字符是否是数字
161             if($index == $len-1)
162             {
163                 $numsStack->push($nums);
164             } else {
165                 //判断下一个字符是否是数字
166                 if($operStack->is_oper(substr($exp, $index+1, 1)))
167                 {
168                     $numsStack->push($nums);
169                     $nums = ‘‘;//置空
170                 }
171             }
172         }
173         $index++;//让$index指向下一个字符
174         if($index == $len)//判断是否扫码完毕
175         {
176             break;//当扫描完毕后,就break
177         }
178     }
179
180     /**
181      * 4.当扫描完毕后,就依次弹出数栈和符号栈的数据,并计算,最终留在数栈的值,就是运算结果
182      */
183     while(!$operStack->is_empty())
184     {
185         $num1 = $numsStack->pop();
186         $num2 = $numsStack->pop();
187         $oper = $operStack->pop();
188         $res = $operStack->get_result($num1, $num2, $oper);
189         $numsStack->push($res);
190     }
191
192     return $numsStack->get_top();
193 }
194
195 $exp = "7*2-5*3-3";
196 $exp = "30+20*6-80";
197 $exp = "3+2*6-4";
198 $numsStack = new Stack();
199 $operStack = new Stack();
200 $res = calculator($operStack, $numsStack, $exp);
201
202 var_dump($res);

时间: 2024-11-08 01:39:38

栈应用二(表达式求值)的相关文章

数据结构 栈的应用 --表达式求值

一: 中缀表达式求值  思想: 需要2个栈,运算对象栈OPND,运算符栈OPTR, 1:将栈OPND初始化为空,栈OPTR初始化为表达式的定界符# 2:扫描表达式,直到遇到结束符# 2.1:当前字符是运算对象,入栈OPND 2.2:当前字符是运算符且优先级比栈OPTR的栈顶运算符优先级高,入栈OPTR,处理下一个字符 2.3:当前字符是运算符且优先级比栈OPTR的栈顶运算符优先级低,则从栈OPND出栈2个运算对象,从栈OPTR出栈一个运算符进行运算,并将运算结果入栈OPND,处理当前字符 2.4

栈的应用——表达式求值

表达式求值是程序设计语言编译中的一个基本问题,它的实现就是对“栈”的典型应用.本文针对表达式求值使用的是最简单直观的算法“算符优先法”. 本文给出两种方式来实现表达式求值,方式一直接利用中缀表达式求值,需要用到两个栈,操作数栈和操作符栈.首先置操作数栈为空栈, 操作符栈仅有“#”一个元素.依次读入表达式中的每个字符,若是操作数则进操作数栈,若是操作符则和操作符栈的栈顶运算符比较优先权作相应操作,直至整个表达式求值完毕.方式二首先把中缀表达式转换为后缀表达式并存储起来,然后利用读出的后缀表达式完成

数据结构(7)----栈与队列之栈的应用四则运算表达式求值

栈与队列之栈的应用四则运算表达式求值 栈在四则运算表达式求值的应用为逆波兰表达式(后缀表达式) 普通算式(中缀表达式):9 + (3 - 1) * 3 + 10 / 2     ---(1) 逆波兰表达式(后缀表达式):9 3 1 - 3 * + 10 2 /         ---(2) 1:逆波兰表达式的计算规则 从左到右遍历表达式的每个数字和符号,遇到数字就进栈,遇到符号,就将处于栈顶的两个数字出栈,进行运算,再把运算结果进栈,一直到最终获得结果.接下来我们以(2)式为例:

将中缀表达式转换为后缀表达式,然后利用栈对表达式求值。

<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script src="js.js"></script> </head> <body> 输入中缀表达式空格分隔 例如 2 + 3 <input type=

c语言:表达式求值实现(包含加减乘除括号)

这道题不难,但是当你认真去编代码的时候,还是要考虑好多细节,所以不能只停留在看懂的层面上,不去实践你永远不知道你到底掌握了没有,加油! 之前的表达式求值不包括括号运算,现将改进后的代码和源代码粘在上面,便于以后的复习. 一.不包括括号运算 #include<iostream> #include<stdio.h> #include<stdlib.h> #include<string> #include<math.h> #define STACK_I

数据结构算法C语言实现(八)--- 3.2栈的应用举例:迷宫求解与表达式求值

一.简介 迷宫求解:类似图的DFS.具体的算法思路可以参考书上的50.51页,不过书上只说了粗略的算法,实现起来还是有很多细节需要注意.大多数只是给了个抽象的名字,甚至参数类型,返回值也没说的很清楚,所以很多需要自己揣摩.这也体现了算法和程序设计语言的特点,算法更侧重本质的描述,而任何编程语言都要照顾到实现的细节以及数据类型等语法方面的需求. 表达式求值: [编码中....] 二.头文件 迷宫求解: 1 //3_2_maze.h 2 /** 3 author:zhaoyu 4 email:[em

栈的应用—算术表达式求值

例三.算术表达式求值 1.问题描述 当一个算术表达式中含有多个运算符,且运算符的优先级不同的情况下,如何才能处理一个算术表达式????? 2.思路 首先我们要知道表达式分为三类:  ①中缀表达式:a+(b-c/d)*e ②前缀表达式+a*-be ③后缀表达式abcd/-e*+ 由于运算符有优先级,所以在计算机中计算一个中缀的表达式非常困难,特别是带括号的更麻烦,而后缀表达式中既无运算符优先又无括号的约束问题因为在后缀表达式中运算符出现的顺序正是计算的顺序,所以计算一个后缀的表达式更简单.所以,可

栈的两个应用:括号匹配的检验和表达式求值

1.     括号匹配的检验 假设表达式中含有3种括号:(),[],{},其嵌套的顺序随意.检验括号是否匹配. 基本思想:在算法中设置一个栈,每读入一个括号,若是右括号,则或者与栈顶匹配的左括号相互消解,或者是不合法的情况:若是左括号,则直接压入栈中.若括号匹配,在算法的开始和结束时,栈都应该是空的. 代码: /* * 判断表达式中的括号是否匹配,匹配输出Yes,否则输出No * {(zhang)+[lei]+{lei}={zhangleilei}} -> Yes * {(zhang)+[lei

NYOJ35 表达式求值 【栈】

表达式求值 时间限制:3000 ms  |  内存限制:65535 KB 难度:4 描述 ACM队的mdd想做一个计算器,但是,他要做的不仅仅是一计算一个A+B的计算器,他想实现随便输入一个表达式都能求出它的值的计算器,现在请你帮助他来实现这个计算器吧. 比如输入:"1+2/4=",程序就输出1.50(结果保留两位小数) 输入 第一行输入一个整数n,共有n组测试数据(n<10). 每组测试数据只有一行,是一个长度不超过1000的字符串,表示这个运算式,每个运算式都是以"