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

Posted 达少Rising

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了数据结构与算法(Java)之栈相关的知识,希望对你有一定的参考价值。

数组实现栈

package com.weeks.stack;

import java.util.Scanner;

/**
 * @author 达少
 * @version 1.0
 */
public class ArrayStackDemo {
    public static void main(String[] args) {
        //创建栈
        ArrayStack arrayStack = new ArrayStack(4);
        //创建输入扫描器,并接收用户输入
        Scanner scanner = new Scanner(System.in);
        char key = ' ';
        //控制while循环
        boolean loop = true;
        //测试各个方法
        while(loop){
            System.out.println("\\n栈操作方法菜单:\\n" +
                    "1 push 数据入栈\\n" +
                    "2 pop  数据出栈\\n" +
                    "3 list 显示栈中数据\\n" +
                    "4 exit 退出程序\\n");
            System.out.print("请输入你的选择:");
            key = scanner.next().charAt(0);
            switch (key){
                case '1':
                    System.out.print("请输入一个整数:");
                    int value = scanner.nextInt();
                    arrayStack.push(value);
                    break;
                case '2':
                    try {
                        int res = arrayStack.pop();
                        System.out.printf("本次出栈的数据为:%d\\n", res);
                    } catch (Exception e) {
                        System.out.println(e);
                    }
                    break;
                case '3':
                    arrayStack.list();
                    break;
                case '4':
                    scanner.close();
                    loop = false;
                    break;
                default:
                    break;
            }
        }
        System.out.println("退出程序~~~");
    }
}

class ArrayStack{
    private int maxSize;//表示栈的容量
    private int top = -1;//表示栈顶,默认值为-1
    private int[] stack;//使用数组模拟栈

    //在有参构造方法中初始化栈
    public ArrayStack(int maxSize){
        this.maxSize = maxSize;
        this.stack = 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;
        }
        //入栈
        stack[++top] = value;
    }

    //数据出栈
    public int pop(){
        //判断是否栈空
        if(isEmpty()){
            throw new RuntimeException("栈已空,没有数据可以出栈!!!");
        }
        //出栈过程
        //1.将出栈数据赋值给临时变量
        int res = stack[top];
        //2.top下移
        top--;
        //3.将出栈数据返回
        return res;
    }

    //遍历栈
    public void list(){
        //判断栈是否为空
        if(isEmpty()){
            System.out.println("栈已空,没有数据可遍历!!!");
            return;
        }
        //遍历
        for(int i = top; i > -1; i--){
            System.out.printf("arr[%d]=%d\\n", i, stack[i]);
        }
    }
}

单链表实现栈

package com.weeks.stack;

import java.util.Scanner;

/**
 * @author 达少
 * @version 1.0
 * 使用单链表的头插法实现栈
 */
public class LinkedListStackDemo {
    public static void main(String[] args) {
        //创建栈
        LinkedListStack stack = new LinkedListStack();
        //创建输入扫描器,并接收用户输入
        Scanner scanner = new Scanner(System.in);
        char key = ' ';
        //控制while循环
        boolean loop = true;
        //测试各个方法
        while(loop){
            System.out.println("\\n栈操作方法菜单:\\n" +
                    "1 push 数据入栈\\n" +
                    "2 pop  数据出栈\\n" +
                    "3 list 显示栈中数据\\n" +
                    "4 exit 退出程序\\n");
            System.out.print("请输入你的选择:");
            key = scanner.next().charAt(0);
            switch (key){
                case '1':
                    System.out.print("请输入一个整数:");
                    int value = scanner.nextInt();
                    stack.push(value);
                    break;
                case '2':
                    try {
                        int res = stack.pop();
                        System.out.printf("本次出栈的数据为:%d\\n", res);
                    } catch (Exception e) {
                        System.out.println(e);
                    }
                    break;
                case '3':
                    stack.list();
                    break;
                case '4':
                    scanner.close();
                    loop = false;
                    break;
                default:
                    break;
            }
        }
        System.out.println("退出程序~~~");
    }
}

class LinkedListStack{
    //头节点不存储具体的数据
    private Node head = new Node(0);

    //空栈判断
    public boolean isEmpty(){
        return head.getNext() == null;
    }

    //入栈使用头插法插入链表
    public void push(int value){
        //创建入栈节点
        Node node = new Node(value);
        //插入到链表的头节点下一个位置
        node.setNext(head.getNext());
        head.setNext(node);
    }

    //出栈,因为使用头插法入栈,所以要从链表的头节点的下一个位置开始出栈
    public int pop(){
        //判断是否空栈
        if (isEmpty()){
            throw new RuntimeException("栈已空,没有数据可以出栈!!!");
        }
        //出栈
        //1.将要出栈的节点数据赋值给临时变量
        int res = head.getNext().getData();
        //2.将出栈的节点从链表中删除
        head.setNext(head.getNext().getNext());
        return res;
    }

    //遍历栈,从头节点的下一个位置开始输出链表数据
    public void list(){
        //判断是否空栈
        if(isEmpty()){
            System.out.println("栈已空,不可遍历!!!");
            return;
        }
        //头节点不能动,需要定义辅助变量遍历栈
        Node cur = head.getNext();
        while(cur != null){
            System.out.println(cur);
            //下移cur
            cur = cur.getNext();
        }
    }
}

class Node{
    private int data;
    private Node next;

    public Node(int data){
        this.data = data;
    }
    public int getData() {
        return data;
    }

    public void setData(int data) {
        this.data = data;
    }

    public Node getNext() {
        return next;
    }

    public void setNext(Node next) {
        this.next = next;
    }

    @Override
    public String toString() {
        return "Node = " + data;
    }
}

栈实现综合计算器

中缀表达式

package com.weeks.stack.calculator;

/**
 * @author 达少
 * @version 1.0
 * 使用栈实现综合计算(中缀表达式的计算)
 */
public class CalculatorDemo {
    public static void main(String[] args) {
        //创建数栈
        LinkedListStack numStack = new LinkedListStack();
        //创建符号栈
        LinkedListStack operatorStack = new LinkedListStack();

        //计算表达式
        String expression = "700+2*6-2";

        //创建辅助变量
        int index = 0;//帮助扫描计算表达式
        char curChar = ' ';
        String keepNum = "";//定义变量拼接数字符号
        //扫描计算表达式,入栈规则:
        //1.当所扫描的字符是数字,可以直接压入数栈中
        //2.当所扫描的字符是操作符,有三种情况:
        //  1)当符号栈为空栈时,当前操作符直接压入符号栈中
        //  2)当前操作符的优先级小于或等栈顶的操作符时,将栈顶操作符弹出,
        //    并在数栈中弹出两个数,进行运算,将运算的结果压入数栈中,并将当前操作符压入符号栈
        //  3)当前操作符的优先级大于栈顶的操作符时,当前操作符直接入栈
        while(index < expression.length()){
            //将当前index位置的字符取出
            curChar = expression.substring(index, index+1).charAt(0);
            //判断当前的字符是否为操作符
            if(operatorStack.isOperator(curChar)){
                //当符号栈为空栈时,当前操作符直接压入符号栈中
                if (operatorStack.isEmpty()){
                    operatorStack.push(curChar);
                }else if(operatorStack.priority(curChar) <= operatorStack.priority((char) operatorStack.getTop())){
                    //当前操作符的优先级小于或等栈顶的操作符时,将栈顶操作符弹出,
                    //并在数栈中弹出两个数,进行运算,将运算的结果压入数栈中,并将当前操作符压入符号栈
                    char opr = (char) operatorStack.pop();
                    int num1 = 0;
                    int num2 = 0;
                    try {
                        num1 = numStack.pop();
                        num2 = numStack.pop();
                    } catch (Exception e) {
                        System.out.println(e.getMessage());
                    }
                    int res = numStack.calculate(num1, num2, opr);
                    numStack.push(res);
                    operatorStack.push(curChar);
                }else{
                    operatorStack.push(curChar);
                }
            }else{//当前字符为数字
                //当前的字符是数字也分两种情况:
                //1.字符串已经到末尾了
                //2.字符串还没到末尾,下一个字符也是数字
                //numStack.push(curChar - 48);//ascii码表
                if(index == expression.length() - 1){
                    //1.字符串已经到末尾了,当前字符直接入栈
                    numStack.push(curChar - 48);//ascii码表
                }else{
                    //当前数字符号与keepNum拼接
                    keepNum += curChar;
                    //判断下一个字符的类型
                    char nextChar = expression.substring(index+1, index+2).charAt(0);
                    if(operatorStack.isOperator(nextChar)){
                        //如果下一个是符号类型将当前的字符串数字直接入栈
                        numStack.push(Integer.parseInt(keepNum));
                        //入栈后要清空keepNum
                        keepNum = "";
                    }
                }
            }
            index++;//index自增
        }
        while(true){
            if(operatorStack.isEmpty()){
                break;
            }
            char opr = (char) operatorStack.pop();
            int num1 = numStack.pop();
            int num2 = numStack.pop();
            int res = numStack.calculate(num1, num2, opr);
            numStack.push(res);
        }
        System.out.printf("计算的结果%s = %d", expression, numStack.pop());
    }
}

class LinkedListStack{
    //头节点不存储具体的数据
    private Node head = new Node(-1);

    //空栈判断
    public boolean isEmpty(){
        return head.getNext() == null;
    }

    //入栈使用头插法插入链表
    public void push(int value){
        //创建入栈节点
        Node node = new Node(value);
        //插入到链表的头节点下一个位置
        node.setNext(head.getNext());
        head.setNext(node);
    }

    //出栈,因为使用头插法入栈,所以要从链表的头节点的下一个位置开始出栈
    public int pop(){
        //判断是否空栈
        if (isEmpty()){
            throw new RuntimeException("栈已空,没有数据可以出栈!!!");
        }
        //出栈
        //1.将要出栈的节点数据赋值给临时变量
        int res = head.getNext().getData();
        //2.将出栈的节点从链表中删除
        head.setNext(head.getNext().getNext());
        return res;
    }

    //遍历栈,从头节点的下一个位置开始输出链表数据
    public void list(){
        //判断是否空栈
        if(isEmpty()){
            System.out.println("栈已空,不可遍历!!!");
            return;
        }
        //头节点不能动,需要定义辅助变量遍历栈
        Node cur = head.getNext();
        while(cur != null){
            System.out.以上是关于数据结构与算法(Java)之栈的主要内容,如果未能解决你的问题,请参考以下文章

JAVA数据结构与算法之栈~ 中缀表达式转换为后缀表达式

我的算法日志:数据结构之栈

算法习题---栈与队列之栈的数学性质

java数据结构和算法

数据结构之栈

浅谈PHP数据结构之栈