用栈来实现后缀表达式

在这里开始讲述关于java的数据结构,争取每日一更,或者两日一更,将所有java的数据结构相关的结构类型,在这里讲解,好了,现在我们开始来讲第一个结构类型,栈,在这里,我要用栈来实现关于算式的计算,在这里使用了后缀表达式。(声明大部分知识来自《java数据结构和算法》,笔者在这里写下读后总结以及自己的补充。)

什么是后缀表达式?这个大家学过c语言的都应该知道了,我要用java来实现,同样的,思路分为两个步骤,1、将中缀表达式(也就是我们经常使用的计算形式 如 1+2*3)转换为后缀表达式,2、将后缀表达式计算出来。

首先是第一个,我们需要建一个栈,笔者在这里建了一个类,StackTest:

<span style="font-size:18px;">public class StackTest {
	
	private int maxsize;
	private char[] a;
	private int top;
	
	public StackTest(int s){
		maxsize = s;
		a = new char[maxsize];
		top = -1;
	}
	
	public void Push(char m){
		a[++top] = m;
	}
	
	public char Pop(){
		return a[top--];
	}
	
	public char peek(){
		return a[top];
	}
	
	public char peekN(int n){
		return a[n];
	}
	
	public int size(){
		return top+1;
	}
	
	public boolean isEmpty(){
		return (top == -1);
	}
	
	public boolean isFull(){
		return (top == maxsize - 1);
	}
}</span>

这个栈很简单,就不再赘述了,接下来就是重点了,关于如何将中缀转换为后缀表达,请注意代码中笔者的注释,能有效理解这个逻辑变化:

public class TransClass {
	
	private String input;
	private String output="";
	private StackTest stackTest;
	
	public TransClass(String s){
		input = s;
		int max = input.length();
		stackTest = new StackTest(max);
	}
	
	public String doTrans(){                             // 进行转换的方法
		for (int i = 0; i < input.length(); i++) {
			char ch = input.charAt(i);
			switch (ch) {
			case '+':
			case '-':
				gotOper(ch,1);								 //进行判断,若是操作符,则进行比较优先级,若是从栈中的操作符优先级比较 高,或者一样,则进行出栈
				break;
			case '*':
			case '/':
				gotOper(ch,2);								//优先级比加减高
				break;
				
			case '(':
				stackTest.Push(ch);							//全部入栈
				break;
				
			case ')':
				gotParen(ch);                            //出栈进行运算,直到出栈到左括号
				break;
				
			default:
				output = output + ch;                 //将操作数放在一个字符串中
				break;
			}
		}
		while (!stackTest.isEmpty()) {
			output = output + stackTest.Pop();             //打印字符串和栈中的操作符
		}
		return output;
	}

	private void gotParen(char ch) {
		while (!stackTest.isEmpty()) {
			char chx = stackTest.Pop();
			if (chx == '(') {
				break;									//如果是遇到左括号,则停止出栈操作
			}else {
				output = output + chx;					//如果不是左括号,则将操作符并在操作数后面
			}
		}// end while 
	}// end gotParen

	private void gotOper(char onThis, int pece1) {
		while (!stackTest.isEmpty()) {
			char opTop = stackTest.Pop();              //取出栈顶元素
			if (opTop == '(') {
				stackTest.Push(opTop);                 //如果遇到左括号,则将元素重新入栈
				break;
			}
			else {
				int pece2;
				if (opTop == '+' || opTop == '-') {
					pece2 = 1;                         //如果栈顶元素是加减,则优先级为1
				}
				else {
					pece2 = 2;							//如果是其他操作符,则优先级为2
				}
				if (pece2 < pece1) {
					stackTest.Push(opTop);    //若是出栈的操作符比获取的操作符的优先级要小,则重新压入栈中
					break;
				}
				else {
					output = output + opTop;   //否则就将出栈的操作符放在操作数后面,两个操作数的优先级一样也是如此,例如A+B-C=AB+C-
				}
			}//end else(it isn't a operator)
		}//end while
		stackTest.Push(onThis);              //然后将获取的新的字符入栈
	}
注释已经写得很清楚了,笔者再补充一下,主要注意两个点,1、操作符优先级的比较。2、左右括号的情况处理。就是这两个点了,然后关于后缀表达式的计算,逻辑是,1、对字符串依次获取,若是操作数则将操作数入栈,如果是操作符,则将栈中的两个元素出栈。2、然后进行相应的计算,在这里需注意,每次得出的结果应压入栈中,最后再将结果出栈。

public int result(String inputStr){
		int resLength = inputStr.length();
		ResultStack mResultStack = new ResultStack(20);
		char ch1;
		int num1,num2,resultStr;
		
		for (int i = 0; i < inputStr.length(); i++) {
			ch1 = inputStr.charAt(i);
			if (ch1 >= '0' && ch1 <= '9') {
				mResultStack.Push((int)(ch1-'0'));
			}else {
				num2 = mResultStack.Pop();
				num1 = mResultStack.Pop();
				switch (ch1) {
				case '+':
					resultStr = num2 + num1;
					break;

				case '-':
					resultStr = num2 - num1;
					break;
					
				case '*':
					resultStr = num2 * num1;
					break;
					
				case '/':
					resultStr = num2 / num1;
					break;
					
				default:
					resultStr = 0;
					break;
				}//end switch
				mResultStack.Push(resultStr);
			}
		}//end for
		resultStr = mResultStack.Pop();
		return resultStr;
	}
最后主函数再进行调用:

public class TestDemo {

	public static void main(String[] args) throws IOException {
		// TODO Auto-generated method stub
		String input,output;
		while (true) {
			System.out.print("Enter infix :");
			System.out.flush();
			input = getString();
			
			if (input.equals("")) {
				break;
			}
			TransClass transClass = new TransClass(input);
			output = transClass.doTrans();
			System.out.println("后缀表达式为:  " + output + '\n');
			int result = transClass.result(output);
			System.out.print("求解结果为: " + result + '\n');
		}// end while 
	}//end main

	private static String getString() throws IOException {
		String result = "";
		InputStreamReader reader = new InputStreamReader(System.in);
		BufferedReader bufReader = new BufferedReader(reader);
		result = bufReader.readLine();
		
		return result;
	}
	
}
运行结果为:



好了,关于栈的知识已经讲完了。



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值