java-栈的实现

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_34975710/article/details/77187174

  栈作为常用的数据存储结构之一,存储的特点是“先进后出”,通常都是直接拿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,这样就带来一个问题,我入栈的时候不管是什么类型的数据都可入栈,这样我们的栈就变成了“杂货铺”不便于使用,现在就需要通过使用泛型来约束栈保存数据的类型。代码主体不需要更改,只需要做一些更改。

扫描二维码关注公众号,回复: 3496436 查看本文章
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"); // 此行代码将会报错,数据类型不匹配
    }

}

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


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

猜你喜欢

转载自blog.csdn.net/qq_34975710/article/details/77187174