后缀表达式计算
2012-10-16 18:01
176 查看
http://www.cppblog.com/deep2/archive/2008/10/25/65021.aspx
// test20.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include<iostream>
#include<stack>
#include<string>
using namespace std;
class PostExp{
public:
PostExp(string str):evalStr(str){}
int evaluate();
private:
string evalStr;
stack<int> postStack;
};
/**
算式中的数字限定在0~9,因为是通过string分别读取每一个元素,如89被认定为8和9
如果操作数要扩大到9以上,则应该用数组保存算式中的每一个元素
此处为方便起见,只是为了表达后缀表达式的基本算法
*/
int PostExp::evaluate(){//后缀表达式计算
for(string::iterator iter=evalStr.begin(); iter!=evalStr.end(); iter++){//从前至后读取
int x,y,z;
if(*iter>='0' && *iter<='9')
postStack.push(*iter - '0');//如果读到数字,压栈
else{//如果读到操作符,出栈两个操作数,并计算
y=postStack.top();//y保存操作符右边的数字
postStack.pop();
x=postStack.top();//x保存操作符左边的数字
postStack.pop();
switch(*iter){
case '+': z=x+y; break;//z保存计算结果
case '-' : z=x- y; break;
case '*': z=x*y; break;
case '/' : z=x/y; break;
}
postStack.push(z);//把计算结果作为操作数压栈
}
}
return postStack.top();
}
int main(){
PostExp* pe=new PostExp("352*5+-");
cout<<pe->evaluate();
system("pause");
}
=================
/article/7664835.html
比如1+2的后缀表达式为12+;
而栈可以把一般的中缀表达式变成后缀表达式,并且计算后缀表达式得出结果,因此此应用在计算器中非常常用;
(1)如果读入操作数,则直接放入输出字符串;
(2)如果读入一般运算符如+-*/,则放入堆栈,但是放入堆栈之前必须要检查栈顶,并确定栈顶运算符的优先级比放入的运算符的优先级低;如果放入的优先级较低,则需要将栈顶的运算符放入输出字符串;
(3)如果读入(,因为左括号优先级最高,因此放入栈中,但是注意,当左括号放入栈中后,则优先级最低;
(4)如果读入),则将栈中运算符取出放入输出字符串,直到取出(为止,注意:()不输出到输出字符串;
(5)顺序读完表达式,如果栈中还有操作符,则弹出,并放入输出字符串;
(1)如果是操作数,则放入栈中;
(2)如果是操作符,则取出栈中两个操作数,进行运算后,将结果放入栈中;
(3)直到最后栈中只有一个元素,此元素就是计算结果;
输入: 四则运算(支持括号)
输出:结果字符串
[java]
view plaincopyprint?
package org.xiazdong.Calculatorutils;
import java.util.Stack;
/**
* 计算器工具类
* 完成整数、浮点的加、减、乘、除、括号运算
*
* 禁忌:如果出现.5表示0.5,则结果不正确
* @author xiazdong
*
*/
public class CalculatorUtils {
/**
* 将中缀表达式转换成后缀表达式 规则: 1.如果是操作数,则添加到输出流 2.如果是(,则添加栈中;
* 3.如果是),则将栈中操作符移入输出流,直到(为止,()不添加入输出流 4.如果是一般操作符(+-*
* /),则加入栈之前,需要检查栈中的操作符的优先级,如果栈顶优先级比添加的优先级高,则将栈顶操作符移入输出流,否则直接添加操作符;
*/
public static String calculate(String str){
return calculateReversePolish(exchangeToReversePolish(str));
}
private static String exchangeToReversePolish(String str) {
// 1.创建Stack
Stack<String> s = new Stack<String>();
// 2.创建输出流字符串
StringBuilder builder = new StringBuilder();
// 3.解析中缀表达式
// 3.1 如果是读到数字,则接着读,直到读到操作符为止
for (int i = 0, numLenCount = 1; i < str.length(); i += numLenCount) {
char ch = str.charAt(i);
String operand = ch + "";
numLenCount = 1;
if ((ch + "").matches("\\d{1}")) {
numLenCount = 1;
char nextChar = 0;
if ((i + numLenCount) < str.length()) { // 下一个字符是否超过边界长度
nextChar = str.charAt(i + numLenCount);
while ((nextChar + "").matches("[.\\d{1}]")) {
operand += nextChar;
if ((i + numLenCount + 1) < str.length()) {
nextChar = str.charAt(i + numLenCount + 1);
numLenCount++;
} else {
numLenCount++;
break;
}
}
}
operand += " ";
builder.append(operand);
} else {
if (ch == '(') {
s.push(ch + "");
} else if (ch == '+' || ch == '-') {
while (s.size() > 0 && s.peek().matches("[-+*/]")) {
builder.append(s.pop() + " ");
}
s.push(ch + "");
} else if (ch == '*' || ch == '/') {
while (s.size() > 0 && s.peek().matches("[*/]")) {
builder.append(s.pop() + " ");
}
s.push(ch + "");
} else if (ch == ')') {
while (s.size() > 0 && !s.peek().equals("(")) {
builder.append(s.pop() + " ");
}
s.pop();
}
}
}
while (s.size() > 0) {
builder.append(s.pop() + " ");
}
System.out.println(builder);
return builder.toString();
}
/**
* 计算后缀表达式
*
*/
private static String calculateReversePolish(String str) {
String[] splitStr = str.split(" ");
Stack<String> s = new Stack<String>();
for (int i = 0; i < splitStr.length; i++) {
String ch = splitStr[i];
if (ch.matches("\\d+.\\d+")||ch.matches("\\d+")) {
s.push(ch);
} else {
if (s.size() >= 2) {
String c1 = s.pop();
String c2 = s.pop();
if (ch.equals("+")) {
if(c1.contains(".")||c2.contains(".")){
s.push(String.valueOf((Double.parseDouble(c2 + "") + Double
.parseDouble(c1 + ""))));
}
else{
s.push(String.valueOf((Integer.parseInt(c2 + "") + Integer
.parseInt(c1 + ""))));
}
} else if ("-".equals(ch)) {
if(c1.contains(".")||c2.contains(".")){
s.push(String.valueOf((Double.parseDouble(c2 + "") - Double
.parseDouble(c1 + ""))));
}
else{
s.push(String.valueOf((Integer.parseInt(c2 + "") - Integer
.parseInt(c1 + ""))));
}
} else if ("*".equals(ch)) {
if(c1.contains(".")||c2.contains(".")){
s.push(String.valueOf((Double.parseDouble(c2 + "") * Double
.parseDouble(c1 + ""))));
}
else{
s.push(String.valueOf((Integer.parseInt(c2 + "") * Integer
.parseInt(c1 + ""))));
}
} else if ("/".equals(ch)) {
s.push(String.valueOf((Double.parseDouble(c2 + "") / Double
.parseDouble(c1 + ""))));
}
} else {
System.out.println("式子有问题!");
return null;
}
}
}
return s.pop();
}
}
// test20.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include<iostream>
#include<stack>
#include<string>
using namespace std;
class PostExp{
public:
PostExp(string str):evalStr(str){}
int evaluate();
private:
string evalStr;
stack<int> postStack;
};
/**
算式中的数字限定在0~9,因为是通过string分别读取每一个元素,如89被认定为8和9
如果操作数要扩大到9以上,则应该用数组保存算式中的每一个元素
此处为方便起见,只是为了表达后缀表达式的基本算法
*/
int PostExp::evaluate(){//后缀表达式计算
for(string::iterator iter=evalStr.begin(); iter!=evalStr.end(); iter++){//从前至后读取
int x,y,z;
if(*iter>='0' && *iter<='9')
postStack.push(*iter - '0');//如果读到数字,压栈
else{//如果读到操作符,出栈两个操作数,并计算
y=postStack.top();//y保存操作符右边的数字
postStack.pop();
x=postStack.top();//x保存操作符左边的数字
postStack.pop();
switch(*iter){
case '+': z=x+y; break;//z保存计算结果
case '-' : z=x- y; break;
case '*': z=x*y; break;
case '/' : z=x/y; break;
}
postStack.push(z);//把计算结果作为操作数压栈
}
}
return postStack.top();
}
int main(){
PostExp* pe=new PostExp("352*5+-");
cout<<pe->evaluate();
system("pause");
}
=================
/article/7664835.html
一、后缀表达式介绍
后缀表达式的特点就是计算机运算非常方便,需要用到栈;计算机处理过程只需要顺序读入,如果遇到数字,则放入栈中,如果是运算符,则将两个栈中数字取出进行运算;比如1+2的后缀表达式为12+;
而栈可以把一般的中缀表达式变成后缀表达式,并且计算后缀表达式得出结果,因此此应用在计算器中非常常用;
二、中缀表达式转换成后缀表达式
此方法需要遵循几个规则:(1)如果读入操作数,则直接放入输出字符串;
(2)如果读入一般运算符如+-*/,则放入堆栈,但是放入堆栈之前必须要检查栈顶,并确定栈顶运算符的优先级比放入的运算符的优先级低;如果放入的优先级较低,则需要将栈顶的运算符放入输出字符串;
(3)如果读入(,因为左括号优先级最高,因此放入栈中,但是注意,当左括号放入栈中后,则优先级最低;
(4)如果读入),则将栈中运算符取出放入输出字符串,直到取出(为止,注意:()不输出到输出字符串;
(5)顺序读完表达式,如果栈中还有操作符,则弹出,并放入输出字符串;
三、计算后缀表达式
规则如下:(1)如果是操作数,则放入栈中;
(2)如果是操作符,则取出栈中两个操作数,进行运算后,将结果放入栈中;
(3)直到最后栈中只有一个元素,此元素就是计算结果;
四、代码
以下代码是计算器的辅助代码,通过此代码可以快速进行计算。输入: 四则运算(支持括号)
输出:结果字符串
[java]
view plaincopyprint?
package org.xiazdong.Calculatorutils;
import java.util.Stack;
/**
* 计算器工具类
* 完成整数、浮点的加、减、乘、除、括号运算
*
* 禁忌:如果出现.5表示0.5,则结果不正确
* @author xiazdong
*
*/
public class CalculatorUtils {
/**
* 将中缀表达式转换成后缀表达式 规则: 1.如果是操作数,则添加到输出流 2.如果是(,则添加栈中;
* 3.如果是),则将栈中操作符移入输出流,直到(为止,()不添加入输出流 4.如果是一般操作符(+-*
* /),则加入栈之前,需要检查栈中的操作符的优先级,如果栈顶优先级比添加的优先级高,则将栈顶操作符移入输出流,否则直接添加操作符;
*/
public static String calculate(String str){
return calculateReversePolish(exchangeToReversePolish(str));
}
private static String exchangeToReversePolish(String str) {
// 1.创建Stack
Stack<String> s = new Stack<String>();
// 2.创建输出流字符串
StringBuilder builder = new StringBuilder();
// 3.解析中缀表达式
// 3.1 如果是读到数字,则接着读,直到读到操作符为止
for (int i = 0, numLenCount = 1; i < str.length(); i += numLenCount) {
char ch = str.charAt(i);
String operand = ch + "";
numLenCount = 1;
if ((ch + "").matches("\\d{1}")) {
numLenCount = 1;
char nextChar = 0;
if ((i + numLenCount) < str.length()) { // 下一个字符是否超过边界长度
nextChar = str.charAt(i + numLenCount);
while ((nextChar + "").matches("[.\\d{1}]")) {
operand += nextChar;
if ((i + numLenCount + 1) < str.length()) {
nextChar = str.charAt(i + numLenCount + 1);
numLenCount++;
} else {
numLenCount++;
break;
}
}
}
operand += " ";
builder.append(operand);
} else {
if (ch == '(') {
s.push(ch + "");
} else if (ch == '+' || ch == '-') {
while (s.size() > 0 && s.peek().matches("[-+*/]")) {
builder.append(s.pop() + " ");
}
s.push(ch + "");
} else if (ch == '*' || ch == '/') {
while (s.size() > 0 && s.peek().matches("[*/]")) {
builder.append(s.pop() + " ");
}
s.push(ch + "");
} else if (ch == ')') {
while (s.size() > 0 && !s.peek().equals("(")) {
builder.append(s.pop() + " ");
}
s.pop();
}
}
}
while (s.size() > 0) {
builder.append(s.pop() + " ");
}
System.out.println(builder);
return builder.toString();
}
/**
* 计算后缀表达式
*
*/
private static String calculateReversePolish(String str) {
String[] splitStr = str.split(" ");
Stack<String> s = new Stack<String>();
for (int i = 0; i < splitStr.length; i++) {
String ch = splitStr[i];
if (ch.matches("\\d+.\\d+")||ch.matches("\\d+")) {
s.push(ch);
} else {
if (s.size() >= 2) {
String c1 = s.pop();
String c2 = s.pop();
if (ch.equals("+")) {
if(c1.contains(".")||c2.contains(".")){
s.push(String.valueOf((Double.parseDouble(c2 + "") + Double
.parseDouble(c1 + ""))));
}
else{
s.push(String.valueOf((Integer.parseInt(c2 + "") + Integer
.parseInt(c1 + ""))));
}
} else if ("-".equals(ch)) {
if(c1.contains(".")||c2.contains(".")){
s.push(String.valueOf((Double.parseDouble(c2 + "") - Double
.parseDouble(c1 + ""))));
}
else{
s.push(String.valueOf((Integer.parseInt(c2 + "") - Integer
.parseInt(c1 + ""))));
}
} else if ("*".equals(ch)) {
if(c1.contains(".")||c2.contains(".")){
s.push(String.valueOf((Double.parseDouble(c2 + "") * Double
.parseDouble(c1 + ""))));
}
else{
s.push(String.valueOf((Integer.parseInt(c2 + "") * Integer
.parseInt(c1 + ""))));
}
} else if ("/".equals(ch)) {
s.push(String.valueOf((Double.parseDouble(c2 + "") / Double
.parseDouble(c1 + ""))));
}
} else {
System.out.println("式子有问题!");
return null;
}
}
}
return s.pop();
}
}
相关文章推荐
- 九度oj 1101 计算后缀表达式
- 中缀表达式转后缀表达式并计算
- 栈应用(中缀表达式转后缀表达式并计算后缀表达式的值)
- 第九周(11.11-11.17)----结对项目----计算后缀表达式
- 后缀表达式的计算
- 利用顺序栈计算后缀表达式(逆波兰表达式)
- 后缀表达式计算
- 使用栈计算后缀表达式
- 中缀表达式转后缀表达式并计算(十位以内)
- 图解后缀表达式的计算过程
- 蓝桥杯 算法训练:表达式计算 中缀表达式变后缀表达式
- 1686 Lazy Math Instructor 计算表达式 后缀表达式 +-*/^()
- 中缀算术转后缀算术表达式并计算的函数
- java实现中缀表达式转后缀表达式并且计算
- c++ 中缀表达式转后缀表达式并计算值
- 不用后缀表达式进行表达式计算(加、减、乘、除、整除、取余、指数)
- 利用STL计算后缀表达式
- 编写计算后缀表达式的值时出现内存方面的debug error.
- 1005. 后缀表达式计算
- 数据结构-栈-计算后缀表达式