• Java 中的栈和队列


    目录

    ​1. 栈

    ​1.1 概念

    1.2 栈的种类

    1.3 栈的实现

    2. 队列

    2.1 概念

    ​2.2 队列实现

    3. 循环队列 

    3.1 为什么会有循环队列

    3.2 如何区分空与满

    3.3 循环队列实现


    ​1. 栈


    ​1.1 概念

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

     

    1.2 栈的种类

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

    1.3 栈的实现

    1. // 基于数组实现链表
    2. public class Stack<E> {
    3. private E[] elementData; // 栈中的元素
    4. private int size; // 当前栈中元素个数
    5. public Stack() {
    6. elementData = (E[]) new Object[10]; // 默认长度为10
    7. }
    8. public Stack(int initCap) {
    9. elementData = (E[]) new Object[initCap]; // 初始长度
    10. }
    11. // 入栈
    12. public void push(E value) {
    13. // 扩容
    14. if(size == elementData.length) {
    15. int oldLength = elementData.length;
    16. int newLength = oldLength << 1;
    17. elementData = Arrays.copyOf(elementData, newLength);
    18. }
    19. // 在数组尾部添加元素
    20. elementData[size++] = value;
    21. }
    22. // 出栈,返回原来的栈顶元素
    23. public E pop () {
    24. if(getSize() == 0) {
    25. throw new NoSuchElementException("栈中没有元素!");
    26. }
    27. // 得到原来的栈顶元素位置
    28. E oldVaule = elementData[size - 1];
    29. size--;
    30. elementData[size] = null;
    31. return oldVaule;
    32. }
    33. // 查看栈顶元素
    34. public E peek() {
    35. if(getSize() == 0) {
    36. throw new NoSuchElementException("栈中没有元素!");
    37. }
    38. return elementData[size - 1];
    39. }
    40. // 获取当前栈的长度
    41. public int getSize() {
    42. return size;
    43. }
    44. @Override
    45. public String toString() {
    46. StringBuilder stringBuilder = new StringBuilder();
    47. stringBuilder.append("[");
    48. for (int i = 0; i < size; i++) {
    49. stringBuilder.append(elementData[i]);
    50. if(i != size - 1) {
    51. stringBuilder.append(",");
    52. }
    53. }
    54. stringBuilder.append("]");
    55. return stringBuilder.toString();
    56. }
    57. }

    2. 队列

    2.1 概念

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

    2.2 队列实现

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

    1. /**
    2. * 基于链表的队列
    3. */
    4. public class LinkedQueue{
    5. private Node head;
    6. private Node tail;
    7. private int size;
    8. private class Node {
    9. private int data;
    10. private Node next;
    11. public Node(int data) {
    12. this.data = data;
    13. }
    14. }
    15. // 入队
    16. public void offer(int value) {
    17. Node node = new Node(value);
    18. if(head == null) {
    19. head = tail = node;
    20. } else {
    21. tail.next = node;
    22. tail = node;
    23. }
    24. size++;
    25. }
    26. // 出队(队首元素出队)
    27. public int poll() {
    28. if(size == 0) {
    29. throw new NoSuchElementException("对列为空!");
    30. } else {
    31. int oldValue = head.data;
    32. Node tempHead = head;
    33. head = head.next;
    34. tempHead.next = null;
    35. size--;
    36. return oldValue;
    37. }
    38. }
    39. // 查看队首元素
    40. public int peek() {
    41. if(size == 0) {
    42. throw new NoSuchElementException("对列为空!");
    43. }
    44. return head.data;
    45. }
    46. public String toString() {
    47. StringBuilder stringBuilder = new StringBuilder();
    48. stringBuilder.append("front[");
    49. Node node = head;
    50. while (node != null) {
    51. stringBuilder.append(node.data);
    52. if(node.next != null) {
    53. stringBuilder.append(",");
    54. }
    55. node = node.next;
    56. }
    57. stringBuilder.append("]tail");
    58. return stringBuilder.toString();
    59. }
    60. }

    3. 循环队列 

    3.1 为什么会有循环队列

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

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

    3.2 如何区分空与满

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

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

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

     

    3.3 循环队列实现

    1. /**
    2. * 循环队列
    3. */
    4. public class LoopQueue implements IQueue {
    5. // 指向循环队列的最后一个元素的下一个位置
    6. private int tail;
    7. // 队首元素,指向队列中的第一个元素索引
    8. private int front;
    9. // 有效元素个数
    10. private int size;
    11. private int[] data;
    12. public LoopQueue(int k) {
    13. data = new int[k + 1];
    14. }
    15. // 判断队列是否已满
    16. public boolean isFull() {
    17. if ((tail + 1) % data.length == front) {
    18. return true;
    19. }
    20. return false;
    21. }
    22. // 判断队列是否为空
    23. public boolean isEmpty() {
    24. // if (front == tail) {
    25. // return true;
    26. // }
    27. // return false;
    28. return tail == front;
    29. }
    30. // 入队
    31. public void offer(int value) {
    32. if (isFull()) {
    33. System.err.println("队列已满!");
    34. return;
    35. } else {
    36. data[tail] = value;
    37. tail = (tail + 1) % data.length;
    38. size++;
    39. }
    40. }
    41. // 出队
    42. public int poll() {
    43. if (isEmpty()) {
    44. System.err.println("队列为空!");
    45. return -1;
    46. } else {
    47. int value = data[front];
    48. front = (front + 1) % data.length;
    49. size--;
    50. return value;
    51. }
    52. }
    53. // 查看队首元素
    54. public int peek() {
    55. if (isEmpty()) {
    56. System.err.println("队列为空!");
    57. return -1;
    58. }
    59. return data[front];
    60. }
    61. // 查看队尾元素
    62. public int getTail() {
    63. if (isEmpty()) {
    64. System.err.println("队列为空!");
    65. return -1;
    66. }
    67. // 最后一个元素的下标
    68. int index = tail == 0 ? data.length - 1 : tail - 1;
    69. return data[index];
    70. }
    71. // 判断有效个数
    72. public int getSize() {
    73. return size;
    74. }
    75. public String toString() {
    76. StringBuilder stringBuilder = new StringBuilder();
    77. stringBuilder.append("[");
    78. // 最后一个元素的位置
    79. int lastIndex = tail == 0 ? data.length - 1 : tail - 1;
    80. for (int i = front; i != tail; ) {
    81. stringBuilder.append(data[i]);
    82. if (i != lastIndex) {
    83. stringBuilder.append(",");
    84. }
    85. i = (i + 1) % data.length;
    86. }
    87. stringBuilder.append("]");
    88. return stringBuilder.toString();
    89. }
    90. }

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

  • 相关阅读:
    项目实战第二十五讲:复杂业务流程编排规则引擎
    【Elasticsearch教程17】Mapping字段类型之token_count
    AUSBC3.0, 震撼来袭!(UVC Camera)
    SpringCloud03 --- 搭建Nacos集群、Feign远程调用、Gateway服务网关
    《性能之巅第2版》阅读笔记(二)--性能观察工具
    JavaScript实现网页截屏的5种方法(详解+代码)
    好记性不如烂笔头(ubuntu的samba的配置)
    Tomcat:部署及优化
    网络安全(黑客)自学
    真正解决jellyfin硬解码转码
  • 原文地址:https://blog.csdn.net/AlinaQ05/article/details/126196718