什么是栈?个人理解栈就好比手枪的子弹夹,“后进先出”,有很多应用栈的地方,例如浏览器中的后退,最经典的应该是逆波兰算法。
什么是队列?个人理解队列就像你打客服电话,由于是高峰时段,你必须先等等待,一个人结束另一个人才能开始,也就是所谓的“先进先出”。
栈都有顺序栈、链栈,队列都有顺序队列、循环队列、链队列。
下面就用逆波兰算法来简单说明栈的应用:
简单说明逆波兰原理
逆波兰算法的核心步骤就2个:
1、将中缀表达式转换为后缀表达式,例如输入的原始表达式是 3*(5+7)(中缀表达) ,转换得到 3 5 7 + *(后缀表达)
2、根据后缀表达式,按照特定的计算规则得到最终结算结果
下面详细介绍这个2步的操作。
中缀表达式转换为后缀表达式
你需要设定一个栈SOP,和一个线性表 L 。SOP用于临时存储运算符和分界符( ,L用于存储后缀表达式。
遍历原始表达式中的每一个表达式元素
(1)如果是操作数,则直接追加到 L中。只有 运算符 或者 分界符( 才可以存放到 栈SOP中
(2)如果是分界符
Ⅰ 如果是左括号 ( , 则 直接压入SOP,等待下一个最近的 右括号 与之配对。
Ⅱ 如果是右括号),则说明有一对括号已经配对(在表达式输入无误的情况下)。不将它压栈,丢弃它,然后从SOP中出栈,得到元素e,将e依次追加到L里。一直循环,直到出栈元素e 是 左括号 ( ,同样丢弃他。
(3)如果是运算符(用op1表示)
Ⅰ如果SOP栈顶元素(用op2表示) 不是运算符,则二者没有可比性,则直接将此运算符op1压栈。 例如栈顶是左括号 ( ,或者栈为空。
Ⅱ 如果SOP栈顶元素(用op2表示) 是运算符 ,则比较op1和 op2的优先级。如果op1 > op2 ,则直接将此运算符op1压栈。
如果不满足op1 > op2,则将op2出栈,并追加到L,重复步骤3。
也就是说,如果在SOP栈中,有2个相邻的元素都是运算符,则他们必须满足:下层运算符的优先级一定小于上层元素的优先级,才能相邻。
最后,如果SOP中还有元素,则依次弹出追加到L后,就得到了后缀表达式。
下面就开始所谓的逆波兰算法:(源码)
package com.cn.hnust.controller;
import java.util.LinkedList;
/**
* 栈类
*/
public class Stracks {
private LinkedList linkedList=new LinkedList();
int top=-1;
public void push( Object value){//入栈方法
top++ ;
linkedList.addFirst(value);
}
public Object pop() {//出栈方法
Object o = linkedList.getFirst();
top--;
linkedList.removeFirst();
return o;
}
public Object top(){
return linkedList.getFirst();
}
}
package com.cn.hnust.controller;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.StringTokenizer;
/**
* 表达式类中缀变后缀
*/
public class Expression {
private ArrayList arrayListMid = new ArrayList();//存储中缀表达式
private ArrayList arrayListLast = new ArrayList(); //存储后缀表达式
private String result;
public Expression(String value) {//根据输入信息创建中缀表达式对象
StringTokenizer stringTokenizer =new StringTokenizer(value,"+-*/()",true);
while(stringTokenizer.hasMoreElements()){
String s = stringTokenizer.nextToken();
arrayListMid.add(s);
}
}
public void Last(){//中缀转后缀
Stracks stracks = new Stracks();//实例化栈类对象,方便调用
String operator;
int postion = 0;
while (true){
if (Calculate.isOperator((String) arrayListMid.get(postion))) {
if (stracks.top == -1
|| ((String) arrayListMid.get(postion)).equals("(")) {
stracks.push(arrayListMid.get(postion));
} else {
if (((String) arrayListMid.get(postion)).equals(")")) {
while(true){
if (stracks.top != -1&&!((String) stracks.top()).equals("(")) {
operator = (String) stracks.pop();
arrayListLast.add(operator);
}else{
if(stracks.top != -1)
stracks.pop();
break;
}
}
} else {
while(true){
if (stracks.top != -1&&Calculate.priority((String) arrayListMid
.get(postion)) <= Calculate
.priority((String) stracks.top())
) {
operator = (String) stracks.pop();
if (!operator.equals("("))
arrayListLast.add(operator);
}else{
break;
}
}
stracks.push(arrayListMid.get(postion));
}
}
} else
arrayListLast.add(arrayListMid.get(postion));
postion++;
if (postion >= arrayListMid.size())
break;
}
while (stracks.top != -1) {
operator = (String) stracks.pop();
if(!operator.equals("("))
arrayListLast.add(operator);
}
}
// 对右序表达式进行求值
private void getResult() {
this.Last();
for(int i=0;i<arrayListLast.size();i++){
System.out.println(arrayListLast.get(i));
}
Stracks aStack = new Stracks();
String op1, op2, is = null;
Iterator it = arrayListLast.iterator();
while (it.hasNext()) {
is = (String) it.next();
if (Calculate.isOperator(is)) {
op1 = (String) aStack.pop();
op2 = (String) aStack.pop();
aStack.push(Calculate.twoResult(is, op1, op2));
} else
aStack.push(is);
}
result = (String) aStack.pop();
it = arrayListMid.iterator();
while (it.hasNext()) {
System.out.print((String) it.next());
}
System.out.println("=" + result);
}
public static void main(String avg[]) {
try {
System.out.println("Input a expression:");
BufferedReader is = new BufferedReader(new InputStreamReader(
System.in));
for (;;) {
String input = new String();
input = is.readLine().trim();
if (input.equals("q"))
break;
else {
Expression boya = new Expression(input);
boya.getResult();
}
System.out
.println("Input another expression or input 'q' to quit:");
}
is.close();
} catch (IOException e) {
System.out.println("Wrong input!!!");
}
}
}
package com.cn.hnust.controller;
public class Calculate {
// 判断是否为操作符号
public static boolean isOperator(String operator) {
if (operator.equals("+") || operator.equals("-")
|| operator.equals("*") || operator.equals("/")
|| operator.equals("(") || operator.equals(")"))
return true;
else
return false;
}
// 设置操作符号的优先级别
public static int priority(String operator) {
if (operator.equals("+") || operator.equals("-"))
return 1;
else if (operator.equals("*") || operator.equals("/"))
return 2;
else
return 0;
}
// 做2值之间的计算
public static String twoResult(String operator, String a, String b) {
try {
String op = operator;
String rs = new String();
double x = Double.parseDouble(b);
double y = Double.parseDouble(a);
double z = 0;
if (op.equals("+"))
z = x + y;
else if (op.equals("-"))
z = x - y;
else if (op.equals("*"))
z = x * y;
else if (op.equals("/"))
z = x / y;
else
z = 0;
return rs + z;
} catch (NumberFormatException e) {
System.out.println("input has something wrong!");
return "Error";
}
}
}