java-栈的实现

来源:互联网 发布:云豹直播源码破解版 编辑:程序博客网 时间:2024/05/21 17:23

  栈作为常用的数据存储结构之一,存储的特点是“先进后出”,通常都是直接拿Java提供的Stack使用,那我们也可以自己动手去实现下栈,栈的存储结构分为顺序存储和链式存储,本篇先实现顺序存储。

一、基本实现

  栈的顺序存储主要靠数组来存储数据,栈中还有一个比较重要的就是“栈顶指针”,不管入栈、出栈还是查看栈顶元素都要用到“栈顶指针”,所以这里可以把“栈顶指针”定义成一个int变量,等于数组最后一个元素的下标。
  下面是具体的代码:

public class OrderStack {    // 保存数据的数组    private Object[] data;    // 栈顶指针    private int top = -1;    // 栈中元素个数    private int size;    /**     * 无参构造,默认创建大小为10的数组     */    public OrderStack() {        this(10);    }    /**     * 带参构造,指定创建数组的大小     *      * @param initialSize  数组的大小     *                 */    public OrderStack(int initialSize) {        data = new Object[initialSize];    }    /**     * 入栈     * @param obj 入栈的数据     *                 */    public void push(Object obj) {        if (top >= data.length - 1) {            // 元素个数超出数组大小            System.out.println("栈满");        } else {            data[++top] = obj;            size++;        }    }    /**     * 出栈     * @return 返回栈顶的元素栈顶元素     */    public Object pop() {        if (isEmpty()) {            // 栈为空时抛出异常            throw new RuntimeException("栈为空");        } else {            Object obj = data[top--];            size--;            data[size] = null; // help GC            return obj;        }    }    /**     * 查看栈顶元素,但并不出栈     * @return 返回栈顶的元素     */    public Object peek() {        if (isEmpty()) {            // 栈为空时抛出异常            throw new RuntimeException("栈为空");        } else {            return data[top];        }    }    /**     * 判断栈是否为空     * @return 为空返回true,否则false     */    public boolean isEmpty() {        return top == -1 ? true : false;    }    /**     * 返回栈中元素的个数     * @return 栈中元素的个数     */    public int size() {        return this.size;    }}

  测试如下:

public class Test {    public static void main(String[] args) {        // TODO Auto-generated method stub        OrderStack orderStack = new OrderStack();        orderStack.push(10);        orderStack.push(20);        orderStack.push(30);        orderStack.push(40);        orderStack.push(50);        orderStack.push(60);        orderStack.push(70);        orderStack.push(80);        orderStack.push(90);        orderStack.push(100);        System.out.println("栈中元素个数:" + orderStack.size());        System.out.println("栈顶元素:" +orderStack.peek());        System.out.println("=============楚河汉界=============");        System.out.println("出栈:" +orderStack.pop());        System.out.println("栈中元素个数:" + orderStack.size());        System.out.println("=============楚河汉界=============");    }}

  运行结果如下,出栈、查看栈顶元素、入栈都可以实现了:

这里写图片描述

二、push()方法的改进

  但是如果我紧接着在入栈5个数据就会报“栈满”的提示,因为正在入栈方法中做了相应的处理,避免入栈的数据超出数组的大小。

    public static void main(String[] args) {        //  ...上面代码省略...        System.out.println("出栈:" +orderStack.pop());        System.out.println("栈中元素个数:" + orderStack.size());        System.out.println("=============楚河汉界=============");        //  再入栈5个        orderStack.push(200);        orderStack.push(210);        orderStack.push(220);        orderStack.push(230);        orderStack.push(240);    }

这里写图片描述

  这个问题需要解决掉,毕竟这样的栈限制太大,可以在push方法中利用Arrays类中的copyOf()方法在数组满时动态的创建长度更长的数组,并将原数组的数据拷贝进去。
  新的push()方法:

    /**     * 入栈     * @param obj 入栈的数据     */    public void push(Object obj) {        if (top >= data.length - 1) {            // 当数组满了,就创建一个新数组,长度为当前数组的2倍,并将当前数组的数据拷贝进去            data = Arrays.copyOf(data, data.length * 2);        }        data[++top] = obj;        size++;    }

  这样不管插入多少个数据都没有问题了:

public class Test {    public static void main(String[] args) {        // TODO Auto-generated method stub        OrderStack orderStack = new OrderStack();        orderStack.push(10);        orderStack.push(20);        orderStack.push(30);        orderStack.push(40);        orderStack.push(50);        orderStack.push(60);        orderStack.push(70);        orderStack.push(80);        orderStack.push(90);        orderStack.push(100);           orderStack.push(200);        orderStack.push(210);        orderStack.push(220);        orderStack.push(230);        orderStack.push(240);        System.out.println("栈中元素个数:" + orderStack.size());        System.out.println("=============楚河汉界=============");    }}

这里写图片描述

三、进一步完善

  上面在定义时数组类型为Object,在push方法中定义的参数也为Object,这样就带来一个问题,我入栈的时候不管是什么类型的数据都可入栈,这样我们的栈就变成了“杂货铺”不便于使用,现在就需要通过使用泛型来约束栈保存数据的类型。代码主体不需要更改,只需要做一些更改。

public class **OrderStack<T>** {    // 保存数据的数组    private Object[] data;    // 栈顶指针    private int top = -1;    // 栈中元素个数    private int size;    /**     * 无参构造,默认创建大小为10的数组     */    public OrderStack() {        this(10);    }    /**     * 带参构造,指定创建数组的大小     *      * @param initialSize     *            数组的大小     *      */    public OrderStack(int initialSize) {        data = new Object[initialSize];    }    /**     * 入栈     * @param obj 入栈的数据     */    public void push(**T obj**) {        if (top >= data.length - 1) {            // 当数组满了,就创建一个新数组,长度为当前数组的2倍,并将当前数组的数据拷贝进去            data = Arrays.copyOf(data, data.length * 2);        }        data[++top] = obj;        size++;    }    /**     * 出栈     *      * @return 返回栈顶的元素栈顶元素     */    **public T pop()** {        if (isEmpty()) {            // 栈为空时抛出异常            throw new RuntimeException("栈为空");        } else {            Object obj = data[top--];            size--;            data[size] = null; // help GC            **return (T) obj;**        }    }    /**     * 查看栈顶元素,但并不出栈     *      * @return 返回栈顶的元素     */    **public T peek()** {        if (isEmpty()) {            // 栈为空时抛出异常            throw new RuntimeException("栈为空");        } else {            **return (T) data[top];**        }    }    /**     * 判断栈是否为空     *      * @return 为空返回true,否则false     */    public boolean isEmpty() {        return top == -1 ? true : false;    }    /**     * 返回栈中元素的个数     *      * @return 栈中元素的个数     */    public int size() {        return this.size;    }}

  测试如下:

public class Test {    public static void main(String[] args) {        // 指定栈只能存储int数据        OrderStack<Integer> orderStack = new OrderStack<Integer>();        orderStack.push(10);        orderStack.push(20);        orderStack.push("abc"); // 此行代码将会报错,数据类型不匹配    }}

  好了,到此最基本顺序栈已经差不多完成了,有什么问题欢迎指正。


生活不只是敲代码,如果你或你身边的人喜欢摄影或者生活的点点滴滴,可以关注下我亲爱的公众号~
这里写图片描述

原创粉丝点击