数据结构——栈(Java代码实现)

栈基本概念

  1. 栈(stack)又名堆栈,它是一种运算受限的线性表。限定仅在表尾进行插入和删除操作的线性表。这一端被称为栈顶,相对地,把另一端称为栈底。栈的操作原则为"后进先出"(LIFO)

  2. 往栈中添加元素的操作,一般叫做 push,入栈
    在这里插入图片描述

  3. 从栈中移除元素的操作,一般叫做 pop,出栈(只能移除栈顶元素,也叫做:弹出栈顶元素)
    在这里插入图片描述

  4. 栈的内部实现可以用以前学过的动态数组和链表实现。其实有了前面的学习,栈的实现很简单。首先我们先设计一个Stack接口,里面写一些通用的操作,供其他类实现。

public interface Stack<E> {
    
    
    /**
     *
     * @return 返回栈中数据的个数
     */
    int getSize();

    /**
     *
     * @return 判断栈是否为空
     */
    boolean isEmpty();

    /**
     * 插入新元素到栈顶
     */
    void push(E e);

    /**
     *
     * @return 删除栈顶元素
     */
    E pop();

    /**
     *
     * @return 返回栈顶元素
     */
    E peek();
}

栈的顺序存储

栈的顺序存储结构使用前面学到的数组实现,此时的栈也被称为顺序栈。
其中动态数组的代码如下:

public class Array<E> {
    
    
    private E[] data;
    private int size;

    /**
     * 构造函数
     *
     * @param capacity 数组的容量
     */
    public Array(int capacity) {
    
    
        data = (E[]) new Object[capacity];
        size = 0;
    }

    /**
     * 无参构造器
     */
    public Array() {
    
    
        this(10);
    }

    /**
     * @return 获取数组的容量
     */
    public int getCapacity() {
    
    
        return data.length;
    }

    /**
     * @return 获取数组中元素的个数
     */
    public int getSize() {
    
    
        return size;
    }

    /**
     * @return 判断数组是否为空
     */
    public boolean isEmpty() {
    
    
        return size == 0;
    }

    /**
     * @param index 插入数组的位置
     * @param e     传入数组的值
     */
    public void add(int index, E e) {
    
    
        if (index < 0 && index > size) {
    
    
            throw new IllegalArgumentException("Add failed. Require index >= 0 and index <= size.");
        }

        if (size == data.length) {
    
    
            resize(2 * data.length);
        }

        for (int i = size - 1; i >= index; i--) {
    
    
            data[i + 1] = data[i];
        }
        data[index] = e;
        size++;
    }

    /**
     * @param e 在所有元素后添加元素
     */
    public void addLast(E e) {
    
    
        add(size, e);
    }

    /**
     * @param e 在所有元素前插入元素
     */
    public void addFirst(E e) {
    
    
        add(0, e);
    }

    /**
     * @return 返回index处的元素
     */
    public E get(int index) {
    
    
        if (index < 0 || index >= size) {
    
    
            throw new IllegalArgumentException("Get failed. Index is illegal.");
        }
        return data[index];
    }

    /**
     *
     * @return 返回数组第一个元素
     */
    public E getFirst(){
    
    
        return get(0);
    }

    /**
     *
     * @return 返回数组最后一个元素
     */
    public E getLast(){
    
    
        return get(size-1);
    }

    /**
     * 修改index处的元素为e
     */
    public void set(int index, E e) {
    
    
        if (index < 0 || index >= size) {
    
    
            throw new IllegalArgumentException("Set failed. Index is illegal.");
        }

        data[index] = e;
    }

    /**
     * 判断数组中是否包含某元素
     */
    public boolean contains(E e) {
    
    
        for (int i = 0; i < size; i++) {
    
    
            if (data[i].equals(e)) {
    
    
                return true;
            }
        }
        return false;
    }

    /**
     * 查找元素的索引,如果不存在,则返回-1
     */
    public int find(E e) {
    
    
        for (int i = 0; i < size; i++) {
    
    
            if (data[i].equals(e)) {
    
    
                return i;
            }
        }
        return -1;
    }

    /**
     * 从数组中删除index位置的元素,返回删除的元素
     */
    public E remove(int index) {
    
    
        if (index < 0 || index >= size) {
    
    
            throw new IllegalArgumentException("Remove failed. Index is illegal.");
        }

        E delNum = data[index];
        for (int i = index + 1; i < size; i++) {
    
    
            data[i - 1] = data[i];
        }
        size--;
        data[size] = null;

        if (size == data.length / 4 && data.length != 0) {
    
    //复杂度震荡
            resize(data.length / 2);
        }
        return delNum;
    }

    /**
     * 刪除第一个元素
     */
    public E removeFirst() {
    
    
        return remove(0);
    }

    /**
     * 刪除最后一个元素
     */
    public E removeLast() {
    
    
        return remove(size - 1);
    }

    /**
     * 从数组中删除元素e
     */
    public void removeElement(E e) {
    
    
        int index = find(e);
        if (index != -1) {
    
    
            remove(index);
        }
    }

    @Override
    public String toString() {
    
    
        StringBuilder res = new StringBuilder();
        res.append(String.format("Array: size = %d , capacity = %d\n", size, data.length));
        res.append("[");
        for (int i = 0; i < size; i++) {
    
    
            res.append(data[i]);
            if (i != size - 1) {
    
    
                res.append(",");
            }
        }
        res.append("]");
        return res.toString();
    }

    /**
     * @param newCapacity 将数组空间的容量变成newCapacity大小
     */
    private void resize(int newCapacity) {
    
    
        E[] newDate = (E[]) new Object[newCapacity];
        for (int i = 0; i < size; i++) {
    
    
            newDate[i] = data[i];
        }

        data = newDate;
    }
}

顺序栈的具体代码如下:

public class ArrayStack<E> implements Stack<E> {
    
    
    private Array<E> array;

    public ArrayStack(int capacity) {
    
    
        array = new Array<>(capacity);
    }

    public ArrayStack() {
    
    
        array = new Array<>();
    }

    @Override
    public int getSize() {
    
    
        return array.getSize();
    }

    @Override
    public boolean isEmpty() {
    
    
        return array.isEmpty();
    }

    @Override
    public void push(E e) {
    
    
        array.addLast(e);
    }

    @Override
    public E pop() {
    
    
        return array.removeLast();
    }

    @Override
    public E peek() {
    
    
        return array.getLast();
    }

    @Override
    public String toString() {
    
    
        StringBuilder res = new StringBuilder();
        res.append("Stack: ").append('[');
        for (int i = 0; i < array.getSize(); i++) {
    
    
            res.append(array.get(i));
            if (i != array.getSize() - 1) {
    
    
                res.append(", ");
            }
        }
        res.append("] top");
        return res.toString();
    }
}

栈的链式存储

栈的链式存储结构也就是用链表存储栈中数据元素,此时的栈称为链栈。
链表的具体实现代码如下:

public class LinkedList<E> {
    
    
    private class Node {
    
    
        public E e;
        public Node next;

        public Node(E e, Node next) {
    
    
            this.e = e;
            this.next = next;
        }

        public Node(E e) {
    
    
            this.e = e;
        }

        public Node() {
    
    
        }

        @Override
        public String toString() {
    
    
            return e.toString();
        }
    }

    //设立一个虚拟头结点,放在第一元素的结点之前
    private Node dummyHead;
    private int size;

    public LinkedList() {
    
    
        dummyHead = new Node();
        size = 0;
    }

    //获取链表中的元素
    public int getSize() {
    
    
        return size;
    }

    //返回链表是否为空
    public boolean isEmpty() {
    
    
        return size == 0;
    }

    //在鏈表的index(0-based)位置添加新的元素e
    public void add(int index, E e) {
    
    

        if (index < 0 || index > size) {
    
    
            throw new IllegalArgumentException("Add failed. Illegal index");
        }

        Node prev = dummyHead;
        for (int i = 0; i < index; i++) {
    
    
            prev = prev.next;
        }

        Node node = new Node(e);
        node.next = prev.next;
        prev.next = node;

        size++;
    }

    //在链表表头添加新的元素
    public void addFirst(E e) {
    
    
        add(0, e);
    }

    //在链表末尾添加新的元素e
    public void addLast(E e) {
    
    
        add(size, e);
    }

    //获取链表的第index位置的元素
    public E get(int index) {
    
    
        if (index < 0 || index >= size)
            throw new IllegalArgumentException("Get failed. Illegal index.");

        Node cur = dummyHead.next;
        for (int i = 0; i < index; i++) {
    
    
            cur = cur.next;
        }

        return cur.e;
    }

    //获取链表的第一个元素
    public E getFirst() {
    
    
        return get(0);
    }

    //获取链表的最后一个元素
    public E getLast() {
    
    
        return get(size - 1);
    }

    //修改链表中的第index个位置的元素
    public void set(int index, E e) {
    
    
        if (index < 0 || index >= size)
            throw new IllegalArgumentException("Set failed. Illegal index.");

        Node cur = dummyHead.next;
        for (int i = 0; i < index; i++) {
    
    
            cur = cur.next;
        }
        cur.e = e;
    }

    //查看链表中是否含有某元素
    public boolean contains(E e) {
    
    
        Node cur = dummyHead.next;
        while (cur != null) {
    
    
            if (cur.e.equals(e)) {
    
    
                return true;
            }
            cur = cur.next;
        }
        return false;
    }

    //从链表中删除某元素,返回删除的元素
    public E remove(int index) {
    
    
        if (index < 0 || index >= size)
            throw new IllegalArgumentException("Remove failed. Index is illegal.");

        Node prev = this.dummyHead;
        for (int i = 0; i < index; i++) {
    
    
            prev = prev.next;
        }

        Node delNode = prev.next;
        prev.next = delNode.next;
        delNode.next = null;
        size--;

        return delNode.e;
    }

    // 从链表中删除第一个元素, 返回删除的元素
    public E removeFirst() {
    
    
        return remove(0);
    }

    // 从链表中删除最后一个元素, 返回删除的元素
    public E removeLast() {
    
    
        return remove(size - 1);
    }

    //从链表中删除某元素
    public void removeElement(E e) {
    
    
        Node prev = this.dummyHead;
        while (prev.next != null) {
    
    
            if (prev.next.e.equals(e)) {
    
    
                break;
            }
            prev = prev.next;
        }

        if (prev.next != null) {
    
    
            Node delNode = prev.next;
            prev.next = delNode.next;
            delNode.next = null;
            size--;
        }
    }

    @Override
    public String toString() {
    
    
        StringBuilder res = new StringBuilder();

        Node cur = dummyHead.next;
        while (cur != null) {
    
    
            res.append(cur.e).append("->");
            cur = cur.next;
        }

        res.append("NULL");

        return res.toString();
    }

}

链栈的具体代码如下:

public class LinkedListStack<E> implements Stack<E> {
    
    
    private LinkedList<E> list;

    public LinkedListStack() {
    
    
        list = new LinkedList<>();
    }

    @Override
    public int getSize() {
    
    
        return list.getSize();
    }

    @Override
    public boolean isEmpty() {
    
    
        return list.isEmpty();
    }

    //链表头是栈顶,链表头是o(1)级别的
    @Override
    public void push(E e) {
    
    
        list.addFirst(e);
    }

    @Override
    public E pop() {
    
    
        return list.removeFirst();
    }

    @Override
    public E peek() {
    
    
        return list.getFirst();
    }

    @Override
    public String toString() {
    
    
        StringBuilder res = new StringBuilder();
        res.append("Stack: top");
        res.append(list.toString());
        return res.toString();
    }
}

猜你喜欢

转载自blog.csdn.net/weixin_46215617/article/details/109608264