当前位置:首页 > 后端开发 > 正文

java 怎么写一个stack

Java写栈( Stack):可继承 java.util.Stack类;或基于 Deque接口实现,如用 ArrayDeque作底层存储,通过 push()入栈、 pop()出栈

是用Java实现栈的详细步骤和完整示例,包括核心逻辑、边界处理及扩展功能:

基础结构设计

  1. 成员变量定义

    • private int[] elements; // 存储元素的数组
    • private int top = -1; // 栈顶指针(初始为-1表示空栈)
    • private static final int DEFAULT_CAPACITY = 10; // 默认容量
  2. 构造函数

    java 怎么写一个stack 第1张

    public Stack() { this(DEFAULT_CAPACITY); // 调用带参构造 } public Stack(int capacity) { if (capacity <= 0) { throw new IllegalArgumentException("容量必须大于0"); } elements = new int[capacity]; // 根据传入容量创建数组 }
  3. 核心方法实现

    | 方法名 | 功能描述 | 关键代码逻辑 | 异常处理 |

    |————–|——————————|——————————————————————————|————————–|

    | push(item) | 将元素压入栈顶 | if (isFull()) throw new StackOverflowError();<br>elements[++top] = item; | 栈满时抛出异常 |

    | pop() | 移除并返回栈顶元素 | if (isEmpty()) throw new EmptyStackException();<br>return elements[top--]; | 栈空时抛出异常 |

    | peek() | 查看但不删除栈顶元素 | if (isEmpty()) throw new EmptyStackException();<br>return elements[top]; | 同上 |

    | size() | 获取当前元素数量 | return top + 1; | 无 |

    | isEmpty() | 判断是否为空栈 | return top == -1; | 无 |

    | isFull() | 判断是否已满 | return top == elements.length 1; | 无 |

    java 怎么写一个stack 第2张

  4. 关键细节解析

    扩容机制优化(动态数组)

    当栈空间不足时,可自动扩展底层数组容量,例如修改push方法:

    public void push(int item) { if (isFull()) { // 创建新数组并复制旧数据 int[] newArray = Arrays.copyOf(elements, elements.length 2); elements = newArray; } elements[++top] = item; } ```此实现使栈的最大容量不再受限于初始化值,但会增加少量性能开销。 # 2. 泛型支持改造 若需存储任意类型数据,可将类改为泛型类: ```java public class Stack<T> { private T[] data; // 使用Object数组兼容所有类型 @SuppressWarnings("unchecked") public Stack() { data = (T[]) new Object[DEFAULT_CAPACITY]; // 类型擦除技巧 } // push/pop等方法相应调整参数类型为T } ```注意需要添加`@SuppressWarnings("unchecked")`注解避免编译警告。 # 3. 迭代器实现(增强遍历能力) 通过实现`Iterable`接口支持增强for循环: ```java public Iterator<Integer> iterator() { return new Iterator<Integer>() { private int current = 0; public boolean hasNext() { return current <= top; } public Integer next() { return data[current++]; } }; } ```使用时可直接调用`for (int num : stack) { ... }`进行遍历。 三、完整代码示例 ```java public class IntStack { private int[] elements; private int top; private static final int DEFAULT_CAPACITY = 10; public IntStack() { this(DEFAULT_CAPACITY); } public IntStack(int capacity) { if (capacity <= 0) throw new IllegalArgumentException("非法容量"); elements = new int[capacity]; top = -1; } public void push(int value) { if (top == elements.length 1) { growCapacity(); } elements[++top] = value; } private void growCapacity() { int newSize = elements.length 2; int[] newArray = Arrays.copyOf(elements, newSize); elements = newArray; } public int pop() throws EmptyStackException { if (isEmpty()) throw new EmptyStackException(); return elements[top--]; } public int peek() throws EmptyStackException { if (isEmpty()) throw new EmptyStackException(); return elements[top]; } public boolean isEmpty() { return top == -1; } public int size() { return top + 1; } }

    典型应用场景

    1. 表达式求值:利用后进先出特性处理运算符优先级(如括号匹配)
    2. 深度优先搜索:记录回溯路径时的节点访问顺序
    3. 函数调用模拟:手动管理递归过程的状态保存
    4. 撤销操作实现:历史记录的反向播放功能

    常见误区警示

    1. 混淆栈与队列:确保只在队尾进行插入/删除操作(LIFO原则)
    2. 忽略空栈检查:所有出栈操作前必须验证非空状态
    3. 数组越界风险:动态扩容时注意新旧数组的数据迁移完整性
    4. 类型安全性问题:使用泛型时避免未经检查的类型转换


    FAQs

    Q1: 如果频繁进行大量数据的入栈出栈操作,应该选择哪种实现方式?

    A: 推荐使用链表结构代替数组实现,因为链表在头部插入/删除的时间复杂度为O(1),而数组需要移动元素导致O(n)的时间消耗,Java标准库中的LinkedList就基于双向链表实现,其Deque接口提供的栈操作方法正是为此优化。

    Q2: Java集合框架中的Stack类为什么被标记为遗留类?

    A: 根据Oracle官方文档建议,应使用Deque接口的实现类(如ArrayDeque)替代传统Stack类,因为前者提供了更完善的迭代器实现和更好的性能表现,且遵循了现代集合框架的设计规范,例如ArrayDeque在作为栈使用时,所有操作的时间复杂度都是O(1),而旧版Stack的某些方法存在冗余设计

    java 怎么写一个stack 第3张

0