运用栈对算数表达式求值

public class StackTool {
	/**
	 * 判断括号是否匹配
	 * 如果是左括号就入栈,右括号则与栈顶元素匹配,如果匹配则删除栈顶元素
	 * @param expression
	 */
	public static void judge(String expression){
		//模拟一个栈
		char[] stack = new char[100];
		int top = 0;
		
		for(int i=0;i<expression.length();i++){
			char val = expression.charAt(i);
			//入栈操作
			if(val=='('||val=='['||val=='{'){
				stack[top++]=val;
			}else if(val==')'){
				//出栈前先判断栈中是否还有元素
				if(top<=0||stack[--top]!='('){
					System.out.println("match failed");
					return;
				}
			}else if(val==']'){
				if(top<=0||stack[--top]!='['){
					System.out.println("match failed");
					return;
				}
			}else if(val=='}'){
				if(top<=0||stack[--top]!='{'){
					System.out.println("match failed");
					return;
				}
			}
		}
		System.out.println(top==0?"match success!":"match failed");
	}
	
	/**
	 * 计算后缀表达式,各个值用空格隔开
	 * 后缀表达式:不包含括号,运算符放在两个运算对象的后面,所有的计算按照运算符出现的顺序从左向右计算
	 * 例如:(2+1)*3   2 1 + 3 *  (8-5)*(4-2)  8 5 - 4 2 - *
	 * @param expression
	 * @return
	 */
	public static double calSuffixExpression(String expression){
		double[] stack = new double[100];
		int top = 0;
		String[] strs = expression.split(" ");
		for(String str : strs){
			if("+".equals(str)){
				double first = stack[--top];
				double second = stack[--top];
				stack[top++] = first + second;
			}else if("-".equals(str)){
				double first = stack[--top];
				double second = stack[--top];
				stack[top++] = first - second;
			}
			else if("*".equals(str)){
				double first = stack[--top];
				double second = stack[--top];
				stack[top++] = first * second;
			}
			else if("/".equals(str)){
				double first = stack[--top];
				double second = stack[--top];
				stack[top++] = first / second;
			}else{
				stack[top++] = Double.parseDouble(str);
			}
		}
		return stack[0];
	}
	
	/**
	 * 计算中缀表达式,中缀表达式就是一般的数学表达式
	 * 思路:如果后面的操作符比前面的操作符运算优先级高那么前面的操作符必须延迟计算,
	 * 如果后面的操作符运算优先级比前面的操作符低或者同级,那么前面的操作符就可以进行运算了
	 * 例子:a+b*c/d
	 * 首先将a入操作数栈,接着将+入操作符栈,接着b入操作数栈,此时还不能计算,还要看后面的操作符
	 * 接着将*入操作符栈,将c入操作数栈。此时碰到/号,与前面的*号同级,因此*号可以计算
	 * 将*出栈,将b,c出栈计算得到结果入操作数栈,将/号入操作符栈,将d入栈.此时表达式已经完毕
	 * 分析过程
	 *   操作数栈                                    操作符栈
	 *   a										a入栈
	 *   a					    +				+入栈
	 *   a b					+				b入栈
	 *   a b					+ *				*入栈  *号优先级比+高,入栈
	 *   a b c					+ *				c入栈
	 *   -------------------------------碰到/  /号与*号优先级相同  出栈计算
	 *   a						+        b,c,*出栈		算b*c  
	 *   a b*c					+ /				b*c,/入栈
	 *   a b*c d				+ /				d入栈    此时表达式完毕
	 *   a 						+       b*c,d,/出栈     算b*c/d
	 *   a b*c/d				+       b*c/d入栈
	 *   								a,b*c/d,+出栈  算a+b*c/d得到结果
	 *   
	 *   -------------------------------------------------------
	 *   加强:带括号
	 *   a*(b+c)----把括号里的内容就当做一个中缀表达式求值,并且左括号优先级最高使得前面的操作符不能运算
	 *   右括号优先级最低迫使括号里的操作符运算完
	 * @param expression
	 * @return
	 */
	public static double calInfixExpression(String expression){
		double[] vals = new double[100];//操作数栈
		int valTop = 0;
		char[] ops = new char[100];//操作符栈
		int opTop = 0;
		
		String[] strs = expression.split(" ");
		for(String str : strs){
			if("+".equals(str)||"-".equals(str)){
				//符号栈不为空
				if(opTop>0){
					int cnt = opTop-1;
					char op = ops[cnt];//获取当前栈顶符号
					//因为当前符号为+或者-,所以前面那个符号一定能够计算
					if(op=='+'||op=='-'||op=='*'||op=='/'){
						opTop--;
						double second = vals[--valTop];
						double first = vals[--valTop];
						if(op=='+'){
							vals[valTop++] = first + second;
						}else if(op=='-'){
							vals[valTop++] = first - second;
						}else if(op=='*'){
							vals[valTop++] = first * second;
						}else if(op=='/'){
							vals[valTop++] = first / second;
						}
					}
				}
				ops[opTop++] = str.charAt(0);//当前操作符入栈
			}
			else if("*".equals(str)||"/".equals(str)){
				//符号栈不为空
				if(opTop>0){
					int cnt = opTop-1;
					char op = ops[cnt];
					//只有前面是*,/才可以计算
					if(op=='*'||op=='/'){
						opTop--;//可以计算将op出栈
						double second = vals[--valTop];
						double first = vals[--valTop];
						if(op=='*'){
							vals[valTop++] = first * second;
						}else if(op=='/'){
							vals[valTop++] = first / second;
						}
					}
				}
				ops[opTop++] = str.charAt(0);//当前操作符入栈
			}
			//优先级最高,前面的运算符不能计算
			else if("(".equals(str)){
				ops[opTop++] = str.charAt(0);
			}
			//碰到右括号,算完括号里的表达式内容
			else if(")".equals(str)){
				char op = ops[--opTop];
				//如果出栈的符号是‘(’则说明表达式已经算完了
				while(op!='('){
					double second = vals[--valTop];
					double first = vals[--valTop];
					if(op=='+'){
						vals[valTop++] = first + second;
					}else if(op=='-'){
						vals[valTop++] = first - second;
					}else if(op=='*'){
						vals[valTop++] = first * second;
					}else if(op=='/'){
						vals[valTop++] = first / second;
					}
					op = ops[--opTop];
				}
			}
			else{
				vals[valTop++] = Double.parseDouble(str);
			}
		}
		//字符串处理完毕,栈中剩下的操作符和操作数中栈顶优先级大于栈底,依次出栈计算就可
		while(opTop>0){
			char op = ops[--opTop];
			double second = vals[--valTop];
			double first = vals[--valTop];
			if(op=='+'){
				vals[valTop++] = first + second;
			}else if(op=='-'){
				vals[valTop++] = first - second;
			}else if(op=='*'){
				vals[valTop++] = first * second;
			}else if(op=='/'){
				vals[valTop++] = first / second;
			}
		}
		return vals[0];
	}

}

下面是一个基于C语言实现算数表达式求值的代码示例: ```c #include <stdio.h> #include <stdlib.h> #define MAX_SIZE 100 // 定义数据结构 typedef struct Stack { int top; // 顶指针 int data[MAX_SIZE]; // 存储数据的数组 } Stack; // 初始化 void init(Stack *stack) { stack->top = -1; } // 判断是否为空 int isEmpty(Stack *stack) { return stack->top == -1; } // 判断是否已满 int isFull(Stack *stack) { return stack->top == MAX_SIZE - 1; } // 入 void push(Stack *stack, int item) { if (isFull(stack)) { printf("Stack Overflow.\n"); exit(EXIT_FAILURE); } stack->data[++stack->top] = item; } // 出 int pop(Stack *stack) { if (isEmpty(stack)) { printf("Stack Underflow.\n"); exit(EXIT_FAILURE); } return stack->data[stack->top--]; } // 取顶元素 int peek(Stack *stack) { if (isEmpty(stack)) { printf("Stack Underflow.\n"); exit(EXIT_FAILURE); } return stack->data[stack->top]; } // 判断是否为操作符 int isOperator(char ch) { return ch == '+' || ch == '-' || ch == '*' || ch == '/'; } // 获取操作符的优先级,返回值越大优先级越高 int getPriority(char op) { switch (op) { case '+': case '-': return 1; case '*': case '/': return 2; default: return 0; } } // 对表达式进行求值 int evaluate(char *expression) { Stack operands, operators; int i, n, val, op1, op2; char ch, prev; // 初始化两个 init(&operands); init(&operators); n = strlen(expression); prev = '\0'; for (i = 0; i < n; i++) { ch = expression[i]; // 如果是空白字符,则跳过 if (isspace(ch)) { continue; } // 如果是数字,则将其入 if (isdigit(ch)) { val = ch - '0'; // 取多位数 while (i + 1 < n && isdigit(expression[i + 1])) { val = val * 10 + (expression[++i] - '0'); } // 如果前一个字符是')',说明当前数字是括号内的第一个数,直接入 // 否则,说明前一个数和当前数构成一位多位数,需要将其弹出并计算 if (prev != ')') { op1 = pop(&operands); val = op1 * 10 + val; } push(&operands, val); } // 如果是'(',则直接入 else if (ch == '(') { push(&operators, ch); } // 如果是')',则将运算符中'('上面的所有运算符取出并计算 else if (ch == ')') { while (peek(&operators) != '(') { op2 = pop(&operands); op1 = pop(&operands); val = pop(&operators); switch (val) { case '+': val = op1 + op2; break; case '-': val = op1 - op2; break; case '*': val = op1 * op2; break; case '/': val = op1 / op2; break; } push(&operands, val); } // 弹出'(' pop(&operators); } // 如果是操作符,则将其入, // 并将运算符中优先级大于等于当前操作符的运算符取出并计算 else if (isOperator(ch)) { while (!isEmpty(&operators) && peek(&operators) != '(' && getPriority(peek(&operators)) >= getPriority(ch)) { op2 = pop(&operands); op1 = pop(&operands); val = pop(&operators); switch (val) { case '+': val = op1 + op2; break; case '-': val = op1 - op2; break; case '*': val = op1 * op2; break; case '/': val = op1 / op2; break; } push(&operands, val); } // 将当前操作符入 push(&operators, ch); } prev = ch; } // 处理所有剩余的操作符 while (!isEmpty(&operators)) { op2 = pop(&operands); op1 = pop(&operands); val = pop(&operators); switch (val) { case '+': val = op1 + op2; break; case '-': val = op1 - op2; break; case '*': val = op1 * op2; break; case '/': val = op1 / op2; break; } push(&operands, val); } return pop(&operands); } // 测试函数 int main() { char expression[100]; printf("Enter an arithmetic expression: "); fgets(expression, 100, stdin); printf("Result: %d\n", evaluate(expression)); return 0; } ``` 这个代码实现了基本的四则运算和括号优先级,可以处理多位数和负数。不过可能还存在一些漏洞,需要自己进一步完善和测试。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值