数据结构与算法(四)之栈

栈简介

栈是一个先入后出(FILO)的有序列表,最先放入的数据在栈底,最后放入的元素在栈顶,最后放入的元素先删除,最先放入的先删除。

栈的实现

public class Stack {
    private int[] stack;
    private int top;
    private int maxSize;
    public Stack(int maxSize){
        this.stack=new int[maxSize];
        this.maxSize=maxSize;
        this.top=0;
    }

    public boolean isFull(){
        return top==maxSize;
    }

    public boolean isEmpty(){
        return top==0;
    }

    public boolean push(int value){
        if(isFull()) return false;
        this.stack[top]=value;
        top++;
        return true;
    }

    public Integer pop(){
        if(isEmpty()) return null;
        int value=stack[top];
        top--;
        return value;
    }
}

中缀表达式的计算

算法思路

比如计算:3+2*6-2
算法步骤如下:
维护2个栈数字栈和符号栈

  1. 从前往后扫描如果遇到数字,直接入数字栈。
  2. 如果遇到符号分为以下3种情况:
  • 如果符号栈为空,直接入栈。
  • 如果符号栈不为空且符号优先级小于或等于栈顶元素,那么pop出两个数字运算,然后将结果重新入栈。
  • 如果符号栈不为空且符号优先级大于栈顶元素,符号直接入栈

代码实现

牛客网地址:https://www.nowcoder.com/questionTerminal/7b18aa6b7cc14f8eaae6b8acdebf890b?toCommentId=103161

import java.util.Scanner;
import java.util.Stack;

public class Main {
    public static void main(String[] args) throws Exception {
        Scanner cin = new Scanner(System.in);
        Main m=new Main();
        while (cin.hasNext()){
            String exp=cin.next();
            float res=m.nifix(exp);
            System.out.println((int)res);
        }

    }
    public float nifix(String expression){
        Stack<Float> numberStack=new Stack<>();
        Stack<Character> symbolStack=new Stack<>();
        String digit="";
        for(int i=0;i<expression.length();i++){
            char x=expression.charAt(i);
            if(Character.isDigit(x)){
                digit+=String.valueOf(x);
                if(i+1>=expression.length()||!Character.isDigit(expression.charAt(i+1))){
                    numberStack.push(Float.parseFloat(digit));
                    digit="";
                }

            }else {
                while (!symbolStack.isEmpty()&&priority(symbolStack.peek())>=priority(x)){
                    char y=symbolStack.pop();
                    float res=calRes(y,numberStack.pop(),numberStack.pop());
                    numberStack.push(res);
                }
                symbolStack.push(x);
            }
        }
        while (!symbolStack.isEmpty()){
            char y=symbolStack.pop();
            float res=calRes(y,numberStack.pop(),numberStack.pop());
            numberStack.push(res);
        }
        return numberStack.pop();
    }
    //判断符号的优先级
    private int priority(char x){
        if(x =='+'|| x =='-'){
            return 1;
        }else{
            return 2;
        }

    }
    //计算结果
    private float calRes(char x,float num1,float num2){
        float res=0;
        switch (x){
            case '+':
                res=num1+num2;
                break;
            case '-':
                res=num2-num1;
                break;
            case '*':
                res=num1*num2;
                break;
            case '/':
                res=num2/num1;
                break;
        }
        return res;

    }
}

后缀表达式的计算

算法思路

后缀表达式的例子:
(3+4)x5-6对应的后缀表达式就是34+5x6-。
计算机处理后缀表达式是很直接的,维护一个栈就可以完成计算。

代码实现

import java.util.Scanner;
import java.util.Stack;

public class Main {
    public static void main(String[] args) throws Exception {
        Scanner cin = new Scanner(System.in);
        Main m=new Main();
        while (cin.hasNext()){
            String exp=cin.next();
            float res=m.postfix(exp);
            System.out.println((int)res);
        }

    }
    public float postfix(String expression){
        String[] expressionItem=expression.split(" ");
        Stack<Float> stack=new Stack<>();
        for(int i=0;i<expressionItem.length;i++){
            String item=expressionItem[i];
            if(isNumeric(item)){
                stack.push(Float.parseFloat(item));
            }else {
                stack.push(cal(item,stack.pop(),stack.pop()));
            }

        }
        return stack.pop();
    }
    private static boolean isNumeric(String str){
        for (int i = str.length();--i>=0;){
            if (!Character.isDigit(str.charAt(i))){
                return false;
            }
         }
        return true;
    }
    //计算结果
    private float cal(String item,float num1,float num2){
        float res=0;
        if(item.equals("+")){
            res=num2+num1;
        }else if(item.equals("-")){
            res=num2-num1;
        }else if(item.equals("/")){
            res=num2/num1;
        }else if(item.equals("*")){
            res=num2*num1;
        }
        return res;

    }
}

中缀表达式转后缀表达式

限制必须是1位数
输入:
a+bc/d-a+f/b
输出:
abc
d/+a-fb/+

算法思路

  • 从左到右开始扫描中缀表达式
  • 遇到数字时,加入后缀表达式
  • 遇到运算符时:
    a.若为’(’,入栈
    b.若为’)’,则依次将栈中的运算符加入到后缀表达式中,直到出现’(‘为止,从栈中删除’(’
    c.若为除括号外的其它运算符,当优先级高于除’('以外的栈顶运算符时,直接入栈;否则从栈顶开始,依次弹出比当前处理的运算符优先级高和优先级相等的运算符,直到出现一个比它优先级低或者遇到了一个左括号为止。

代码实现

import java.util.Scanner;
import java.util.Stack;

public class Main {
    public static void main(String[] args) throws Exception {

        Scanner cin = new Scanner(System.in);
        Main m = new Main();
        while (cin.hasNext()) {
            String exp = cin.next();
            String res = m.niToPost(exp);
            System.out.println(res);
        }
    }

    //判断是否是数字
    private static boolean isNumeric(char c) {
        if (c == '+' || c == '-' || c == '*' || c == '/' || c == '(' || c == ')')
            return false;
        return true;
    }

    public String niToPost(String expression) {
        char[] res = new char[expression.length()];
        int index = 0;
        Stack<Character> symbolStack = new Stack<>();
        for (int i = 0; i < expression.length(); i++) {
            char x = expression.charAt(i);
            if (isNumeric(x)) {
                res[index] = x;
                index++;
            } else if (x == '(') {
                symbolStack.push(x);
            } else if (x == ')') {
                while (symbolStack.peek() != '(') {
                    res[index] = symbolStack.pop();
                    index++;
                }
                symbolStack.pop();
            } else {
                while (!symbolStack.isEmpty() && symbolStack.peek() != '(' && priority(symbolStack.peek()) >= priority(x)) {
                    res[index] = symbolStack.pop();
                    index++;
                }
                symbolStack.push(x);
            }

        }
        while (!symbolStack.isEmpty()) {
            res[index] = symbolStack.pop();
            index++;
        }
        return String.valueOf(res);
    }

    //判断符号的优先级
    private int priority(char x) {

        if (x == '+' || x == '-') {
            return 1;
        } else if (x == '*' || x == '/') {
            return 2;
        }
        return 0;
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值