栈的前缀_中缀_后缀表达式

栈的前缀_中缀_后缀表达式

三种表达式

  • 前缀表达式,又称为波兰式,在前缀表达式中,运算符位于操作数之前。
  • 例如(3+4)*5-6,其前缀表达式为:- *+3456
  • 中缀表达式即我们人类日常使用的数学运算
  • 后缀表达式,又称为逆波兰表达式,在后缀表达式中,运算符位于操作数之后。
  • 例如(3+4)*5-6,其后缀表达式为:34+5 *6-

转换方法

  • 中缀转前缀
    确定中缀表达式的运算顺序,然后一层一层加上括号,相当于将一个括号的内容看作了一个数,然后从最里面的括号开始运算。

  • 例子:
    1+(2+3)*4-5 =>((1+((2+3)*4))-5)
    1、(2+3) =>+23
    2、((2+3)*4) => *+234
    3、(1+((2+3)*4)) => +1 *+234
    4、((1+((2+3)*4)) -5)=> -+1 *+2345

  • 中缀转后缀
    步骤和中缀转前缀类似,不同的是,后缀表达式中的运算符位于操作数之后

  • 例子:
    1+(2+3)*4-5 =>((1+((2+3)*4))-5)
    1、(2+3) =>23+
    2、((2+3)*4) => 23+4 *
    3、(1+((2+3)*4)) => 123+4 *+
    4、((1+((2+3)*4)) -5)=> 123+4 *+5-

前缀、后缀表达式原理的计算器求值

  • 前缀表达式:
    1、从右至左扫描前缀表达式,遇到数字时就将数字压入堆栈
    2、遇到运算符时,弹出栈顶和次顶的两个数,用该运算符对这两个数做相应的运算,并将结果入栈。
    3、重复步骤1和步骤2,直到表达式被扫描完,最后运算得到值。

  • 后缀表达式:
    1、从左至右扫描前缀表达式,遇到数字时就将数字压入堆栈
    2、遇到运算符时,弹出栈顶和次顶的两个数,用该运算符对这两个数做相应的运算,并将结果入栈。
    3、重复步骤1和步骤2,直到表达式被扫描完,最后运算得到值。

中缀转后缀表达式代码实现

思路

1、 初始化两个栈,s1暂时存储运算符,s2存储数字和运算符
2、从左至右扫描中缀表达式,扫描到数字存入s2
3、 扫描到运算符时,
1)如果s1为空栈,或者栈顶运算符为“(”,则直接入s1栈
2)如果该运算符的优先级比栈顶运算符的优先级高,也直接入s1栈
3)如果1)和2)都不满足,就将当前s1栈的栈顶元素取出,并令其入s2栈,然后再重复1)~3)的步骤,直到希望入栈的运算符入s1栈
4、扫描到“(”就直接入s1栈,遇到“)”则一直取出s1栈中的运算符并存入s2栈,直到s1栈取出一个“(”后(该"("不存入s2栈),停止取出s1栈中的运算符,而该“)”也不存入s1和s2栈
5、重复2~4,直到中缀表达式被遍历完
6、将s1栈中的运算符依次取出并存入s2栈中
7、s2栈中的数据再全部取出,并逆序,就得到了对应的后缀表达式

代码实现
public static List<String> infixListToRpnList(List<String> list) {//将中缀表达式转为逆波兰表达式
		List<String> rpnList=new ArrayList<String>();
		Stack<String> datastack=new Stack<String>();//存储中间结果和符号
		Stack<String> operstack=new Stack<String>();//暂时存储符号
		int num2=0;
		int num1=0;
		int result=0;
		String oper=null;
		for(String item:list) {
			if(item.matches("\\d+")) {//如果是数字就入数栈
				datastack.push(item);
			
			}else {
				if(operstack.size()==0||operstack.peek().equals("(")) {//如果栈空或者栈顶是"(",直接插入数据
					operstack.push(item);
					
				}else if(item.equals(")")){//如果item是")",则将符号栈中的运算符取出,直到取出一个"("后为止
					while(true) {
						if(operstack.peek().equals("(")) {
							operstack.pop();
							break;
						}
						datastack.push(operstack.pop());
					}
				}else if(priority(item)>priority(operstack.peek())) {//如果优先级大于栈顶运算符的优先级,也直接插入
					operstack.push(item);
				}else if(priority(item)<=priority(operstack.peek())){//如果优先级小于等于栈顶运算符的优先级,
					
					datastack.push(operstack.pop());
					//将当前运算符栈的栈顶元素插入s2,然后再循环判断新栈顶元素的优先级和希望入栈的运算符的优先级
					while(true) {
						if(operstack.size()==0||operstack.peek().equals("(")) {
							operstack.push(item);
							break;
						}else if(priority(item)>priority(operstack.peek())) {
							operstack.push(item);
							break;
						}else {
							datastack.push(operstack.pop());
						}
						
					}
				
				}
			}
		}
		//将符号栈中剩下的运算符全部插入数栈
		while(operstack.size()!=0) {
			datastack.push(operstack.pop());
		}
		
		for(String item:datastack) {
			rpnList.add(item);
		}
		return rpnList;
	}
public static void main(String[] args) {
		List<String> list=infixToArrayList("4*5-8+60+8/2");
		list=infixListToRpnList(list);
		for(String i:list) {
			System.out.println(i);
		}
	}

运行结果

4
5
*
8
-
60
+
8
2
/
+

后缀表达式实现简易整数计算器

思想

从左至右扫描后缀表达式,遇到数字时,就将数字插入栈中,遇到运算符就从栈中取出2个数字,根据运算符令这2个数字做运算,得到的结果插入栈中。重复上述过程,直到表达式被扫描完毕,最后完成运算得到结果。

代码实现
public class ReversePolishNotation {

	public static void main(String[] args) {
		List<String> list=infixToArrayList("4*5-8+60+8/2");
		
		list=infixListToRpnList(list);
		for(String i:list) {
			System.out.println(i);
		}
		System.out.printf("计算结果%d\n",calculator(list));
	}
	public static int priority(String s) {//优先级
		if(s.equals("*")||s.equals("/")) {
			return 1;
		}else if(s.equals("+")||s.equals("-")) {
			return 0;
		}else {
			return -1;
		}
	}
	
	public static List<String> infixToArrayList(String infix){//将中缀表达式放入链表
		List<String> list=new ArrayList<String>();
		char ch=' ';
		String keepStr="";
		int index=0;
		while(index<infix.length()) {
			ch=infix.charAt(index);
			if(ch<48||ch>57) {
				list.add(ch+"");
				index++;
			}else {
				while((index<infix.length())&&ch>=48&&ch<=57) {
					keepStr+=ch;
					index++;
					if(index>=infix.length()) {
						break;
					}
					ch=infix.charAt(index);
				}
				list.add(keepStr);
				keepStr="";
			}
		}
		return list;
	}
	public static List<String> infixListToRpnList(List<String> list) {//将中缀表达式转为逆波兰表达式
		List<String> rpnList=new ArrayList<String>();
		Stack<String> datastack=new Stack<String>();//存储中间结果和符号
		Stack<String> operstack=new Stack<String>();//暂时存储符号
		int num2=0;
		int num1=0;
		int result=0;
		String oper=null;
		for(String item:list) {
			if(item.matches("\\d+")) {//如果是数字就入数栈
				datastack.push(item);
			
			}else {
				if(operstack.size()==0||operstack.peek().equals("(")) {//如果栈空或者栈顶是"(",直接插入数据
					operstack.push(item);
					
				}else if(item.equals(")")){//如果item是")",则将符号栈中的运算符取出,直到取出一个"("后为止
					while(true) {
						if(operstack.peek().equals("(")) {
							operstack.pop();
							break;
						}
						datastack.push(operstack.pop());
					}
				}else if(priority(item)>priority(operstack.peek())) {//如果优先级大于栈顶运算符的优先级,也直接插入
					operstack.push(item);
				}else if(priority(item)<=priority(operstack.peek())){//如果优先级小于等于栈顶运算符的优先级,
					
					datastack.push(operstack.pop());
					//将当前运算符栈的栈顶元素插入s2,然后再循环判断新栈顶元素的优先级和希望入栈的运算符的优先级
					while(true) {
						if(operstack.size()==0||operstack.peek().equals("(")) {
							operstack.push(item);
							break;
						}else if(priority(item)>priority(operstack.peek())) {
							operstack.push(item);
							break;
						}else {
							datastack.push(operstack.pop());
						}
						
					}
				
				}
			}
		}
		//将符号栈中剩下的运算符全部插入数栈
		while(operstack.size()!=0) {
			datastack.push(operstack.pop());
		}
		
		for(String item:datastack) {
			rpnList.add(item);
		}
		return rpnList;
	}
	
	public List<String> save(String rpn){//将表达式处理,放入List中
		String []rpnStr=rpn.split(" ");//通过分割符将每个数据存放到字符串数组中
		List<String> list=new ArrayList<String>();
		for(String item:rpnStr) {//将字符串数组中的每一个元素都存放进List中
			list.add(item);
		}
		return list;
	}
	
	public static int calculator(List<String> list) {//运算
		
		Stack<String> stack=new Stack<String>();
		for(String item:list) {
			if(item.matches("\\d+")) {//正则表达式判断是否是数字
				stack.push(item);
			}else {//不是数字就说明是运算符
				int num2=Integer.parseInt(stack.pop());
				int num1=Integer.parseInt(stack.pop());//取出两个数字
				int result=0;
				if(item.equals("+")) {
					result=num1+num2;
				}else if(item.equals("-")) {
					result=num1-num2;
				}else if(item.equals("*")) {
					result=num1*num2;
				}else if(item.equals("/")) {
					result=num1/num2;
				}else {
					throw new RuntimeException("该字符不是运算符");
				}
				stack.push(""+result);//做完运算后,要让数据入栈
			}
		}
		
		return Integer.parseInt(stack.pop());
	}
}

运行结果

4
5
*
8
-
60
+
8
2
/
+
计算结果76
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值