Java如何手写自定义栈实战?

Java中实现自定义栈可通过数组或链表结构,核心步骤包括定义栈类、内部存储数组或链表、栈顶指针,以及实现push、pop、peek和isEmpty等方法,数组实现需处理扩容,链表实现更灵活但需管理节点。

在Java中实现自定义栈是理解数据结构基础的重要实践,栈遵循后进先出(LIFO)原则,核心操作包括入栈(push)、出栈(pop)、查看栈顶(peek)等,下面通过两种典型实现——数组链表,详细讲解开发步骤,代码可直接用于实际项目。

Java如何手写自定义栈实战?


数组实现(固定容量)

数组实现适合预先知道栈最大深度的场景,内存连续、访问高效。

类结构与成员变量

public class ArrayStack {
    private int maxSize;   // 栈的最大容量
    private int[] stack;   // 用数组存储元素
    private int top;       // 栈顶指针(索引)
}

构造方法

初始化数组并置空栈:

public ArrayStack(int size) {
    this.maxSize = size;
    this.stack = new int[maxSize];
    this.top = -1;  // 初始化栈顶指针为-1(空栈)
}

核心方法实现

入栈 (push)

public void push(int value) {
    if (isFull()) {
        throw new RuntimeException("栈已满!");
    }
    stack[++top] = value;  // 指针上移后写入数据
}

出栈 (pop)

public int pop() {
    if (isEmpty()) {
        throw new RuntimeException("栈为空!");
    }
    return stack[top--];  // 返回栈顶元素,指针下移
}

查看栈顶 (peek)

Java如何手写自定义栈实战?

public int peek() {
    if (isEmpty()) {
        throw new RuntimeException("栈为空!");
    }
    return stack[top];
}

判空 & 判满

public boolean isEmpty() {
    return top == -1;
}
public boolean isFull() {
    return top == maxSize - 1;
}

链表实现(动态扩容)

链表实现无需预设容量,动态扩展内存,避免空间浪费。

节点类定义

private class Node {
    int value;
    Node next;
    Node(int value) {
        this.value = value;
    }
}

栈类与构造方法

public class LinkedStack {
    private Node top;  // 栈顶节点
    public LinkedStack() {
        top = null;    // 初始空栈
    }
}

核心方法实现

入栈 (push)

public void push(int value) {
    Node newNode = new Node(value);
    newNode.next = top;  // 新节点指向原栈顶
    top = newNode;       // 更新栈顶指针
}

出栈 (pop)

public int pop() {
    if (isEmpty()) {
        throw new RuntimeException("栈为空!");
    }
    int value = top.value;
    top = top.next;  // 栈顶下移
    return value;
}

查看栈顶 (peek)

Java如何手写自定义栈实战?

public int peek() {
    if (isEmpty()) {
        throw new RuntimeException("栈为空!");
    }
    return top.value;
}

判空

public boolean isEmpty() {
    return top == null;
}

两种实现的对比

特性 数组实现 链表实现
容量 固定大小(需预设) 动态扩展(无上限)
内存效率 连续内存,无额外指针开销 每个节点含指针,略占空间
时间复杂度 所有操作 O(1) 所有操作 O(1)
适用场景 明确最大深度的场景(如递归解析) 频繁增减元素的动态场景

关键注意事项

  1. 异常处理
    执行pop()peek()前必须检查空栈,避免NullPointerException
  2. 泛型扩展
    可将int替换为泛型<T>,支持多种数据类型(如Stack<String>)。
  3. 线程安全
    多线程环境下需用synchronized修饰方法或改用ConcurrentLinkedDeque

引用说明:本文代码基于《数据结构与算法分析(Java描述)》的栈实现逻辑,结合Oracle官方文档的异常处理规范编写,链表实现参考了Java标准库中LinkedList的链式结构思想。

原创文章,发布者:酷盾叔,转转请注明出处:https://www.kd.cn/ask/16257.html

(0)
酷盾叔的头像酷盾叔
上一篇 2025年6月9日 03:50
下一篇 2025年6月9日 03:58

相关推荐

  • Java如何输出箭头?

    在Java中输出箭头可通过多种方式实现: ,1. 使用Unicode字符直接打印(如System.out.print(“→”);输出右箭头)。 ,2. 组合ASCII字符绘制箭头图案(”-˃”`或换行拼接的星号箭头)。 ,3. 借助图形库(如AWT/JavaFX)绘制自定义箭头图形。 ,根据需求选择文本符号或图形化方案即可。

    2025年6月14日
    200
  • Java函数如何返回两个值

    Java函数无法直接返回两个值,常用方法包括:1.返回数组或集合对象;2.自定义包含两个属性的类;3.使用Pair/Triple元组类;4.通过参数传递可变对象修改值;5.返回Map键值对集合,推荐使用封装对象或元组类保证类型安全。

    2025年5月29日
    300
  • Java基础如何快速入门

    学习Java基础入门:先安装JDK和开发工具(如IDEA),掌握基本语法(变量、数据类型、运算符、流程控制),重点理解面向对象核心概念(类、对象、封装、继承、多态),并通过编写简单程序和小项目实践巩固。

    2025年6月7日
    100
  • Java项目如何快速编译?

    Java项目通过javac编译器将源代码(.java文件)编译成平台无关的字节码(.class文件),该字节码由JVM解释执行。

    2025年6月16日
    200
  • 如何在Java中使用sqrt函数?

    在Java中,使用Math.sqrt()方法计算平方根,传入double类型参数,返回double类型结果,double result = Math.sqrt(16); 将得到4.0,注意处理负数返回NaN的情况。

    2025年6月11日
    100

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

联系我们

400-880-8834

在线咨询: QQ交谈

邮件:HI@E.KD.CN