栈 - 快速入门

概述

  • 栈是限制线性表中元素的插入和删除只能在线性表的同一端进行的一种特殊线性表。允许插入和删除的一端,为变化的一端,称为栈顶,另一端为固定的一端,称为栈底。
  • 根据栈的定义可知,最先放入栈中元素在栈底,最后放入的元素在栈顶,而删除元素刚好相反,最后放入的元素最先删除,最先放入的元素最后删除。

应用场景

  • 子程序的调用: 在跳往子程序前, 会先将下一个指令的地址存到栈中, 直到子程序执行完后再将地址取出, 回到原来的位置 如浏览器的后退/向前, JVM的虚拟机栈
  • 表达式的转换(如 中缀表达式转后缀表达式)与求值
  • 二叉树的遍历
  • 图形的深度优先(depth-first)搜索法

数组模拟栈

/** 定义数组栈*/
class ArrayStack {
    /** 栈大小*/
    private int maxSize;
    /** 通过该数组存放数据, 模拟栈数据结构*/
    private int[] stack;
    /** 栈顶的 index, 初始值为-1*/
    private int top = -1;

    public ArrayStack(int maxSize) {
        this.maxSize = maxSize;
        stack = new int[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++;
        stack[top] = value;
    }

    /** 出/弹栈*/
    public int pop() {
        if (isEmpty()) {
            throw new RuntimeException("出栈失败, 没有数据!");
        }
        int value = stack[top];
        top--;
        return value;
    }

    /** 从栈顶开始打印所有内容*/
    public void list() {
        if (isEmpty()) {
            System.out.println("打印失败, 没有数据!");
            return;
        }
        for (int i = top; i >= 0; i--) {
            System.out.printf("stack[%d]=%d\n", i, stack[i]);
        }
    }
}

public class ArrayStackApp {
    public static void main(String[] args) {
        System.out.println("push(添加数据到栈顶)");
        System.out.println("pop(从栈取数据)");
        System.out.println("show(打印栈所有内容)");
        System.out.println("exit(退出程序)");
        /** 创建数组栈实例*/
        ArrayStack stack = new ArrayStack(3);
        String command;
        boolean loop = true;
        Scanner scanner = new Scanner(System.in);
        while (loop) {
            System.out.println("请输入命令!");
            command = scanner.next();
            switch (command) {
                case "show":
                    stack.list();
                    break;
                case "push":
                    System.out.println("请输入数值!");
                    int value = scanner.nextInt();
                    stack.push(value);
                    break;
                case "pop":
                    try {
                        int result = stack.pop();
                        System.out.printf("数据 %d已出栈!\n", result);
                    } catch (Exception e) {
                        System.out.println(e.getMessage());
                    }
                    break;
                case "exit":
                    scanner.close();
                    loop = false;
                    break;
                default:
                    break;
            }
        }

        System.out.println("程序结束!");
    }

}

单链表模拟栈

/** 定义节点*/
class Node {
    int no;
    Node next;

    /** 创建一个新的节点, 同时 next指向, 之前的栈顶节点*/
    public Node(int no, Node next){
        this.no = no;
        this.next = next;
    }

    public int getNo() {
        return no;
    }
}

/** 定义不带头的单向链表栈*/
class ListStack {
    /** 栈大小*/
    int size;
    /** 栈内有效节点个数*/
    int count;
    /** 栈顶节点*/
    Node currentNode;

    public ListStack(int size) {
        this.size = size;
        this.count = 0;
        this.currentNode = null;
    }

    /** 栈满*/
    public boolean isFull() {
        return count == size ? true: false;
    }

    /** 栈空*/
    public boolean isEmpty() {
        return count == 0 ? true: false;
    }

    /** 入/压栈*/
    public void push(int value) {
        if (isFull()) {
            System.out.println("入栈失败, 栈已满!");
            return;
        }
        /** 新建节点, 再将它设为栈顶节点, 此节点的 next是引用了, 之前的栈顶节点*/
        currentNode = new Node(value, currentNode);
        /** 递增有效节点个数*/
        count++;
    }

    /** 出/弹栈*/
    public int pop() {
        if (isEmpty()) {
            throw new RuntimeException("出栈失败, 没有数据!");
        }
        int no = currentNode.getNo();
        /** 将当前下一个节点覆盖当前节点*/
        currentNode = currentNode.next;
        /** 递减有效节点个数*/
        count--;
        return no;
    }

    /** 打印栈顶的节点内容*/
    public void peak(){
        if (isEmpty()) {
            System.out.println("打印失败, 没有数据!");
            return;
        }
        System.out.println(currentNode.getNo());
    }

    /** 打印栈的所有节点内容*/
    public void show(){
        if (isEmpty()) {
            System.out.println("打印失败, 没有数据!");
            return;
        }

        Node temp = currentNode;
        int i = count;
        while (true) {
            if (temp == null) {
                return;
            }
            System.out.printf("stack[%d]=%d\n", i, temp.getNo());
            i--;
            temp = temp.next;
        }
    }
}

public class SingleLinkedListStackApp {
    public static void main(String[] args) {
        System.out.println("push(添加数据到栈顶)");
        System.out.println("pop(从栈取数据)");
        System.out.println("peak(打印栈顶的节点内容)");
        System.out.println("show(打印栈的所有节点内容)");
        System.out.println("exit(退出程序)");
        /** 创建链表栈实例*/
        ListStack stack = new ListStack(3);
        String command;
        boolean loop = true;
        Scanner scanner = new Scanner(System.in);
        while (loop) {
            System.out.println("请输入命令!");
            command = scanner.next();
            switch (command) {
                case "push":
                    System.out.println("请输入数值!");
                    int value = scanner.nextInt();
                    stack.push(value);
                    break;
                case "pop":
                    try {
                        int result = stack.pop();
                        System.out.printf("数据 %d已出栈!\n", result);
                    } catch (Exception e) {
                        System.out.println(e.getMessage());
                    }
                    break;
                case "peak":
                    stack.peak();
                    break;
                case "show":
                    stack.show();
                    break;
                case "exit":
                    scanner.close();
                    loop = false;
                    break;
                default:
                    break;
            }
        }

        System.out.println("程序结束!");
    }

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值