栈的简单学习

什么是栈:

栈是一种有序数据项构成的数据结构,数据项的插入和删除只能在一端(栈顶)进行。LIFO(last in first out)。

这里分别用数组和链表简单实现栈的功能。

1.用数组实现栈,元素array[0]就表示了栈底元素,array.length表示了栈的长度,array[array.length-1]表示了栈顶元素。每次有元素入栈的时候,array.length++

public ArrayStack<E> implements Cloneable{
    private E[] data;       //栈中的数据项
    private int items;      //栈中数据项的个数

    //初始化一个大小为INITIAL_LENGTH的栈
    public ArrayStack(){
        final int INITIAL_LENGTH = 10;  
        items = 0;
        data = (E[]) new Object[INITIAL_LENGTH];
    }

    //手动输入栈的大小
    public ArrayStack(int initialLength){
        if(initialLength < 0)
            throw new IllegalArgumentException("输入的栈的大小有误!")
        items = 0;
        data = (E[]) new Object[initialLength];
    }

    //获取当前栈的大小
    public int getLength(){
        return data.length;
    }

    //获取当前栈内元素的个数
    public int itemsSize(){
        return items;
    }

    //判断当前栈是否为空
    public boolean isEmpty(){
        return (items == 0);
    }

    //修改当前栈的长度
    public void changeLength(int newLength){
        E[] newStack;
        if(data.length < newLength){
            newStack = (E[]) new Object[newLength];
            System.arraycopy(data, 0, newStack, 0, items);
            data = newStack;
        }
    }

    //实现clone方法生成栈的一个副本
    public ArrayStack<E> clone(){
        ArrayStack<E> stackCopy;

        try{
            stackCopy = (ArrayStack<E>)super.clone();
        }
        catch(CloneNotSupportedException e){
            throw new RuntimeException("复制失败!这个数据类型没有实现clone方法!")
        }
        stackCopy.data = data.clone();

        return stackCopy;
    }
}

下面就是栈最重要的入栈、出栈以及获取栈顶数据项的操作。

    //获取当前栈顶项数据
    public E peek(){
        if(items == 0)
            throw new EmptyStackException();

        return data[items-1];
    }

将栈顶数据项出栈,就是获取当前栈顶数据项,并将栈的长度减小,当栈为空时返回一个空值。

    public E pop(){
        E topItem;
        if(items == 0)
            throw new EmptyStackException();
        topItem = data[--items];
        data[items] = null;

        return topItem;
    }  

将数据项入栈,要注意栈必须有足够的位置才能够push。

    public void push(E newItem){
        if(items == data.length)
            changeLength(2*items + 1);  //栈内如果没有空间了,增大栈的空间
        data[items] = newItem;
        items++;
    }  

这里如果2*items+1 > Integer.MAX_VALUE会产生算数溢出,造成入栈失败。
上面将栈的长度变长了,所以应该定义一个方法恢复到正确的长度,让它调用。

    public void trimToSize(){
        E[] trimArray;
        if(data.length != items){
            trimArray = (E[]) new Object[items];
            System.arraycopy(data, 0, trimArray, 0, items);
            data = trimArray;
        }
    }

用链表实现栈的本质跟数组实现还是差不多的,用一个个链表的结点来表示栈中的数据项。栈顶存储在链表的头部引用的位置,栈底存储在链表的尾部引用的位置,然后让变量head引用链表的头部位置。

public class LinkedStack<E> implements Cloneable{
    private Node<E> head;

    //初始化链表实现的栈
    public LinkedStack(){
        head == null;
    }

    public boolean isEmpty(){
        return (head == null);
    }

    //实现复制栈的方法
    public LinkedStack<E> clone(){
        LinkedStack<E> linkCopy;

        try{
            linkCopy = (LinkedStack)super.clone();
        }
        catch(CloneNotSupportedException e){
            throw new RuntimeException("复制失败!这个数据类型没有实现clone方法!");
        }

        linkCopy.head = Node.listCopy(head);

        return linkCopy;
    }

    //获取当前栈的长度
    public int size(){
        return Node.listLength(head);
    }
}

用链表实现的栈的入栈、出栈和获取栈顶数据的方法跟用数组实现是类似的。

    //获取栈顶数据项
    public E peek(){
        if(head == null)
            throw new EmptyStackException();
        return head.getData();
    }

    //将栈顶数据项出栈
    public E pop(){
        E top;
        if(head == null)
            throw new EmptyStackException();
        top = top.getLink();

        return top;
    }

    //将数据项入栈
    public E push(E newItem){
        head = new Node<E>(newItem, head);
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值