有人可能会觉得,用数组或链表直接实现功能不就可以了吗?为什么还要引入栈这种数据结构呢?
其实栈的引入简化了程序设计的问题,划分了不同关注层次,使得思考范围缩小,更加聚集于我们要解决的问题核心。他封装了一些方法,使得我们使用这些方法的时候不需要考虑里面的细节问题,而只需要考虑如何用这种结构解决问题。
栈的应用:
1、递归问题(用栈来管理函数的调用,这在高级语言中系统已经帮我们管理了,我们不用操心这个问题)
2、四则运算表达式求值
代码实现如下:
package seqList;
import java.util.ArrayList;
/*
* 要想让计算机具有处理我们通常的标准(中缀)表达式的能力,最重要的就是两步:
* 1、将中缀表达式转化为后缀表达式
* 2、将后缀表达式进行运算得出结果
*/
//前面的三个函数是为了将字符串转化为字符串数组
public class Arithmetic {
// 判断是否为操作符
public boolean isOpe(String s) {
String[] ope=new String[]{"+","-","*","/","(",")"};
for(int i=0;i<ope.length;i++) {
if(s.equals(ope[i])) {
return true;
}
}
return false;
}
//判断是否为数字
public boolean isDigit(char c){
if(c>='0'&&c<='9'){
return true;
}
return false;
}
//将字符串转化为字符串数组
public ArrayList<String> transtion(String s){
ArrayList<String> list=new ArrayList<>();
char[] chr=s.toCharArray();
StringBuilder sb=new StringBuilder();
for(int i=0;i<chr.length;i++) {
if(isDigit(chr[i])) {
sb.append(chr[i]);
}
else {
if(sb.toString().length()>0) {
list.add(sb.toString());
sb.delete(0, sb.toString().length());
}
list.add(chr[i]+"");
}
}
if(sb.toString().length()>0) {
list.add(sb.toString());
sb.delete(0, sb.toString().length());
}
for(int i=0;i<list.size();i++) {
System.out.print(list.get(i));
}
System.out.println();
return list;
}
//中缀表达式转后缀表达式
public ArrayList<String> InfixToPostfix(ArrayList<String> s) throws Exception {
ArrayList<String> postfixList=new ArrayList<>();//存储后缀表达式
LinkStack stack=new LinkStack();//存储操作符
for(int i=0;i<s.size();i++) {
//如果是( 则进栈
if(s.get(i).equals("(")) {
stack.push(s.get(i));
}
//如果是*或者除号/也进栈
else if(s.get(i).equals("*")||s.get(i).equals("/")) {
stack.push(s.get(i));
}
/*当符号是+或者-时,它们已经是优先级最低的符号了
*
* 1、如果栈不为空,但栈顶元素是( 时,入栈
* 2、如果不是,栈顶元素出栈,放到后缀表达式中
*/
//这块一直出错,当Stack不为空时,如果没有左括号是要一直出栈,知道栈为空,所以此时s.get(i)是要进栈的
else if(s.get(i).equals("+")||s.get(i).equals("-")) {
//如果栈不为空的话
while(!stack.isEmpty()) {
//先判断栈顶元素是否为( ,若是入栈
if(stack.getTop().equals("(")) {
stack.push(s.get(i));
break;
}
//若不是,栈顶元素出栈
else {
postfixList.add((String)stack.pop());
}
}
//栈空,将该元素入栈
if(stack.isEmpty())
stack.push(s.get(i));
}
else if(s.get(i).equals(")")){
while(!stack.getTop().equals("(")) {
postfixList.add((String)stack.pop());
}
stack.pop();//将( 出栈
}
else {
postfixList.add(s.get(i));
}
}
while(!stack.isEmpty()) {
postfixList.add((String)stack.pop());
}
for(int i=0;i<postfixList.size();i++) {
System.out.print(postfixList.get(i));
}
return postfixList;
}
//将后缀表达式进行运算得出结果
public int calculate(ArrayList<String> postfixList) throws Exception {
LinkStack stack=new LinkStack();//暂时存储还没有计算的数和操作符
for(int i=0;i<postfixList.size() ;i++) {
if(!isOpe(postfixList.get(i))) {
stack.push(Integer.parseInt(postfixList.get(i)));
}
else {
if(postfixList.get(i).equals("+")) {
int sum=(int)stack.pop()+(int)stack.pop();
stack.push(sum);
}
if(postfixList.get(i).equals("-")) {
int x=(int)stack.pop();
int y=(int)stack.pop();
int sum=y-x;
stack.push(sum);
}
if(postfixList.get(i).equals("*")) {
int sum=(int)stack.pop()*(int)stack.pop();
stack.push(sum);
}
if(postfixList.get(i).equals("/")) {
int x=(int)stack.pop();
int y=(int)stack.pop();
int sum=y/x;
stack.push(sum);
}
}
}
return (int)stack.pop();
}
//测试代码
public static void main(String[] args) throws Exception {
Arithmetic ari=new Arithmetic();
String str = "9+(3-1)*3+10/2";
ArrayList<String> list = ari.transtion(str);
ArrayList<String> list1= ari.InfixToPostfix(list);
System.out.println();
System.out.println(ari.calculate(list1));
}
}
运行结果: