Java 中的栈和队列

目录

​1. 栈

​1.1 概念

1.2 栈的种类

1.3 栈的实现

2. 队列

2.1 概念

​2.2 队列实现

3. 循环队列 

3.1 为什么会有循环队列

3.2 如何区分空与满

3.3 循环队列实现


​1. 栈


​1.1 概念

栈是一种仅支持在表尾进行插入和删除操作的线性表,这一端被称为栈顶,另一端被称为栈底。元素入栈指的是把新元素放到栈顶元素的上面,使之成为新的栈顶元素;元素出栈指的是从一个栈删除元素又称作出栈或退栈,它是把栈顶元素删除掉,使其相邻的元素成为新的栈顶元素。栈中的元素遵守后进先出(LIFO)的原则.

 Java 中的栈和队列_第1张图片

1.2 栈的种类

栈的底层实现有两种,基于数组的实现:顺序栈(ArrayList);基于链表的实现:链式栈(LinkedList)。 

1.3 栈的实现

// 基于数组实现链表
public class Stack {
    private E[] elementData; // 栈中的元素
    private int size; // 当前栈中元素个数

    public Stack() {
        elementData = (E[]) new Object[10]; // 默认长度为10
    }

    public Stack(int initCap) {
        elementData = (E[]) new Object[initCap]; // 初始长度
    }

    // 入栈
    public void push(E value) {
        // 扩容
        if(size == elementData.length) {
            int oldLength = elementData.length;
            int newLength = oldLength << 1;
            elementData = Arrays.copyOf(elementData, newLength);
        }
        // 在数组尾部添加元素
        elementData[size++] = value;
    }

    // 出栈,返回原来的栈顶元素
    public E pop () {
        if(getSize() == 0) {
            throw new NoSuchElementException("栈中没有元素!");
        }
        // 得到原来的栈顶元素位置
        E oldVaule = elementData[size - 1];
        size--;
        elementData[size] = null;
        return oldVaule;
    }

    // 查看栈顶元素
    public E peek() {
        if(getSize() == 0) {
            throw new NoSuchElementException("栈中没有元素!");
        }
        return elementData[size - 1];
    }

    // 获取当前栈的长度
    public int getSize() {
        return size;
    }

    @Override
    public String toString() {
        StringBuilder stringBuilder = new StringBuilder();
        stringBuilder.append("[");
        for (int i = 0; i < size; i++) {
            stringBuilder.append(elementData[i]);
            if(i != size - 1) {
                stringBuilder.append(",");
            }
        }
        stringBuilder.append("]");
        return stringBuilder.toString();
    }
}

2. 队列

2.1 概念

队列是一种仅支持在表尾进行插入操作、在表头进行删除操作的线性表,插入端称为队尾,删除端称为队首,因整体类似排队的队伍而得名。它满足先进先出的性质(FIFO),元素入队即将新元素加在队列的尾,元素出队即将队首元素取出,它后一个作为新的队首。·

Java 中的栈和队列_第2张图片

2.2 队列实现

队列和栈相同也是可以使用数组和链表实现,但是对于队列来说使用链表的结构效率更高。

/**
 * 基于链表的队列
 */
public class LinkedQueue{
    private Node head;
    private Node tail;
    private int size;
    private class Node {
        private int data;
        private Node next;

        public Node(int data) {
            this.data = data;
        }
    }

    // 入队
    public void offer(int value) {
        Node node = new Node(value);
        if(head == null) {
            head = tail = node;
        } else {
            tail.next = node;
            tail = node;
        }
        size++;
    }

    // 出队(队首元素出队)
    public int poll() {
        if(size == 0) {
            throw new NoSuchElementException("对列为空!");
        } else {
            int oldValue = head.data;
            Node tempHead = head;
            head = head.next;
            tempHead.next = null;
            size--;
            return oldValue;
        }
    }

    // 查看队首元素
    public int peek() {
        if(size == 0) {
            throw new NoSuchElementException("对列为空!");
        }
        return head.data;
    }

    public String toString() {
        StringBuilder stringBuilder = new StringBuilder();
        stringBuilder.append("front[");
        Node node = head;
        while (node != null) {
            stringBuilder.append(node.data);
            if(node.next != null) {
                stringBuilder.append(",");
            }
            node = node.next;
        }
        stringBuilder.append("]tail");
        return stringBuilder.toString();
    }
}

3. 循环队列 

3.1 为什么会有循环队列

在顺序队列中,当下标走到队尾后,不能再往后走插入元素,但其实数组中还有位置,这叫做“假溢出”,为了解决这个问题提高数组利用率,就出现了循环队列。

Java 中的栈和队列_第3张图片

实现循环对列,最重要的是如何判断队列为空还是为满。

3.2 如何区分空与满

1. 通过 size 属性记录当前队列中的元素个数;

2. 保留一个位置,这个位置不能存储元素。这样当队满为 front == (rear+ 1)% length,队空为 front == rear

front:指向循环队列的第一个元素下标,rear:指向循环队列的最后一个元素的下一个下标

Java 中的栈和队列_第4张图片

3.3 循环队列实现

/**
 * 循环队列
 */
public class LoopQueue implements IQueue {
    // 指向循环队列的最后一个元素的下一个位置
    private int tail;
    // 队首元素,指向队列中的第一个元素索引
    private int front;
    // 有效元素个数
    private int size;
    private int[] data;

    public LoopQueue(int k) {
        data = new int[k + 1];
    }

    // 判断队列是否已满
    public boolean isFull() {
        if ((tail + 1) % data.length == front) {
            return true;
        }
        return false;
    }

    // 判断队列是否为空
    public boolean isEmpty() {
//        if (front == tail) {
//            return true;
//        }
//        return false;
        return tail == front;
    }

    // 入队
    public void offer(int value) {
        if (isFull()) {
            System.err.println("队列已满!");
            return;
        } else {
            data[tail] = value;
            tail = (tail + 1) % data.length;
            size++;
        }
    }

    // 出队
    public int poll() {
        if (isEmpty()) {
            System.err.println("队列为空!");
            return -1;
        } else {
            int value = data[front];
            front = (front + 1) % data.length;
            size--;
            return value;
        }
    }

    // 查看队首元素
    public int peek() {
        if (isEmpty()) {
            System.err.println("队列为空!");
            return -1;
        }
        return data[front];
    }

    // 查看队尾元素
    public int getTail() {
        if (isEmpty()) {
            System.err.println("队列为空!");
            return -1;
        }
        // 最后一个元素的下标
        int index = tail == 0 ? data.length - 1 : tail - 1;
        return data[index];
    }

    // 判断有效个数
    public int getSize() {
        return size;
    }

    public String toString() {
        StringBuilder stringBuilder = new StringBuilder();
        stringBuilder.append("[");
        // 最后一个元素的位置
        int lastIndex = tail == 0 ? data.length - 1 : tail - 1;
        for (int i = front; i != tail; ) {
            stringBuilder.append(data[i]);
            if (i != lastIndex) {
                stringBuilder.append(",");
            }
            i = (i + 1) % data.length;
        }
        stringBuilder.append("]");
        return stringBuilder.toString();
    }
}

活动地址:CSDN21天学习挑战赛

你可能感兴趣的:(JavaSE,java,数据结构)