栈(Stack)原理及实现

目录

栈概述

顺序结构实现

链表结构实现


栈概述

栈是一种数据结构,它代表只能在某一端进行插入、删除操作的特殊线性表,通常就是在线性表的尾端进行插入、删除操作。允许进行插入、删除操作的一端被称为栈顶(top),另一端则被称为栈底(bottom)。

归纳起来:栈就是一种后进先出(LIFO)的线性表。

栈常用操作:

  • 初始化:通常是一个构造器,用于创建一个空栈。
  •  返回栈的长度:该方法用于返回栈中数据元素的个数。
  •  入栈:向栈的栈顶插入一个数据元素,栈的长度+1。
  •  出栈:从栈的栈顶删除一个数据元素,栈的长度-1,该方法通常返回被删除的元素。
  •  访问栈顶元素:返回栈顶的数据元素,但不删除栈顶元素。
  •  判断栈是否为空:该方法判断栈是否为空,如果栈为空返回true,否则返回false。
  •  清空栈:将栈清空。

顺序结构实现

顺序存储结构的栈简称为顺序栈,它利用一组地址连续的存储单元依次存放从栈底到栈顶的数据元素。

栈底位置固定不变,它的栈顶元素可以直接通过顺序栈底层数组的数组元素arr[size-1]来访问。

public class SequenceStack<T> {
    private int DEFAULT_SIZE = 10;
    //保存数组的长度
    private int capacity;
    //当数组容量不够时,每次增加的长度
    private int capacityIncrement = 0;
    //用数组做元素的容器
    private Object[] elementData;
    //栈元素的长度
    private int size = 0;
    public SequenceStack() {
        this.capacity = DEFAULT_SIZE;
        elementData = new Object[capacity];
    }
    public SequenceStack(T element) {
        this();
        elementData[0] = element;
        size++;
    }

    /**
     * 以指定长度的数组量创建栈
     * @param element 第一个栈元素
     * @param initSize 初始化长度
     */
    public SequenceStack(T element, int initSize) {
        this.capacity = initSize;
        elementData = new Object[capacity];
        elementData[0] = element;
        size++;
    }

    /**
     * 以指定长度的数组量创建栈
     * @param element 第一个栈元素
     * @param initSize 初始化长度
     * @param capacityIncrement 数组增长的单位长度
     */
    public SequenceStack(T element, int initSize, int capacityIncrement) {
        this(element, initSize);
        this.capacityIncrement = capacityIncrement;
    }
    //栈大小
    public int length() {
        return size;
    }
    //入栈
    public void push(T element) {
        ensureCapacity(size + 1);
        elementData[size + 1] = element;
    }
    //判断当前栈空间是不是够用,不够的话以2倍扩容
    private void ensureCapacity(int minCapacity) {
        if (minCapacity > capacity) {
            if (capacityIncrement > 0) {
                while (capacity < minCapacity) {
                    capacity += capacityIncrement;
                }
            } else {
                while (capacity < minCapacity) {
                    capacity <<= 1;
                }
            }
            elementData = Arrays.copyOf(elementData, capacity);
        }
    }
    //出栈
    public T pop() {
        T oldValue = (T) elementData[size - 1];
        elementData[--size] = null;
        return oldValue;
    }
    //返回栈顶元素,但不删除
    public T peek() {
        return (T) elementData[size - 1];
    }
    //判断是否为空
    public boolean empty() {
        return size == 0;
    }
    //清空
    public void clear() {
        Arrays.fill(elementData, null);
        size = 0;
    }
}

链表结构实现

也可采用单链表来保存栈中所有元素,这种链式结构的栈也被称为链栈。

对于链栈而言,栈顶元素不断地改变,程序只要使用一个top引用来记录当前的栈顶元素即可。

top引用变量永远引用栈顶元素,再使用一个size变量记录当前栈中包含多少元素即可。

public class LinkStack<T> {
    //定义内部类Node,代表链栈的节点
    private class Node {
        //节点数据
        private T data;
        //下个节点引用
        private Node next;

        public Node() {
        }

        public Node(T data, Node next) {
            this.data = data;
            this.next = next;
        }
    }
    //栈顶元素
    private Node top;
    //链栈包含的节点数
    private int size;

    public LinkStack() {
        top = null;
    }

    public LinkStack(T element) {
        top = new Node(element, null);
        size++;
    }

    public int length() {
        return size;
    }
    //入栈
    public void push(T element) {
        top = new Node(element, top);
        size++;
    }
    //出栈
    public T pop() {
        Node oldValue = top;
        top = top.next;
        oldValue.next = null;
        size--;
        return oldValue.data;
    }
    //返回栈顶元素
    public T peek() {
        return top.data;
    }
    //判断是否为空
    public boolean empty() {
        return size == 0;
    }
    //清空
    public void clear() {
        top = null;
        size = 0;
    }
}

 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值