• JavaSE---栈和队列


    1、(Stack)

    1.1 概念

            栈:一种特殊的线性表,其 只允许在固定的一端进行插入和删除元素操作 。进行数据插入和删除操作的一端称为栈顶,另一端称为栈底。栈中的数据元素遵守后进先出LIFO Last In First Out )的原则。
            压栈:栈的插入操作叫做进栈/ 压栈 / 入栈, 入数据在栈顶
            出栈:栈的删除操作叫做出栈。出数据在栈顶

     1.2 栈的使用

    1. public static void main(String[] args)
    2. {
    3. Stack s = new Stack();
    4. s.push(1);
    5. s.push(2);
    6. s.push(3);
    7. s.push(4);
    8. System.out.println(s.size()); // 获取栈中有效元素个数---> 4
    9. System.out.println(s.peek()); // 获取栈顶元素---> 4
    10. s.pop(); // 4出栈,栈中剩余1 2 3,栈顶元素为3
    11. System.out.println(s.pop()); // 3出栈,栈中剩余1 2 栈顶元素为3
    12. if(s.empty())
    13. {
    14. System.out.println("栈空");
    15. }
    16. else
    17. {
    18. System.out.println(s.size());
    19. }
    20. }

    1.3 栈的模拟实现

            从上图中可以看到,Stack 继承了 Vector Vector ArrayList 类似,都是动态的顺序表,不同的是 Vector 是线程安全的。
    1. public class MyStack
    2. {
    3. int[] array;
    4. int size;
    5. public MyStack()
    6. {
    7. array = new int[3];
    8. }
    9. public int push(int e)
    10. {
    11. ensureCapacity();
    12. array[size++] = e;
    13. return e;
    14. }
    15. public int pop()
    16. {
    17. int e = peek();
    18. size--;
    19. return e;
    20. }
    21. public int peek()
    22. {
    23. if(empty())
    24. {
    25. throw new RuntimeException("栈为空,无法获取栈顶元素");
    26. }
    27. return array[size-1];
    28. }
    29. public int size()
    30. {
    31. return size;
    32. }
    33. public boolean empty()
    34. {
    35. return 0 == size;
    36. }
    37. private void ensureCapacity()
    38. {
    39. if(size == array.length)
    40. {
    41. array = Arrays.copyOf(array, size*2);
    42. }
    43. }
    44. }

    1.4 栈的应用场景

            1. 改变元素的序列
            1. 若进栈序列为 1,2,3,4 ,进栈过程中可以出栈,则下列不可能的一个出栈序列是()
                    A: 1,4,3,2 B: 2,3,4,1 C: 3,1,4,2 D: 3,4,2,1
            2.一个栈的初始状态为空。现将元素 1 2 3 4 5 A B C D E依次入栈,然后再依次出栈,则元素出栈的顺序是( )。
                    A: 12345ABCDE B: EDCBA54321 C: ABCDE12345 D: 54321EDCBA
            2. 将递归转化为循环
            比如:逆序打印链表
    1. // 递归方式
    2. void printList(Node head)
    3. {
    4. if(null != head)
    5. {
    6. printList(head.next);
    7. System.out.print(head.val + " ");
    8. }
    9. }
    10. // 循环方式
    11. void printList(Node head)
    12. {
    13. if(null == head)
    14. {
    15. return;
    16. }
    17. Stack s = new Stack<>();
    18. // 将链表中的结点保存在栈中
    19. Node cur = head;
    20. while(null != cur)
    21. {
    22. s.push(cur);
    23. cur = cur.next;
    24. }
    25. // 将栈中的元素出栈
    26. while(!s.empty())
    27. {
    28. System.out.print(s.pop().val + " ");
    29. }
    30. }
            3. 括号匹配
            4. 逆波兰表达式求值
            5. 出栈入栈次序匹配

    栈的压入、弹出序列_牛客题霸_牛客网 (nowcoder.com)

    1.5 概念区分

            栈、虚拟机栈、栈帧有什么区别呢?

    2、队列(Queue)

    2.1 概念

            队列:只允许在一端进行插入数据操作,在另一端进行删除数据操作的特殊线性表,队列具有先进先出 FIFO(First In First Out) 入队列:进行插入操作的一端称为 队尾( Tail/Rear 出队列:进行删除操作的一端称为 队头 Head/Front

    2.2 队列的使用

            在Java 中, Queue 是个接口,底层是通过链表实现 的。

             注意:Queue是个接口,在实例化时必须实例化LinkedList的对象,因为LinkedList实现了Queue接口。

    1. public static void main(String[] args)
    2. {
    3. Queue q = new LinkedList<>();
    4. q.offer(1);
    5. q.offer(2);
    6. q.offer(3);
    7. q.offer(4);
    8. q.offer(5); // 从队尾入队列
    9. System.out.println(q.size());
    10. System.out.println(q.peek()); // 获取队头元素
    11. q.poll();
    12. System.out.println(q.poll()); // 从队头出队列,并将删除的元素返回
    13. if(q.isEmpty())
    14. {
    15. System.out.println("队列空");
    16. }
    17. else
    18. {
    19. System.out.println(q.size());
    20. }
    21. }

    2.3 队列模拟实现

            队列中既然可以存储元素,那底层肯定要有能够保存元素的空间,通过前面线性表的学习了解到常见的空间类型有两种:顺序结构 和 链式结构。同学们思考下: 队列的实现使用顺序结构还是链式结构好?

     2.4 循环队列

            实际中我们有时还会使用一种队列叫循环队列。如操作系统课程讲解生产者消费者模型时可以就会使用循环队列。环形队列通常使用数组实现。

             数组下标循环的小技巧

    1. 下标最后再往后 (offffset 小于 array.length): index = (index + offffset) % array.length

     2. 下标最前再往前(offffset 小于 array.length): index = (index + array.length - offffset) % array.length

             如何区分空与满

    1. 通过添加 size 属性记录
    2. 保留一个位置
    3. 使用标记

     622. 设计循环队列 - 力扣(LeetCode)https://leetcode.cn/problems/design-circular-queue/

    3、双端队列 (Deque)

            双端队列(deque )是指允许两端都可以进行入队和出队操作的队列, deque “double ended queue” 的简称。那就说明元素可以从队头出队和入队,也可以从队尾出队和入队

     Deque是一个接口,使用时必须创建LinkedList的对象。

     4、面试题

    1. 用队列实现栈。
    2. 用栈实现队列。
    3. 实现一个最小栈。

    155. 最小栈 - 力扣(LeetCode)

  • 相关阅读:
    交换机和路由器技术-22-OSPF动态路由协议
    学校报名测评小程序开发制作功能介绍
    GO远程构建并调试
    问题:如果要编辑建好的建筑和空间,需要在分级按钮( )和细分操作按钮楼层下,才能选中建筑物和空间; #微信#媒体#其他
    数据选择器
    Redis基本使用
    Mysql启动报错:InnoDB: Operating system error number 13 in a file operation.的解决方法
    用过Apifox这个API接口工具后,确实感觉postman有点鸡肋......
    如何处理前端文件上传?
    著名书法家傅成洪在香港第八届“一带一路”高峰论坛上展示艺术与合作的融合
  • 原文地址:https://blog.csdn.net/weixin_51912875/article/details/125718488