数据结构和算法之栈1

33 篇文章 0 订阅
32 篇文章 0 订阅

数组模拟栈

(1)将数组模拟成栈的思想:

//用数组模拟栈的思想:
* 1·先创建栈,用数组
* 2·定义一个变量top表示栈顶,初始化为-1
* 3·入栈:top++,stack[top]=val,要进行栈满的操作
* 4·出栈:数据取出:int value=stack[top];top--即可,要进行判断栈为空的操作,因为有返回值,所以一般我们进行异常抛出*/

1.1:注意:因为是拿数组进行模拟栈

1:在栈类中有一个数组
2:在栈类中有一个maxSize定义栈的大小;因为栈是有大小的
3:在栈类中必须有一个指针一直指向栈顶,初始值为-1;
4:其次是在栈类中写入方法,模拟实现栈即可

1.2:栈的代码如下所示

package com.dataStrcture;
import java.util.Scanner;
//用数组模拟栈
/*思想:
* 1·先创建栈,用数组
* 2·定义一个变量top表示栈顶,初始化为-1
* 3·入栈:top++,stack[top]=val,要进行栈满的操作
* 4·出栈:数据取出:int value=stack[top];top--即可,要进行判断栈为空的操作,因为有返回值,所以一般我们进行异常抛出*/
class ArrayStack{
    public int maxSize;//栈的大小
    public int[]stack;
    public int top=-1;//栈顶,初始化为-1;

    //构造器:
    public ArrayStack(int maxSize) {
        this.maxSize = maxSize;
        stack=new int[maxSize];//初始化栈的大小
    }

    //栈满
    public boolean isFull(){
        return top==maxSize-1;//当栈满的时候top=maxSize-1;
    }

    //栈空
    public boolean isEmpty(){
        return top==-1;
    }

    //入栈:push
    public void push(int val){
        //要先判断栈是否满了
        if(isFull()){
            System.out.println("栈满了");
            return;
        }
        top++;
        stack[top]=val;
    }

    //出栈:pop:将栈顶的数据进行返回,并且top--
    public int pop(){
        if(isEmpty()){
            //有返回值的话,可以进行抛出异常,不然返回的就是有数据的
            throw new RuntimeException("栈是空的,无元祖进行返回");
        }
        int value=stack[top];
        top--;
        return value;
    }

    //显示栈中的所有值,进行栈遍历
    public void showStack(){
        //遍历时,需要从栈顶遍历数据
        if(isEmpty()){
            System.out.println("栈为空,没有数据可以显示");
            return;
        }
        for(int i=top;i>=0;i--){//要从栈顶开始遍历栈
            System.out.println("stack["+i+"]="+stack[i]);
        }
    }
}

public class Stack {
    public static void main(String[] args) {
        //测试ArrayStack
        ArrayStack stack=new ArrayStack(4);
        String key="";
        boolean loop=true;//控制是否输出菜单
        Scanner input = new Scanner(System.in);

        while(loop){
            System.out.println("show:显示栈");
            System.out.println("exit:退出");
            System.out.println("push:表示将数据入栈");
            System.out.println("pop:表示将数据出栈");
            System.out.println("请输入你的选择:");
            key=input.next();
            switch (key){
                case "show":
                    stack.showStack();
                    break;
                case "push":
                    System.out.println("请输入你要入栈的元素:");
                    int value=input.nextInt();
                    stack.push(value);
                    break;
                case "pop":
                    try{
                        int res=stack.pop();
                        System.out.println("出栈的数据是:"+res);
                    }catch (Exception e){
                        System.out.println(e.getMessage());//如果发生异常,打印在pop中处理的异常结果即可
                    }
                    break;
                case "exit":
                    input.close();
                    loop=false;
                    break;
                default:
                    break;
            }
        }
        System.out.println("程序退出");
    }
}

(2)栈的应用:中缀表达计算器
2.1:计算器的思想:

//中缀表达计算器:
//首先要创建一个栈:需要进行扩展功能:优先级的判断;数字与符号的判断
/*用栈实现综合计算器
* 1·通过一个index指针进行遍历输入的表达式
* 2·如果发现是数字进行入(数字)栈操作
* 3·如果发现是运算符进行入(运算符)栈操作
    * 3.1·如果发现运算符栈是空的就直接入栈
    * 3.2·如果运算符栈不为空,则就与运算符栈栈顶的元素进行优先级的比对:
           * 3.2.1·若优先级低于栈顶运算符,则数栈出栈两位数,运算符栈出栈一位,然后进行计算,将计算的结果进行入栈到数栈中,
                * 然后将当前优先级低的运算符进行入栈(运算符)处理
           * 3.2.2·若优先级高于栈顶运算符就直接入运算符栈
* 4·当表达式扫描完毕后,依次从数栈和字符栈中pop出相应的数字和运算符进行运算
* 5·最后一个在数栈中的就是结果
* 6·总结:上面的思路只能解决一位数的加减乘除
* 7·优化:解决多位数的运算器
* 7.1·在扫描为一个数字时,不着急入栈,要向后进行扫描,
    * 看看后面是否还有数字,若还是有的话进行拼接,若为运算符的话,就直接入(数)栈
    * 注意:拼接的时候将用于拼接的那个变量进行清空即可,不然拼接后的数字有错
    * */

2.2:代码如下所示:

package com.dataStrcture;
class ArrayStack1{
    public int maxSize;//栈的大小
    public int[]stack;
    public int top=-1;//栈顶,初始化为-1;

    //构造器:
    public ArrayStack1(int maxSize) {
        this.maxSize = maxSize;
        stack=new int[maxSize];//初始化栈的大小
    }

    //栈满
    public boolean isFull(){
        return top==maxSize-1;//当栈满的时候top=maxSize-1;
    }

    //栈空
    public boolean isEmpty(){
        return top==-1;
    }

    //入栈:push
    public void push(int val){
        //要先判断栈是否满了
        if(isFull()){
            System.out.println("栈满了");
            return;
        }
        top++;
        stack[top]=val;
    }

    //出栈:pop:将栈顶的数据进行返回,并且top--
    public int pop(){
        if(isEmpty()){
            //有返回值的话,可以进行抛出异常,不然返回的就是有数据的
            throw new RuntimeException("栈是空的,无元祖进行返回");
        }
        int value=stack[top];
        top--;
        return value;
    }

    //返回一个栈栈顶的数值,但不是真正的出栈(pop),只是知道里面存的是什么进行看一眼,比对一下即可
    public int peek(){

        return stack[top];
    }

    //显示栈中的所有值,进行栈遍历
    public void showStack(){
        //遍历时,需要从栈顶遍历数据
        if(isEmpty()){
            System.out.println("栈为空,没有数据可以显示");
            return;
        }
        for(int i=top;i>=0;i--){//要从栈顶开始遍历栈
            System.out.println("stack["+i+"]="+stack[i]);
        }
    }

    //返还运算符的优先级,优先级由程序员来确定,优先级使用数字来进行表示:数字越大优先级越高
    public int priority(int oper){//在java中char和int是可以互用的,char的底层比较就是int数值的比较
        if(oper=='*'||oper=='/'){
            return 1;
        }else if(oper=='+'||oper=='-'){
            return 0;
        }else {
            return -1;//假定目前的运行符只有加减乘除
        }
    }

    //判断是是不是一个运算符
    public boolean isOper(char val){
        return val=='*'||val=='/'||val=='+'||val=='-';
    }//返回时真的话就是运算符

    //进行计算的方法
    public int cal(int num1,int num2,int oper){
        int result=0;
        switch (oper){
            case '+':
                result=num1+num2;
                break;
            case '-':
                result=num2-num1;//注意顺序
                break;
            case '*':
                result=num1*num2;
                break;
            case '/':
                result=num2/num1;
                break;
            default:
                 break;
        }
        return result;
    }

}
public class StackCalculator {
    public static void main(String[] args) {
        //根据思路,完成表达式的运算:
        String exception="70+2*6-2";
        //创建两个栈,就是数栈和符号栈
        ArrayStack1 numStack=new ArrayStack1(10);
        ArrayStack1 operStack=new ArrayStack1(10);
        //创建一个变量用来扫描字符串
        int index=0;//用来扫描的
        int num1=0;
        int num2=0;
        int oper=0;
        int result=0;
        char ch=' ';//将每次扫描的char保存到ch中
        String keepNum="";//用于拼接多位数
        while(true) {
            //依次得到扫描字符串得到的字符:exception
            ch = exception.substring(index, index + 1).charAt(0);

            //开始进行判断:然后做出相应的处理
            if (operStack.isOper(ch)) {//如果扫描的是运算符
                //第一就是得判断,符号栈是否为空
                if (!operStack.isEmpty()) {//当前符号栈不为空,也就是说要进行优先级的比较
                    //进行处理:
                    // 比较后,从符号栈中pop出一个运算符,然后从数栈中pop出两个数进行运算即可
                    if (operStack.priority(ch) <= operStack.priority(operStack.peek())) {//进行与符号栈栈顶的符号进行优先级的比对
                        num1 = numStack.pop();
                        num2 = numStack.pop();
                        oper = operStack.pop();//也就是数栈弹出两个,符号栈弹出一个进行运算
                        result = numStack.cal(num1, num2, oper);

                        //然后将运算后的结果进行入栈
                        numStack.push(result);

                        //然后还要将当前优先级低的进行如符号栈
                        operStack.push(ch);

                    } else {//反之,当前的运算符的优先级高于运算符栈顶的运算符
                        operStack.push(ch);
                    }
                } else {
                    //表示当前符号栈不为空的时候,进行入栈处理
                    operStack.push(ch);
                }

            } else {/*当ch为数值的时候,直接入栈:
            注意:1·不能一发现是数的时候进行入栈处理
                  2·70:就得向后再看一位,若果是符号的话,将数字进行入栈,如果还是数字的话就得进行拼接,将拼接的结果入栈
                  3·因此我们要定义一个变量 字符串,用于拼接*/

                //处理多位数:
                keepNum += ch;

                //如果:ch是exception的最后一位,不用再进行扫描,直接入栈即可
                if (index == exception.length() - 1) {
                    numStack.push(Integer.parseInt(keepNum));
                } else {
                    //拼接完成了之后,判断下一个字符是否还是数字,若是数字继续进行扫描即可,如果是运算符,直接将其数字入栈即可
                    //注意:只是向后看一位,所以index是不变的
                    if (operStack.isOper(exception.substring(index + 1, index + 2).charAt(0))) {
                        //如果后一位是运算符,就直接入栈:keepNum="1";或者"123"
                        numStack.push(Integer.parseInt(keepNum));//字符串转int

                        //重要!!!!要讲keepNum清空,因为下个数字进行拼接的时候是一个新的
                        keepNum = "";
                    }
                    //numStack.push(ch - 48);//因为之后后读入的是字符,而不是整数,在ASC码表中
                }
            }
            //让index+1,(也就是index一直遍历)看看是否到了扫描的是字符串的最后一个的时候,也就是循环跳出的时候
            index++;
            if(index>=exception.length()){
                break;
            }
        }

        //当表达式扫描完毕的话,就顺序的从 数栈和符号栈进行pop处理,进行运算即可
        while (true){
            //如果符号栈为空,则就是计算到最后一次计算,也就是最后的结果,数栈中也只有一个数值(结果)
            if(operStack.isEmpty()){
                break;
            }
            num1=numStack.pop();
            num2=numStack.pop();
            oper=operStack.pop();
            result=numStack.cal(num1,num2,oper);
            numStack.push(result);//入栈
        }
        //将数栈中的左后一个数pop出来就可以,就是表达式的结
        System.out.println("表达式:"+exception.toString()+"="+numStack.pop());
    }
}

2.3:运行结果如下所示:
在这里插入图片描述

(3)总结: 该方法就是利用中缀实现表达式的运算求解;对于计算机来说有点麻烦,速度不够快。所有可以使用前后缀的方法可以进行实现,一般使用的是后缀。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值