• Java学习----栈Stack


    今日学习内容总结如下:

    栈Stack

    栈的实现可以有数组实现的顺序栈和链表结构的链式栈

    数组实现的栈结构

    如果需要一个支持动态扩容的顺序栈,则底层还需要以来一个支持动态扩容的数组,将原来的数据搬移到新数组中。也可以使用顺序栈支持动态扩容。

    1. public class ArrayStack {
    2. private Object[] items; //栈中存放的数据
    3. private int size; // 栈中存放数据的个数
    4. public ArrayStack() {
    5. this(10);
    6. }
    7. public ArrayStack(int capacity) {
    8. items=new Object[capacity];
    9. }
    10. //数据压栈--将数据存储在栈顶
    11. public boolean push(Object item) {
    12. //如果栈已经满了则不允许再添加数据
    13. if(size==items.length)
    14. return false;
    15. items[size++]=item;
    16. return true;
    17. }
    18. //数据弹栈--将数据栈栈顶的数据获取出来,同时删除栈顶数据
    19. public Object pop() {
    20. //如果栈中没有数据则返回为null
    21. if(size==0)
    22. return null;
    23. return items[--size];
    24. }
    25. }

    java预定义的栈实现

    public class Stack extends Vector

    实现方式为自定义实现的可变长数组,线程安全

    • E push(E item) 把项压入堆栈顶部
    • synchronized E pop() 移除堆栈顶部的对象,并作为此函数的值返回该对象
    • synchronized E peek() 查看堆栈顶部的对象,但不从堆栈中移除它
    • boolean empty() 测试堆栈是否为空
    • synchronized int search(Object o) 返回对象在堆栈中的位置,以 1 为基数

    总结自定义栈--在线考试题--放水题

    栈是一种用于存储数据的简单数据结构,栈与线性表的最大区别是数据的存取的操作,可以这样认为栈Stack是一种特殊的线性表,其插入和删除操作只允许在线性表的一端进行,一般而言,把允许操作的一端称为栈顶Top,不可操作的一端称为栈底Bottom,同时把插入元素的操作称为入栈Push,删除元素的操作称为出栈Pop。若栈中没有任何元素,则称为空栈

    顺序栈和链式栈

    1. //定义接口
    2. interface Stack {
    3. // 栈是否为空
    4. boolean empty();
    5. // data元素入栈
    6. void push(T data);
    7. // 返回栈顶元素,未出栈
    8. T peek();
    9. // 出栈,返回栈顶元素,同时从栈中移除该元素
    10. T pop();
    11. }

    如果不考虑编程成本,下一步应该定义抽象类,在抽象类中添加公共方法

    顺序栈,顾名思义就是采用顺序表实现的的栈,顺序栈的内部以顺序表为基础,实现对元素的存取操作,当然还可以采用内部数组实现顺序栈,这里使用内部数据组来实现栈,至于以顺序表作为基础的栈实现

    1. class SeqStack implements Stack, Serializable {
    2. // 栈顶指针,-1代表空栈
    3. private int top = -1;
    4. // 容量大小默认为10
    5. private int capacity = 10;
    6. // 存放元素的数组
    7. private T[] array;
    8. private int size;
    9. public SeqStack() {
    10. array = (T[]) new Object[capacity];
    11. }
    12. // 一般情况下应该方法名称为getSize,但是遵循一般的使用习惯,所以命名为size()
    13. public int size() {
    14. return size;
    15. }
    16. @Override
    17. public boolean empty() {
    18. return this.top == -1;
    19. }
    20. // 添加元素,从栈顶(数组尾部)插入
    21. public void push(T data) {
    22. // 判断容量是否充足
    23. if (size == array.length)
    24. ensureCapacity(size * 2 + 1);// 扩容
    25. // 从栈顶添加元素
    26. array[++top] = data;
    27. size++;
    28. }
    29. private synchronized void ensureCapacity(int len) {
    30. Object[] res = new Object[len];
    31. System.arraycopy(array, 0, res, 0, this.size);
    32. this.array = (T[]) res;
    33. }
    34. // 获取栈顶元素的值,不删除
    35. public T peek() {
    36. if (empty())
    37. throw new EmptyStackException();
    38. return array[top];
    39. }
    40. // 从栈顶(顺序表尾部)删除
    41. public T pop() {
    42. if (empty())
    43. throw new EmptyStackException();
    44. size--;
    45. return array[top--];
    46. }
    47. }
    48. class EmptyStackException extends RuntimeException {
    49. private static final long serialVersionUID = -4870633979582008865L;
    50. public EmptyStackException() {
    51. super("栈中没有数据");
    52. }
    53. public EmptyStackException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
    54. super(message, cause, enableSuppression, writableStackTrace);
    55. }
    56. public EmptyStackException(String message, Throwable cause) {
    57. super(message, cause);
    58. }
    59. public EmptyStackException(String message) {
    60. super(message);
    61. }
    62. public EmptyStackException(Throwable cause) {
    63. super(cause);
    64. }
    65. }

    Queue队列

    队列是一种特殊的线性表,特殊之处在于它只允许在表的前端front进行删除操作,而在表的后端rear进行插入操作,和栈一样,队列是一种操作受限制的线性表。进行插入操作端称为队尾,进行删除操作端称为队头。

    根据实现方式不同分为顺序队列和链式队列

    顺序队列

    采用数组实现

    队列的基本操作为添加数据的入队操作enqueue和删除并获取数据的dequeue出队操作

    1. public class ArrayQueue {
    2. private Object[] items; // 具体存储数据的数组
    3. private int head = 0;// 队头下标
    4. private int tail = 0; // 队尾下标
    5. public ArrayQueue() {
    6. this(10);
    7. }
    8. public ArrayQueue(int capacity) {
    9. items = new Object[capacity];
    10. }
    11. public boolean enqueue(Object item) { // 入队操作
    12. if (tail == items.length)
    13. return false; // 队伍已满,拒绝插入操作
    14. items[tail++] = item;
    15. return true;
    16. }
    17. public Object dequeue() { // 出队操作
    18. if (head == tail)
    19. return null; // 队列为空
    20. return items[head++];
    21. }
    22. }

    循环队列

    基于数组的队列实现中,当tail=items.length时需要搬移大量的数据,就会导致入队操作的性能降低,可以使用循环队列解决。

    典型算法题目:约瑟夫环

    1. import java.util.Arrays;
    2. public class CircleQueue {
    3. private Object[] items;
    4. private int head = 0, tail = 0;
    5. public CircleQueue() {
    6. this(10);
    7. }
    8. public CircleQueue(int capacity) {
    9. items = new Object[capacity];
    10. }
    11. public boolean enqueue(Object item) {
    12. // 如果尾指针和头指针重合则表示不能插入数据,因为头指针指向的位置上有数据
    13. if (tail % items.length == head && items[head] != null) {
    14. return false;
    15. } // 拒绝插入数据
    16. tail = tail % items.length;
    17. items[tail++] = item;
    18. return true;
    19. }
    20. public Object dequeue() {
    21. if (head== tail && items[head] != null)
    22. return null;
    23. Object res = items[head];
    24. items[head] = null;
    25. head = (head + 1) % items.length;
    26. return res;
    27. }
    28. public static void main(String[] args) {
    29. CircleQueue cq = new CircleQueue();
    30. for (int i = 0; i < 12; i++) {
    31. cq.enqueue(i);
    32. }
    33. System.out.println(Arrays.toString(cq.items));
    34. System.out.println("ddd:" + cq.head);
    35. for (int i = 0; i < 4; i++)
    36. System.out.println(cq.dequeue());
    37. for (int i = 11; i < 20; i++) {
    38. cq.enqueue(i);
    39. }
    40. System.out.println(Arrays.toString(cq.items));
    41. }
    42. }

  • 相关阅读:
    题目1444:蓝桥杯201 4年第五届真题斐波那契
    作为前端还在使用GIF动画吗?换一种更优雅的方案吧
    嵌入式系统,典型嵌入式系统基本组成,微处理器,嵌入式微处理器,嵌入式软硬件裁减原则,嵌入式实时操作系统
    8-11二路插入排序
    《天天数学》连载51:二月二十日
    分布式计算框架Flink核心基石介绍
    Git从本地库撤销已经添加的文件或目录
    【ArkUI】【HarmonyOS】鸿蒙ets项目如何npm方式引入第三方js类库
    wabp.m 代码注释(便于算法快速理解)
    HTML+CSS篮球静态网页设计(web前端网页制作课作业)NBA杜兰特篮球运动网页
  • 原文地址:https://blog.csdn.net/hanxuya/article/details/126555125