栈就像压弹夹,先进后出
写个类,构造方法要有始终指向弹夹顶部的top,和代表数组最大容量的maxsize,以及数组本身,
要有push压和pop弹方法,遍历,满了没,空了没方法,
,和模拟队列是一致的只是没有front只有rear,,top从-1开始,每放一个top加一,当top==maxsize-1就是满了
写完基础的栈后就是用它实现功能,
栈实现四则运算的过程是,是数就压进数栈,是符号,1符号栈是空直接压,2不是空就比当前的和栈里的那个优先级大,当前大(接着压)栈里大(回头算栈里的:pop两数,一符号,做完运算入数栈)之后接着压,压完后同样是pop两数,一符号,做完运算入数栈,最后留在数栈的就是结果。
要用到的方法,判断栈是不是空,判断符号优先级,参数为两数一符号的运算方法,在不取出子弹的前提下返回弹夹顶部是个什么数的方法
注意:由于栈是先进后出,当你弹出两个数后出来的那个才是第一个
1.循环遍历获得每一个字符,可以通过String类的,substring(开始,结束)返回一个子字符串然后用charAt(char index)来截取返回的字符串的char值,substring是个左闭右开的返回所以结束要大一,要遍历则开始和结束必须必须是个随循环增加的数,所以要有个表示当前截取遍历到的字符的索引值且在循环结束时自增,
2.要判断这个char是个符号还是数字,由于符号只有四个写个方法判断下是不是加减乘除
true就进行字符的判断,false就把数push进数栈,个位char转数字用char-48(ascll的0)
3.是符号就先判断符号栈是不是空的,是空直接加,
4符号栈不空则对比当前循环截取到的字符和符号栈顶的字符那个优先级大,当前大就接着加
5.栈里的大就调用运算方法,弹出两个数做参数,方法写成switch case,符号做被匹配值,匹配到那个运算符号返回那个的结果,
每截取一个char都做以上步骤直到代表当前循环第几个char的index>=String.length()
1-5走完算是全压进栈里了,
然后不停对栈里的符号和数字做运算结果压数栈,这里可以复用上面的,直到符号栈为空,
最后打印数栈的数字就是结果
上面的这个有个缺陷就是不能对两位数进行操作,
需要对判读不是符号以后的else,进行一些筛选
两位数,要有个空字符串用来拼接两位数的字符,拼接用string += char
然后判断是不是到式子的末尾了,也就是没有下一个了,假设最后一个数是4位数,到式子末尾就意味着他已经把最后一个数拼接完了,再往下是没有符号的,如果再不入栈还会接着往下拼接,所以要加条件强行入栈
如果不是最后一个数就看他的下一字符是不是个符号,如果是符号就把当前截取到的数字进行压栈,如果不是符号也就是多位数还没有截完接着截取
个位的str转成int可以用ascll但是多位的要用包装类Integer.parseInt(s)方法
package stack2;
public class calculator {
public static void main(String[] args) {
// TODO Auto-generated method stub
String shizi ="30+2*6-2";
//这里放式子,不能加括号
stack1 numstack = new stack1(10);
stack1 operstack = new stack1(10);
int index =0;
int num1 = 0;
int num2 = 0;
int oper = 0;
int res = 0;
char ch = ' ';
String keepnum = "";
while(true) {
ch = shizi.substring(index,index+1).charAt(0);
if(operstack.isfuhao(ch)) {
if(!operstack.isempty()) {
if(operstack.priority(ch) <= operstack.priority(operstack.peek())) {
num1 = numstack.pop();
num2 = numstack.pop();
oper = operstack.pop();
res = numstack.cal(num1,num2,oper);
numstack.push(res);
operstack.push(ch);
}else {
operstack.push(ch);
}
}else {
operstack.push(ch);
}
}else {
//numstack.push( - 48);
//
keepnum += ch;
if(index == shizi.length() -1) {
numstack.push(Integer.parseInt(keepnum));
}else {
if(operstack.isfuhao(shizi.substring(index+1,index+2).charAt(0))) {
numstack.push(Integer.parseInt(keepnum));
keepnum = "";
}
}
}
//while内
index++;
if (index >= shizi.length()) {
//因为他已经循环到最后一次
//了且最后一次的操作也执行完了
break;
}
}
//while结束
while(true) {
if(operstack.isempty()) {
break;
}
num1 = numstack.pop();
num2 = numstack.pop();
oper = operstack.pop();
res = numstack.cal(num1,num2,oper);
numstack.push(res);
}
System.out.printf("表达式%s = %d",shizi,numstack.pop());
}
}
class stack1 {
public int maxsize;
public int[] list;
public int top = -1;
public stack1(int maxsize) {
this.maxsize = maxsize;
list = new int[this.maxsize];
}
public boolean isfull() {
return top == maxsize - 1;
}
public boolean isempty () {
return top == -1;
}
public void push (int value) {
if(isfull()) {
System.out.println("满了");
return;
}
top++;
list[top] = value;
}
public int pop() {
if(isempty()) {
throw new RuntimeException("空了");
}
int value = list[top];
top--;
return value;
}
public void list(){
if(isempty()) {
System.out.println("空了");
return;
}
for(int i = top;i>=0;i--) {
System.out.printf("list[%d]=%d \n",i,list[i]);
}
}
//返回运算符优先级
public int priority (int fuhao) {
if(fuhao == '*' || fuhao == '/') {
return 1;
}else if (fuhao == '+'||fuhao == '-') {
return 0;
}else {
return -1;
}
}
public int peek() {
return list[top];
}
public boolean isfuhao(char val) {
return val == '+' || val =='-' || val == '*'||val == '/';
}
public int cal(int num1,int num2,int fuhao) {
int res = 0;
switch (fuhao) {
case '+':
res = num1+num2;
break;
case '-':
res = num2-num1;
break;
case '*':
res = num2*num1;
break;
case '/':
res = num2/num1;
break;
default:
break;
}
return res;
}
}
第二段代码是用JFrame做的一个交互界面运算器
,底层是中缀转后缀再运算,能算出带括号和多位数的算式,
(JFrame就是java内部的两个用来实现gui交互界面的类,awt和swing,千万别学这两个类,除了idea是这个编写的,基本没人用java做交互界面,早就被淘汰了)
package swt;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.util.ArrayList;
import java.util.Stack;
public class JFpoland {
public static String zhongshi = "1+((2+3)*4)-5";
static int g= 0;
public static void main(String[] args) {
// TODO Auto-generated method stub
//String shizi = "3 4 + 5 * 6 - ";
ArrayList<String> a =noblanklist(zhongshi);
System.out.println(a);
ArrayList<String> reverse = zhuan(a);
System.out.println(reverse);
g = calculate(reverse);
fr frame = new fr();
System.out.println(g);
/*
ArrayList<String> list = new ArrayList<>();
list = getlistString(shizi);
System.out.println(list);
try {
System.out.println(calculate(list));
}catch(Exception e) {
System.out.println(e.getMessage());
}
*/
}
//把字符串式子按空格分割成字符串数组再遍历存到Arraylist中
public static ArrayList<String> getlistString(String shizi){
ArrayList<String> list = new ArrayList<>();
String[] split = shizi.split(" ");
for(String ele:split) {
list.add(ele);
}
return list;
}
public static ArrayList<String> noblanklist (String shizi){
ArrayList<String> list = new ArrayList<>();
int i = 0;
String str = "";
char c;
do {
//如果c是个非数字,我需要加入到ls (c=shizi.charAt(i)) < 48 || (c=shizi.charAt(i)) >57
c = shizi.charAt(i);
if(shizi.substring(i,i+1).matches("\\D")) {
list.add("" + c);
i++;
}else {
str = "";
while(i < shizi.length() && shizi.substring(i,i+1).matches("\\d")) {
//限制是数字本身就是遇到符号就入栈的条件
str += c;
i++;
}
list.add(str);
}
}while(i < shizi.length());
return list;
}
public static int priority (int fuhao) {
if(fuhao == '*' || fuhao == '/') {
return 1;
}else if (fuhao == '+'||fuhao == '-') {
return 0;
}else {
return -1;
}
}
public static ArrayList<String> zhuan (ArrayList<String> slist) {
Stack<String> s1 = new Stack<String>();//符号
ArrayList<String> s2 = new ArrayList<>();//数字
for(String item:slist) {
if(item.matches("\\d+")) {
s2.add(item);
}else if (item.equals("(")) {
s1.push(item);
}else if (item.equals(")")) {
while(!s1.peek().equals("(")) {
s2.add(s1.pop());
}
s1.pop();
}else {
//当,当前符号的优先级小于之前加入的符号就把之前的提出来加到数栈
while(s1.size() != 0 && operation.getvalue(item) <= operation.getvalue(s1.peek())) {
s2.add(s1.pop());
}
s1.push(item);
}
}
while(s1.size() != 0) {
s2.add(s1.pop());
}
return s2;
}
public static int calculate(ArrayList<String> ls) {
Stack<String> stack = new Stack<String>();
for(String item:ls) {
if (item.matches("\\d+")) {
stack.push(item);
}else {
int num2 = Integer.parseInt(stack.pop());
int num1 = Integer.parseInt(stack.pop());
int res = 0;
if(item.equals("+")) {
res = num1 + num2;
}else if(item.equals("-")) {
res = num1 - num2;
}else if(item.equals("*")) {
res = num1 * num2;
}else if(item.equals("/")) {
res = num1 / num2;
}else {
throw new RuntimeException("运算有问题");
}
stack.push("" + res);
}
}
return Integer.parseInt(stack.pop());
}
}
class liste implements ActionListener {
fr now ;
public void set (fr a){
this.now = a;
}
@Override
public void actionPerformed(ActionEvent e) {
if(e.getSource() == now.list){
String zhongshi = now.list.getText();
ArrayList<String> a = JFpoland.noblanklist(zhongshi);
System.out.println(a);
ArrayList<String> reverse = JFpoland.zhuan(a);
System.out.println(reverse);
int g = JFpoland.calculate(reverse);
now.testshow.append("答案是"+g);
}
}
}
class fr extends JFrame{
public JTextField list ;
public JCheckBox check;
public JTextArea testshow;
liste listen;
public fr(){
init();
setVisible(true);
}
void init(){
setLayout(new FlowLayout());
list = new JTextField(20);
testshow = new JTextArea(9,20);
check = new JCheckBox("请输入乘号是*除是/的带括号无小数的加减乘除式子");
listen = new liste();
list.addActionListener(listen);
add(list);
add(check);
add(testshow);
pack();
listen.set(this);
setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
}
}
class operation {
public static int add = 1;
public static int sub = 1;
public static int mul = 2;
public static int div = 2;
public static int getvalue(String operation) {
int result = 0;
switch (operation) {
case "+": {
result = add;
break;
}
case "*": {
result = mul;
break;
}
case "/": {
result = div;
break;
}
case "-": {
result = sub;
break;
}
default:
System.out.println(operation);
System.out.println("不存在该运算符");
}
return result;
}
}