上一节介绍了栈和队列两种数据结构,这里接介绍一个栈和队列的综合应用:计算表达式
计算表达式
以前做小练习的时候也做过小的计算器,对表达式的计算是很重要也是很头疼的一部分,这里就来看看如何使用栈和队列来实现。
计算表达式分两步:
- 将算术表达式转换为后缀表达式。
- 计算后缀表达式的值。
中缀表达式 | 后缀表达式 |
---|---|
A+B-C | AB+C- |
A*B/C | AB*C/ |
A+B*C | ABC*+ |
A*(B+C) | ABC+* |
A*B+C*D | AB*CD*+ |
A+B*(C-D/(E+F)) | ABCDEF+/-*+ |
举例一个计算过程:
中缀表达式转换为后缀表达式的转换规则:
中缀表达式读取的字符 | 动作 |
---|---|
操作数 | 写至输出 |
左括号 | 压入栈 |
右括号 | 栈非空时重复一下步骤:弹出一项,若项不为(,则写至输出,若为(退出循环 |
代码实现:
import java.io.*;
class StackX
{
private int maxSize;
private char[] stackArray;
private int top;
public StackX(int s) // constructor
{
maxSize = s;
stackArray = new char[maxSize];
top = -1;
}
public void push(char j) // 压入数据项至栈顶
{ stackArray[++top] = j; }
public char pop() // 从栈顶拿走一项元素 (栈大小改变)
{ return stackArray[top--]; }
//--------------------------------------------------------------
public char peek() // 获取栈顶元素 (只获得栈顶元素 栈不变)
{ return stackArray[top]; }
//--------------------------------------------------------------
public boolean isEmpty() // 判断是否为空
{ return (top == -1); }
//-------------------------------------------------------------
public int size() // 获取栈大小
{ return top+1; }
//--------------------------------------------------------------
public char peekN(int n) // 获取指定元素
{ return stackArray[n]; }
//--------------------------------------------------------------
public void displayStack(String s)
{
System.out.print(s);
System.out.print("Stack (bottom-->top): ");
for(int j=0; j<size(); j++)
{
System.out.print( peekN(j) );
System.out.print(' ');
}
System.out.println("");
}
//--------------------------------------------------------------
}
class InToPost
{
private StackX theStack;
private String input;
private String output = "";
public InToPost(String in)
{
input = in;
int stackSize = input.length();
theStack = new StackX(stackSize);
}
public String doTrans()
{
for(int j=0; j<input.length(); j++) // 遍历
{
char ch = input.charAt(j);
theStack.displayStack("For "+ch+" ");
switch(ch)
{
case '+': // + 或 -
case '-':
gotOper(ch, 1);
break;
case '*': // * 或 /
case '/':
gotOper(ch, 2);
break;
case '(':
theStack.push(ch);
break;
case ')':
gotParen(ch);
break;
default:
output = output + ch;
break;
}
}
while( !theStack.isEmpty() )
{
theStack.displayStack("While ");
output = output + theStack.pop();
}
theStack.displayStack("End ");
return output;
}
public void gotOper(char opThis, int prec1)
{
while( !theStack.isEmpty() )
{
char opTop = theStack.pop();
if( opTop == '(' )
{
theStack.push(opTop);
break;
}
else
{
int prec2;
if(opTop=='+' || opTop=='-')
prec2 = 1;
else
prec2 = 2;
if(prec2 < prec1)
{
theStack.push(opTop);
break;
}
else
output = output + opTop;
}
}
theStack.push(opThis);
}
public void gotParen(char ch)
{
while( !theStack.isEmpty() )
{
char chx = theStack.pop();
if( chx == '(' )
break;
else
output = output + chx;
}
}
//--------------------------------------------------------------
}
class InfixApp
{
public static void main(String[] args) throws IOException
{
String input, output;
while(true)
{
System.out.print("Enter infix: ");
System.out.flush();
input = getString();
if( input.equals("") )
break;
InToPost theTrans = new InToPost(input);
output = theTrans.doTrans(); // do the translation
System.out.println("Postfix is " + output + '\n');
}
}
//--------------------------------------------------------------
public static String getString() throws IOException
{
InputStreamReader isr = new InputStreamReader(System.in);
BufferedReader br = new BufferedReader(isr);
String s = br.readLine();
return s;
}
//--------------------------------------------------------------
}
输出效果:
接下来就是如何从后缀表达式求值:
后缀表达式读取的字符 | 动作 |
---|---|
操作数 | 入栈 |
操作符 | 从栈中提取两个操作数,计算结果,结果入栈 |
代码实现:
import java.io.*;
class StackX
{
private int maxSize;
private int[] stackArray;
private int top;
public StackX(int size) // constructor
{
maxSize = size;
stackArray = new int[maxSize];
top = -1;
}
public void push(int j) // put item on top of stack
{ stackArray[++top] = j; }
//--------------------------------------------------------------
public int pop() // take item from top of stack
{ return stackArray[top--]; }
//--------------------------------------------------------------
public int peek() // peek at top of stack
{ return stackArray[top]; }
//--------------------------------------------------------------
public boolean isEmpty() // true if stack is empty
{ return (top == -1); }
//--------------------------------------------------------------
public boolean isFull() // true if stack is full
{ return (top == maxSize-1); }
//--------------------------------------------------------------
public int size() // return size
{ return top+1; }
//--------------------------------------------------------------
public int peekN(int n) // peek at index n
{ return stackArray[n]; }
public void displayStack(String s)
{
System.out.print(s);
System.out.print("Stack (bottom-->top): ");
for(int j=0; j<size(); j++)
{
System.out.print( peekN(j) );
System.out.print(' ');
}
System.out.println("");
}
}
class ParsePost
{
private StackX theStack;
private String input;
//--------------------------------------------------------------
public ParsePost(String s)
{ input = s; }
//--------------------------------------------------------------
public int doParse()
{
theStack = new StackX(20); // make new stack
char ch;
int j;
int num1, num2, interAns;
for(j=0; j<input.length(); j++) // for each char,
{
ch = input.charAt(j); // read from input
theStack.displayStack(""+ch+" "); // *diagnostic*
if(ch >= '0' && ch <= '9') // if it's a number
theStack.push( (int)(ch-'0') ); // push it
else // it's an operator
{
num2 = theStack.pop(); // pop operands
num1 = theStack.pop();
switch(ch) // do arithmetic
{
case '+':
interAns = num1 + num2;
break;
case '-':
interAns = num1 - num2;
break;
case '*':
interAns = num1 * num2;
break;
case '/':
interAns = num1 / num2;
break;
default:
interAns = 0;
} // end switch
theStack.push(interAns); // push result
} // end else
} // end for
interAns = theStack.pop(); // get answer
return interAns;
}
}
class PostfixApp
{
public static void main(String[] args) throws IOException
{
String input;
int output;
while(true)
{
System.out.print("Enter postfix: ");
System.out.flush();
input = getString(); // read a string from kbd
if( input.equals("") ) // quit if [Enter]
break;
// make a parser
ParsePost aParser = new ParsePost(input);
output = aParser.doParse(); // do the evaluation
System.out.println("Evaluates to " + output);
}
}
public static String getString() throws IOException
{
InputStreamReader isr = new InputStreamReader(System.in);
BufferedReader br = new BufferedReader(isr);
String s = br.readLine();
return s;
}
}
至此表达式的计算就完成了,还是比较复杂的,需要完全理解。