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

栈的底层实现有两种,基于数组的实现:顺序栈(ArrayList);基于链表的实现:链式栈(LinkedList)。
- // 基于数组实现链表
- public class Stack<E> {
- 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();
- }
- }
队列是一种仅支持在表尾进行插入操作、在表头进行删除操作的线性表,插入端称为队尾,删除端称为队首,因整体类似排队的队伍而得名。它满足先进先出的性质(FIFO),元素入队即将新元素加在队列的尾,元素出队即将队首元素取出,它后一个作为新的队首。·
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();
- }
- }
在顺序队列中,当下标走到队尾后,不能再往后走插入元素,但其实数组中还有位置,这叫做“假溢出”,为了解决这个问题提高数组利用率,就出现了循环队列。

实现循环对列,最重要的是如何判断队列为空还是为满。
1. 通过 size 属性记录当前队列中的元素个数;
2. 保留一个位置,这个位置不能存储元素。这样当队满为 front == (rear+ 1)% length,队空为 front == rear。
front:指向循环队列的第一个元素下标,rear:指向循环队列的最后一个元素的下一个下标
- /**
- * 循环队列
- */
- 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天学习挑战赛