zoukankan      html  css  js  c++  java
  • 5 手写Java Stack 核心源码

    Stack是Java中常用的数据结构之一,Stack具有"后进先出(LIFO)"的性质。
    只能在一端进行插入或者删除,即压栈与出栈

    栈的实现比较简单,性质也简单。可以用一个数组来实现栈结构。

    1. 入栈的时候,只在数组尾部插入
    2. 出栈的时候,只在数组尾部删除**

    我们来看一下Stack的用法 :如下

      public static void main(String[] args){
    
            //新建一个栈
            Stack<String> stack = new Stack<>();
    
            //分别向栈中添加不同的元素
            stack.push("tom");
            stack.push("jim");
            stack.push("wendy");
            stack.push("natasha");
    
            //分别弹栈
            System.out.println(stack.pop());
            System.out.println(stack.pop());
            System.out.println(stack.pop());
            System.out.println(stack.pop());
    
        }
    

    输出如下:

    natasha
    wendy
    jim
    tom
    

    从输出可以看到,最后入栈的,最先出栈

    下面我们底层用数组也来实现这样一个栈,在数组的尾部插入和删除。
    也就是入栈和出栈。如下图:

    完整的源码如下:

    public class QStack<E> {
        //数组的默认大小为10
        private static final int DEFAULT_INIT_CAPACITY = 10;
    
        //底层的数组
        private Object[] elements;
    
        //栈中的个数
        private int size;
    
        public QStack() {
            this(DEFAULT_INIT_CAPACITY);
        }
    
    
        public QStack(int capacity) {
            //capacity条件检查 ,这里我们直接抛出异常
            if (capacity <= 0) {
                throw new IllegalArgumentException("capacity <= 0");
            }
    
            if (capacity > Integer.MAX_VALUE) {
                throw new IllegalArgumentException("capacity > Integer.MAX_VALUE");
            }
    
            //新建一个capacity大小的数组
            elements = new Object[capacity];
    
            //初始个数为0
            size = 0;
        }
    
        //栈是否为空
        public boolean isEmpty() {
            return size == 0;
        }
    
        //返回栈中的元素个数
        public int size() {
            return size;
        }
    
        //将一个元素压入栈中
        public E push(E e) {
            //如果栈已满,进行扩容
            if (size >= elements.length) {
                grow();
            }
    
            //扩容完后将元素e压入栈中
            elements[size] = e;
    
            //别忘了size需要加 1
            size++;
    
            return e;
        }
    
        //出栈,就是将数组最后一个元素弹出
        public E pop() {
            //如果栈为空就返回null
            if (isEmpty()) {
                return null;
            }
    
            //拿到栈的大小
            int len = size();
    
            //把数组中最后一个元素保存起来
            E e = peek();
            //个数别忘了减1
            size--;
    
            //将最后一个元素置null
            elements[len - 1] = null;
    
            //返回e
            return e;
        }
    
        //返回最后一个元素
        public E peek() {
            int len = size();
    
            if (len == 0)
                throw new RuntimeException("stack is empty");
    
            return (E) elements[len - 1];
        }
    
        //扩容
        private void grow() {
            //将之前的数组保存
            int oldCapacity = elements.length;
            Object[] old = elements;
    
            //新的数组大小为原来数组大小的2倍
            int newCapacity = oldCapacity * 2;
            //再新建一个大小为原来数组2倍的新数组
            elements = new Object[newCapacity];
    
            //把以前的老的数组中的元素都移动新数组中
            for (int i = 0; i < oldCapacity; i++) {
                elements[i] = old[i];
            }
    
            //释放以前的内存空间
            old = null;
        }
    
    }
    
    
    

    以上面可知:用数组实现栈结构,主要需要注意以下 2 点:

    1. 在数组的尾部插入和删除,也就是压栈和弹栈
    2. 由于是用数组实现栈结构,数组满的时候,需要扩容

    下面我们写一段测试代码来测试,如下:

       public static void main(String[] args){
            //创建一个栈
            QStack<String> stack = new QStack<>();
            
            //分别向栈中压入4个不同的元素
            stack.push("tom");
            stack.push("jim");
            stack.push("wendy");
            stack.push("natasha");
    
            //分别弹栈
            System.out.println(stack.pop());
            System.out.println(stack.pop());
            System.out.println(stack.pop());
            System.out.println(stack.pop());
        }
    
    

    打印如下:

    natasha
    wendy
    jim
    tom
    

    欢迎访问作者的helloworld的个人博客:
    https://www.helloworld.net/jiulu

    同时也可以加作者的微信:daitukeji
    也可以扫下面的二维码添加
    image

  • 相关阅读:
    19年春第六周学习
    Java编程思想
    个人作业4-结对开发地铁
    Hadoop学习笔记—1.基本介绍与环境配置
    ZooKeeper学习第二期--ZooKeeper安装配置
    ZooKeeper学习第一期---Zookeeper简单介绍
    loadrunner--参数化—使用数据文件参数化
    loadrunner--analysis--图表筛选、合并、显示
    loadrunner--并发测试
    session和cookie
  • 原文地址:https://www.cnblogs.com/start1225/p/10099988.html
Copyright © 2011-2022 走看看