数据结构与算法——栈

栈(stack)

在这里插入图片描述

介绍

1)栈的英文为(stack)

2)栈是一个先入后出(FILO-First In Last Out)的有序列表。

3)栈(stack)是限制线性表中元素的插入和删除只能在线性表的同一端进行的一种特殊线性表。允许插入和删除的
一端,为变化的一端,称为栈顶(Top),另一端为固定的一端,称为栈底(Bottom)。

4)根据栈的定义可知,最先放入栈中元素在栈底,最后放入的元素在栈顶,而删除元素刚好相反,最后放入的元
素最先删除,最先放入的元素最后删除

5)图解方式说明出栈(pop)和入栈(push)的概念

栈的应用场景

1)子程序的调用:在跳往子程序前,会先将下个指令的地址存到堆栈中,直到子程序执行完后再将地址取出,以
回到原来的猩序中。

2)处理递归调用:和子程序的调用类似,只是除了储存下一个指令的地址外,也将参数、区域变量等数据存入堆
栈中。

3)表达式的转换[中缀表达式转后缀表达式]与求值(实际解决)。

4)二叉树的遍历。

5)图形的深度优先(depth 一 first)搜索法。

数组模拟栈

实现栈的思路分析

1.使用数组来模拟栈

2定义一个top 来表示栈顶,初始化为-1

3.入栈的操作,当有数据加入到栈时,

top++;

stack[top] = data;

4.出栈的操作,

intvalue =stack[top];

top–,

return valuel

代码实现:

package com.iswhl.stack;

public class ArrayStackDemo {
    public static void main(String[] args) {
        ArrayStack arrayStack = new ArrayStack(3);
        arrayStack.push(1);
        arrayStack.push(2);
        arrayStack.push(3);


//        System.out.println(arrayStack.pop());
//        System.out.println(arrayStack.pop());
//        System.out.println(arrayStack.pop());

        System.out.println("栈的输出结果为:");
        arrayStack.list();
    }
}

class ArrayStack{
    private int maxSize;//栈的最大值
    private int[] stack;//模拟栈的数组
    private int top = -1;//top表示为栈顶,初始值为-1
    //定义构造器
    public ArrayStack(int maxSize) {
        this.maxSize = maxSize;
        stack = new int[this.maxSize];
    }
    //判断栈是否为空
    public Boolean isEmpty(){
        return top == -1;
    }
    //判断栈是否是满的
    public Boolean isFull(){
        return top == maxSize -1;
    }
    //入栈
    public void push(int value){
        if (isFull()){
            System.out.println("栈满,无法再入栈");
            return;
        }
        top++;
        stack[top] = value;
    }
    //出栈
    public int pop(){
        if (isEmpty()){
            throw new RuntimeException("当前栈为空,无法取值");
        }
        return stack[top--];
    }
    //遍历栈
    public void list(){
        if (isEmpty()){
            throw new RuntimeException("当前栈为空,无法取值");
        }
        int tops  = top;
        while (true){
            if (tops == -1){
                break;
            }
            System.out.printf("stack[%d] = %d\n",tops,stack[tops]);
            tops--;
        }
    }
}

使用栈来实现综合计算器(中缀表达式):

实现思路:

使用栈完成表达式的计算思路

1.通过一个index值(索引),来遍历我们的表达式2如果我们发现是一个数字,就直接入数栈

3.如果发现扫描到是一个符号,就分如下情况

3.1如果发现当前的符号栈为空,就直接入栈

3.2如果符号栈有操作符,就进行比较,如果当前的操作符的优先级小于或者等于楫中的操作符,就需要从数栈中pop出两个数在从符号栈中pop出一个符号,进行运算,将得到结果,入数栈,然后将当前的操作符入符号栈,如果当前的操作符的优先级大于栈中的操作符,就直接入符号栈

4.当表达式扫描完毕,就顺序的从数栈和符号栈中pop出相应的数和符号,并运行.

5.最后在数栈只有一个数字,就是表达式的结果

验证: 3+2*6-2=13

在这里插入图片描述

在这里插入图片描述

涉及的小的知识点

Java中int于char的关系

在java中,无论是一个字符,还是一个字符型变量,实则也是一个数字,所以,可以直接将一个(不超过char的范围的)数字赋值给一个char变量,即可输出其结果:

即在不超过int的范围下,int于char一定程度上可以混合使用


char c1 = 97;
System.out.println(c1);
结果:

a
    
同样的,我们可以将一个字符赋值给一个int变量,因为字符也是一个数字嘛

char c2 = 'a' + 1;
int num2 = 'a' + 1;
System.out.println("c2:          " + c2);
System.out.println("num2:        " + num2);
System.out.println("(char) num2: " + (char) num2);

结果:

c2:          b
num2:        98
(char) num2: b

ps:要注意char的大小过界的问题,我们可以直接以一个数字赋给一个char型的变量,但是,若我们赋的值的大小大于了65536,会发生报错。

java中subString的用法

substring()
截取字符串的一部分字符

函数用法
第一种

substring(int beginIndex)
返回从起始位置到字符串末尾

第二种

substring(int beginIndex, int endIndex)
返回从起始位置到目标位置之间的字符串
但不包含目标位置

public String substring(int beginIndex)public String substring(int beginIndex, int endIndex)
    
beginIndex -- 起始索引(包括), 索引从 0 开始。

endIndex -- 结束索引(不包括)。
    
public class RunoobTest {
    public static void main(String args[]) {
        String Str = new String("This is text");
 
        System.out.print("返回值 :" );
        System.out.println(Str.substring(4) );
 
        System.out.print("返回值 :" );
        System.out.println(Str.substring(4, 10) );
    }
}

以上程序执行结果为:

返回值 : is text
返回值 : is te

小的知识点:将字符类型的值转化为数值形式,需要将该字符的值减去48(根据AscII来的)

java做到字符串转数字

java字符串转数字的方法:

1、转化为整型数字【Integer.parseInt(String s) 】;

2、转化为浮点型数字【Float.parseFloat(String s)】;

java字符串转数字的方法:
    
1、转化为整型数字

1)、转化为整型数字 Integer.parseInt(str)
    
public class Test {

public static void main(String args[]){

String s = "123";

int num = Integer.parseInt(str);

int sum = num + 100;

System.out.println("Result is: "+sum); // 输出结果为:Result is: 223

}}


2)、Integer.valueOf(String s),代码示例如下
    
    
public class Test2 {

public static void main(String args[]){

String s = "-100";

int num = Integer.valueOf(str);

int sum = num + 101;

System.out.println("Result is: "+sum); // 输出结果为:Result is: 1

} }

2、转化为浮点型数字 Float.parseFloat(s)1Float.parseFloat(String s),代码示例如下:
    
public class Test {

public static void main(String args[]){

String s = "123.11";

float num = Float.parseFloat(s);

float sum = num + 100;

System.out.println("Result is: "+sum); // 输出结果为:Result is: 223.11

}}2Double.parseDouble(String s),代码示例如下:
    
public class Test2 {

public static void main(String args[]){

String s = "100.01";

double num = Double.parseDouble(s);

double sum = num + 100;

System.out.println("Result is: "+sum); // 输出结果为:Result is: 200.01

}}

代码实现:

package com.iswhl.stack;

public class Calculator {
    public static void main(String[] args) {
        //定义一个表达式
        String expression = "11+2*1-2/1";
        //定义一个数组栈 一个符号栈
        ArrayStack2 numStack = new ArrayStack2(10);
        ArrayStack2 operStack = new ArrayStack2(10);
        int index = 0;//辅助索引 用来遍历栈
        int num1 = 0;//取出的栈中的值
        int num2 = 0;//取出的栈中的值
        int oper = 0;//用于存储操作符
        String keepnum = "";//用于存储拼接的多位数
        while (true){//用来遍历表达式
            char ch = expression.substring(index,index+1).charAt(0);//用于取出表达式中的一个字符,从第一个开始遍历取出
            if (operStack.isOper(ch)){//当前扫描到的字符为 操作符
                if (operStack.isEmpty()){//如果当前的栈为空,则直接入栈
                    operStack.push(ch);
                }else {//如果当前的栈不为空
                    //如果当前的操作符的优先级小于或者等于栈中的操作符,
                    if (!operStack.isEmpty()) {
                        // 就需要从数栈中pop出两个数在从符号栈中pop出一个符号,进行运算,将得到结果,入数栈
                        if (operStack.priority(ch) <= operStack.priority(operStack.peek())) {
                            num1 = numStack.pop();
                            num2 = numStack.pop();
                            oper = operStack.pop();
                            int res2 = numStack.cla(num1, num2, oper);
                            //进行运算,将得到结果,入数栈
                            numStack.push(res2);
                            //然后将当前的操作符入符号栈
                            operStack.push(ch);
                        } else {//如果当前的操作符的优先级大于栈中的操作符,就直接入符号栈
                            operStack.push(ch);
                        }
                    }
                }
            }else {//扫描的值为数字

                keepnum += ch;
                if (index == expression.length() - 1){
                    numStack.push(Integer.parseInt(keepnum));//通过Integer.parseInt(keepnum)将其转化为一个整数值
                }else {
                    //这里判断当前数值的下一位是不是为数字
                    if (operStack.isOper(expression.substring(index+1,index+2).charAt(0))){
                        numStack.push(Integer.parseInt(keepnum));
                        //将多位数添加到数栈了后将,该keepnum清空
                        keepnum = "";
                    }
                }
            }
            index++;
            if (index >= expression.length()){
                break;
            }
        }
        //到这里就说明整个表达式扫描完毕到栈中了
        while (true){
            if (operStack.isEmpty()){//上面此时结果已经运算完毕,只剩下数栈中的结果值
                break;
            }
            num1 = numStack.pop();
            num2 = numStack.pop();
            oper = operStack.pop();
            int res2 = numStack.cla(num1,num2,oper);
            //进行运算,将得到结果,入数栈
            numStack.push(res2);
        }
        System.out.printf("表达式%s = %d",expression,numStack.pop());
    }
}

//定义一个栈
class ArrayStack2{
    private int maxSize;//栈的最大值
    private int[] stack;//模拟栈的数组
    private int top = -1;//top表示为栈顶,初始值为-1
    //定义构造器
    public ArrayStack2(int maxSize) {
        this.maxSize = maxSize;
        stack = new int[this.maxSize];
    }
    //判断栈是否为空
    public Boolean isEmpty(){
        return top == -1;
    }
    //判断栈是否是满的
    public Boolean isFull(){
        return top == maxSize -1;
    }
    //入栈
    public void push(int value){
        if (isFull()){
            System.out.println("栈满,无法再入栈");
            return;
        }
        top++;
        stack[top] = value;
    }
    //出栈
    public int pop(){
        if (isEmpty()){
            throw new RuntimeException("当前栈为空,无法取值");
        }
        return stack[top--];
    }
    //返回当前栈顶的值,但是不是出栈
    public int peek(){
        return stack[top];
    }
    //遍历栈
    public void list(){
        if (isEmpty()){
            throw new RuntimeException("当前栈为空,无法取值");
        }
        int tops  = top;
        while (true){
            if (tops == -1){
                break;
            }
            System.out.printf("stack[%d] = %d\n",tops,stack[tops]);
            tops--;
        }
    }
    //返回运算符的优先级,返回的数值越大,优先级越大
    public int priority(int oper){
        if (oper == '*' || oper == '/'){
            return 1;
        }else if (oper == '+' || oper == '-'){
            return 0;
        }else {
            return -1;//目前假定运算符只有+ - * /
        }
    }
    //判断是不是运算符
    public boolean isOper(char oper){
        return oper =='+' || oper == '-' || oper == '*' || oper == '/';
    }
    //计算方法
    public int cla(int num1,int num2,int oper){
        int res = 0;//初始化结果为0
        switch (oper){
            case '+':
                res = num1 + num2;
                break;
            case '-':
                res = num2 - num1;//这里要主要是后一个pop出的数来减去前一个pop的数
                break;
            case '*':
                res = num1 * num2;
                break;
            case '/':
                res = num2 / num1;
                break;
            default:
                break;
        }
        return res;
    }
}

使用栈来实现综合计算器(前缀表达式):

实现思路:

前缀表达式的计算机求值
从右至左扫描表达式,遇到数字时,将数字压入堆栈,遇到运算符时,弹出栈顶的两个数,用运算符对它们做相应的计算(栈顶元素和次顶元素),并将结果入栈;重复上述过程直到表达式最左端,最后运算得出的值即为表达式的结果
例如:(3+4)×5-6对应的前缀表达式就是-×+3456,针对前缀表达式求值步骤如下:
1)从右至左扫描,将6、5、4、3压入堆栈
2)遇到+运算符,因此弹出3和4 (3为栈顶元素,4为次顶元素),计算出3+4的值,得7,再将7入栈
3)接下来是×运算符,因此弹出7和5,计算出7×5=35,将35入栈4)最后是-运算符,计算出35-6的值,即29,由此得出最终结果

在这里插入图片描述

逆波兰计算器:

在这里插入图片描述

实现思路:

后缀表达式的计算机求值
从左至右扫描表达式,遇到数字时,将数字压入堆栈,遇到运算符时,弹出栈顶的两个数,用运算符对它们做相应的计算(次顶元素和栈顶元素),并将结果入栈;重复上述过程直到表达式最右端,最后运算得出的值即为表达式的结果
例如: (3+4)×5-6对应的前缀表达式就是34+5×6-,针对后缀表达式求值步骤如下:
1)从左至右扫描,将3和4压入堆栈;
2)遇到+运算符,因此弹出4和3(4为栈顶元素,3为次顶元素),计算出3+4的值,得7,再将7入栈;
3)将5入栈;
4)接下来是×运算符,因此弹出5和7,计算出7×5=35,将35入栈;5)将6入栈;
6)最后是-运算符,计算出35-6的值,即29,由此得出最终结果

在这里插入图片描述

涉及的小的知识点

Java字符串分割函数split

Java中的我们可以利用[split]把字符串按照指定的分割符进行分割,然后返回字符串数组,

下面是string.split的用法实例及注意事项:

1.split 方法
将一个字符串分割为子字符串,然后将结果作为字符串数组返回。
基本格式 :stringObj.split([separator,[limit]])
(1)stringObj
必选项。要被分解的对象即你想要进行操作的字符串,该对象不会被split方法修改。
(2)separator
可选项。字符串或正则表达式对象可以看做一个字符即你想以此字符进行字符串分割,它标识了分隔字符串时使用的是一个还是多个字符。如果忽略该选项,返回包含整个字符串的单一元素数组。
(3)limit
可选项。该值用来限制返回数组中的元素个数(也就是最多分割成几个数组元素,只有为正数时有影响)
注意split 方法的结果是一个字符串数组,在 stingObj 中每个出现 separator 的位置都要进行分解。separator不作为任何数组元素的部分返回。

例:
String str="Java string split test"; 
      String[] strarray=str.split(" "); //str即为stringObj;
      for (int i = 0; i < strarray.length; i++) 
          System.out.println(strarray[i]); 


输出:

Java 
string 
split 
test 
    
    
    
例:
String str1 = "XXX.YYY.ZZZ";
String[] array1 = str1.split("[.]");  //以句点作为分隔标记(根据正则表达式)
for( int i=0; i<array1.length; i++ ){
	System.out.println( array1[i] );
}


输出:
    XXX
    YYY
    ZZZ
Java matches() 方法

matches() 方法用于检测字符串是否匹配给定的正则表达式。

调用此方法的 str.matches(regex) 形式与以下表达式产生的结果完全相同:

Pattern.matches(regex, str)
语法
public boolean matches(String regex)
参数
  • regex – 匹配字符串的正则表达式。
返回值

在字符串匹配给定的正则表达式时,返回 true。

实例
public class Test {
    public static void main(String args[]) {
        String Str = new String("www.runoob.com");

        System.out.print("返回值 :" );
        System.out.println(Str.matches("(.*)runoob(.*)"));
        
        System.out.print("返回值 :" );
        System.out.println(Str.matches("(.*)google(.*)"));

        System.out.print("返回值 :" );
        System.out.println(Str.matches("www(.*)"));
    }
}

以上程序执行结果为:

返回值 :true
返回值 :false
返回值 :true
正则表达式的基本使用:
\\d+ 就表示多个数字,形如 12446763……
    
\\d+\\.\\d+ 就表示小数,形如12.3340.1287.343……
    
\\d+||(\\d+\\.\\d+)  多个连续的数字或者 多个连续的数+小数点+多个连续的数  即非负整数或者非负小数
Arrays.asList()将数组转list

split拆分出数组,然后ava.util.Arrays.asList(Array),将数组转换成list集合

【1. 要点】

该方法是将数组转化成List集合的方法。

List list = Arrays.asList(“a”,“b”,“c”);

注意:

(1)该方法适用于对象型数据的数组(String、Integer…)

(2)该方法不建议使用于基本数据类型的数组(byte,short,int,long,float,double,boolean)

(3)该方法将数组与List列表链接起来:当更新其一个时,另一个自动更新

(4)不支持add()、remove()、clear()等方法

*总结:如果你的List只是用来遍历,就用Arrays.asList()。*

*如果你的List还要添加或删除元素,还是乖乖地new一个java.util.ArrayList,然后一个一个的添加元素。*

package cn.wyc;
 
import java.util.Arrays;
import java.util.List;
 
public class Test {
    public static void main(String[] args){
 
       //1、对象类型(String型)的数组数组使用asList(),正常
        String[] strings = {"aa", "bb", "cc"};
        List<String> stringList = Arrays.asList(strings);
        System.out.print("1、String类型数组使用asList(),正常:  ");
        for(String str : stringList){
            System.out.print(str + " ");
        }
        System.out.println();
 
 
        //2、对象类型(Integer)的数组使用asList(),正常
        Integer[] integers = new Integer[] {1, 2, 3};
        List<Integer> integerList = Arrays.asList(integers);
        System.out.print("2、对象类型的数组使用asList(),正常:  ");
        for(int i : integerList){
            System.out.print(i + " ");
        }
//        for(Object o : integerList){
//            System.out.print(o + " ");
//        }
        System.out.println();
 
 
        //3、基本数据类型的数组使用asList(),出错
        int[] ints = new int[]{1, 2, 3};
        List intList = Arrays.asList(ints);
        System.out.print("3、基本数据类型的数组使用asList(),出错(输出的是一个引用,把ints当成一个元素了):");
        for(Object o : intList){
            System.out.print(o.toString());
        }
        System.out.println();
 
        System.out.print("   " + "这样遍历才能正确输出:");
        int[] ints1 = (int[]) intList.get(0);
        for(int i : ints1){
            System.out.print(i + " ");
        }
        System.out.println();
 
        //4、当更新数组或者List,另一个将自动获得更新
        System.out.print("4、当更新数组或者List,另一个将自动获得更新:  ");
        integerList.set(0, 5);
        for(Object o : integerList){
            System.out.print(o + " ");
        }
        for(Object o : integers){
            System.out.print (o + " ");
        }
        System.out.println();
 
        //5、add()   remove() 报错
        System.out.print("5、add()   remove() 报错:  ");
//        integerList.remove(0);
//        integerList.add(3, 4);
//        integerList.clear(); 
    }
 
}

输出结果:
1String类型数组使用asList(),正常:  aa bb cc 
2、对象类型的数组使用asList(),正常:  1 2 3 
3、基本数据类型的数组使用asList(),出错(输出的是一个引用,把ints当成一个元素了)[I@1540e19d
   这样遍历才能正确输出:1 2 3 
4、当更新数组或者List,另一个将自动获得更新:  5 2 3 5 2 3 
5add()remove()clear() 报错: 
java中将字符(Char)转换为字符串的四种方式
方法一:使用Character.toString()java

Character类提供了一个静态方法toString()用来将字符转换成字符串。jquery

char ch = 'U';
String charToString = Character.toString(ch);数组

 

方法二:使用字符串链接符字符串

当咱们使用字符串链接符的时候,会自动将其余类型的变量转换为字符串类型,以下:get

char ch = 'U';
String str = "" ch;变量
或
String str = ""+ch;


 
方法三:使用匿名数组(anonymous array)方法

java中的匿名数组能够被用来封装一个单独的字符到字符数组,而后将这个字符数组做为String的构造器参数。总结

char ch = 'U';
String fromChar = new String(new char[]{ch});query

方法四:使用String.valueOf()

 

char ch = 'U';
String valueOfchar = String.valueOf(ch);

代码实现:

package com.iswhl.stack;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Stack;

public class PolandNotation {
    public static void main(String[] args) {
        //定义一个逆波兰表达式(3+4)×5-6
        String expression = "3 4 + 5 * 6 -";//使用空格符作为数值分隔符
        List<String> strings = toList(expression);
        int calcul = calcul(strings);
        System.out.printf("结果为:%s = %d",expression,calcul);
    }

    //定义一个将String转化为list的方法
    public static List<String> toList(String expression){
        //将这个String中的值按照“ ”来进行分割
        String[] split = expression.split(" ");
        //通过Arrays.asList()该方法将一个字符串数组转换成list
        List<String> list = new ArrayList<>(Arrays.asList(split));
        return list;
    }
    //通过逆波兰表达式对list中的表达式进行计算
    public static int calcul(List<String> list){
        //创建一个栈
        Stack<String> stack = new Stack<>();
        //对list进行遍历
        for (String item:list) {
            //判断是否为一对数字
            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是string形式,无法存入int类型的值
                //所有我们需要将 int类型的值    ""+res   通过这种形式来将int类型的值转化为string类型
                stack.push(""+res);
            }
        }
        return Integer.parseInt(stack.pop());
    }
}

中缀表达式转换为后缀表达式

具体步骤如下:

1)初始化两个栈:运算符栈s1和储存中间结果的栈s2;

2)从左至右扫描中缀表达式;

3)遇到操作数时,将其压s2;

4)遇到运算符时,比较其与s1栈顶运算符的优先级:

​ (1)如果s1为空,或栈顶运算符为左括号“(",则直接将此运算符入栈;

​ (2)否则,若优先级比栈顶运算符的高,也将运算符压入s1;

​ (3)否则,将s1栈顶的运算符弹出并压入到s2中,再次转到(4-1)与s1中新的栈顶运算符相比较;

5)遇到括号时:

​ (1)如果是左括号“(”,则直接压入s1

​ (2)如果是右括号“)",则依次弹出s1栈顶的运算符,并压入s2,直到遇到左括号为止,此时将这一对括号丢弃

6)重复步骤2至5,直到表达式的最右边

7)将s1中剩余的运算符依次弹出并压入s2

8)依次弹出s2中的元素并输出,结果的逆序即为中缀表达式对应的后缀表达式

在这里插入图片描述

在这里插入图片描述

代码实现:

package com.iswhl.stack;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Stack;

public class PolandNotation {
    public static void main(String[] args) {
        //定义一个逆波兰表达式(3+4)×5-6
        //String expression = "3 4 + 5 * 6 -";//使用空格符作为数值分隔符
        String expression = "1+((2+3)*4)-5";//使用空格符作为数值分隔符

        List<String> infixList = toInfixList(expression);
        System.out.println("转化后的中缀表达式"+infixList);

        List<String> sufixList = toSufixList(infixList);
        System.out.println("转化后的后缀表达式"+sufixList);

        System.out.println("计算结果为:");
        int calcul = calcul(sufixList);
        System.out.printf("%s = %d",expression,calcul);


//        List<String> strings = toList(expression);
//        int calcul = calcul(strings);
//        System.out.printf("结果为:%s = %d",expression,calcul);
    }
    //将一个string类型的字符串转化为list
    public static List<String> toInfixList(String expression){
        //分析:由于该字符串没有空格将其隔开,所有我们使用传统的遍历方法来进行实现
        //定义一个lsit
        List<String> list = new ArrayList<>();
        int index = 0;//用来进行遍历
        String str;//用来拼接字符串
        char ch;
        do{
            //如果取出的字符为一个字符(这里的48 与 57 对应ASCII中的值,不清楚可以查看ASCII表中的值)
            if ((ch = expression.charAt(index)) < 48 || (ch = expression.charAt(index)) > 57){
                list.add(""+ch);//将一个char转化为string类型
                index++;
            }else {
                str = "";//将str清空
                //说明此时的ch为一个数字
                if (index < expression.length() && (ch = expression.charAt(index)) >= 48 && (ch = expression.charAt(index)) <= 57){
                    str += ch;
                    index++;
                }
                list.add(str);
            }
            }
            while (index < expression.length());
        return list;
    }
    //将一个中缀表达式转化为后缀表达式
    public static List<String> toSufixList(List<String> ls){
        //初始化两个栈:运算符栈s1和储存中间结果的栈s2;
        //s2栈我们使用,list来代替,所有初始化一个list与一个stack
        Stack<String> s1 = new Stack<>();//s1用来存放运算符
        List<String> s2 = new ArrayList<>();//s2用来存放中间结果,其最后结果的顺序输出即为逆波兰表达式
        //遍历ls
        for (String item: ls) {
            //遇到操作数时,将其压s2;
            if(item.matches("\\d+")){//正则表达式,用来判断是否为数字
                s2.add(item);
            }else if (item.equals("(")){//如果是左括号“(”,则直接压入s1
                s1.add(item);
            }else if (item.equals(")")){
                //如果是右括号“)",则依次弹出s1栈顶的运算符,并压入s2,
                // 直到遇到左括号为止,此时将这一对括号丢弃
                while (s1.size() > 0 && !s1.peek().equals("(")){
                    s2.add(s1.pop());
                }
                s1.pop();//将s1中的"("取出丢掉
            }else {//遇到运算符时
                //若优先级比栈顶运算符的低,将s1栈顶的运算符弹出并压入到s2中
                while (s1.size() != 0 && Operation.getValue(item) <= Operation.getValue(s1.peek())){
                    s2.add(s1.pop());
                }
                //若优先级比栈顶运算符的高,也将运算符压入s1;
                s1.push(item);
            }
        }
        //将s1中剩余的运算符依次弹出并压入s2
        while (s1.size() != 0){
            s2.add(s1.pop());
        }
        return s2;
    }

    //定义一个将String转化为list的方法
    public static List<String> toList(String expression){
        //将这个String中的值按照“ ”来进行分割
        String[] split = expression.split(" ");
        //通过Arrays.asList()该方法将一个字符串数组转换成list
        List<String> list = new ArrayList<>(Arrays.asList(split));
        return list;
    }
    //通过逆波兰表达式对list中的表达式进行计算
    public static int calcul(List<String> list){
        //创建一个栈
        Stack<String> stack = new Stack<>();
        //对list进行遍历
        for (String item:list) {
            //判断是否为一对数字
            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是string形式,无法存入int类型的值
                //所有我们需要将 int类型的值    ""+res   通过这种形式来将int类型的值转化为string类型
                stack.push(""+res);
            }
        }
        return Integer.parseInt(stack.pop());
    }
}
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 opersion){
        int result = 0;
        switch (opersion){
            case "+":
                result = ADD;
                break;
            case "-":
                result = SUB;
                break;
            case "*":
                result = MUL;
                break;
            case "/":
                result = DIV;
                break;
            default:
                System.out.println("输入的运算符,不属于加减乘除");
                break;
        }
        return result;
    }
}


运行结果:
转化后的中缀表达式[1, +, (, (, 2, +, 3, ), *, 4, ), -, 5]
输入的运算符,不属于加减乘除
输入的运算符,不属于加减乘除
转化后的后缀表达式[1, 2, 3, +, 4, *, +, 5, -]
计算结果为:
1+((2+3)*4)-5 = 16
进程已结束,退出代码0

们需要将 int类型的值 “”+res 通过这种形式来将int类型的值转化为string类型
stack.push(“”+res);
}
}
return Integer.parseInt(stack.pop());
}
}
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 opersion){
    int result = 0;
    switch (opersion){
        case "+":
            result = ADD;
            break;
        case "-":
            result = SUB;
            break;
        case "*":
            result = MUL;
            break;
        case "/":
            result = DIV;
            break;
        default:
            System.out.println("输入的运算符,不属于加减乘除");
            break;
    }
    return result;
}

}

运行结果:
转化后的中缀表达式[1, +, (, (, 2, +, 3, ), *, 4, ), -, 5]
输入的运算符,不属于加减乘除
输入的运算符,不属于加减乘除
转化后的后缀表达式[1, 2, 3, +, 4, *, +, 5, -]
计算结果为:
1+((2+3)*4)-5 = 16
进程已结束,退出代码0


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

三横同学

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值