当前位置:首页 > 技术 > 正文内容

用Java打造高效栈数据结构

访客 技术 2026年8月23日 1

栈(Stack)是一种遵循后进先出(LIFO,Last In First Out)原则的线性数据结构。在Java中,我们可以通过接口抽象其行为,再分别用数组或链表实现。以下展示完整实现,包含两个版本:数组栈和链表栈。

1. 定义栈接口

首先定义一个泛型接口,明确栈的核心操作:

public interface IStack<E> {
    boolean add(E item);      // 入栈
    E remove();               // 出栈
    E top();                  // 查看栈顶
    boolean empty();          // 判空
    int length();             // 元素个数
    void reset();             // 清空
}

2. 基于数组的栈实现

使用动态数组存储,支持自动扩容,避免固定容量限制。

public class ArrayBasedStack<T> implements IStack<T> {
    private static final int INIT_CAPACITY = 10;
    private T[] data;
    private int count;

    @SuppressWarnings("unchecked")
    public ArrayBasedStack() {
        data = (T[]) new Object[INIT_CAPACITY];
        count = 0;
    }

    @SuppressWarnings("unchecked")
    public ArrayBasedStack(int capacity) {
        if (capacity <= 0) throw new IllegalArgumentException("容量必须大于0");
        data = (T[]) new Object[capacity];
        count = 0;
    }

    @Override
    public boolean add(T item) {
        ensureCapacity();
        data[count++] = item;
        return true;
    }

    @Override
    public T remove() {
        if (empty()) throw new RuntimeException("栈为空");
        T value = data[--count];
        data[count] = null; // 避免内存泄漏
        return value;
    }

    @Override
    public T top() {
        if (empty()) throw new RuntimeException("栈为空");
        return data[count - 1];
    }

    @Override
    public boolean empty() {
        return count == 0;
    }

    @Override
    public int length() {
        return count;
    }

    @Override
    public void reset() {
        for (int i = 0; i < count; i++) data[i] = null;
        count = 0;
    }

    private void ensureCapacity() {
        if (count >= data.length) {
            @SuppressWarnings("unchecked")
            T[] newData = (T[]) new Object[data.length * 2];
            System.arraycopy(data, 0, newData, 0, count);
            data = newData;
        }
    }

    // 从栈底到栈顶输出
    public void printStack() {
        System.out.print("栈内容: [");
        for (int i = 0; i < count; i++) {
            System.out.print(data[i]);
            if (i < count - 1) System.out.print(", ");
        }
        System.out.println("]");
    }
}

3. 基于链表的栈实现

使用单向链表,元素动态分配,无容量限制。

public class LinkedStack<T> implements IStack<T> {
    private Node<T> head;   // 栈顶节点
    private int size;

    private static class Node<E> {
        E value;
        Node<E> next;
        Node(E value) { this.value = value; }
    }

    public LinkedStack() {
        head = null;
        size = 0;
    }

    @Override
    public boolean add(T item) {
        Node<T> newNode = new Node<>(item);
        newNode.next = head;
        head = newNode;
        size++;
        return true;
    }

    @Override
    public T remove() {
        if (empty()) throw new RuntimeException("栈为空");
        T result = head.value;
        head = head.next;
        size--;
        return result;
    }

    @Override
    public T top() {
        if (empty()) throw new RuntimeException("栈为空");
        return head.value;
    }

    @Override
    public boolean empty() {
        return size == 0;
    }

    @Override
    public int length() {
        return size;
    }

    @Override
    public void reset() {
        head = null;
        size = 0;
    }

    // 借助临时栈实现从底到顶的输出
    public void printStack() {
        System.out.print("栈内容: [");
        LinkedStack<T> temp = new LinkedStack<>();
        Node<T> current = head;
        while (current != null) {
            temp.add(current.value);
            current = current.next;
        }
        while (!temp.empty()) {
            System.out.print(temp.remove());
            if (!temp.empty()) System.out.print(", ");
        }
        System.out.println("]");
    }
}

4. 测试两种实现

编写测试代码验证功能:

public class StackDemo {
    public static void main(String[] args) {
        System.out.println("=== 数组栈测试 ===");
        runTests(new ArrayBasedStack<>());

        System.out.println("\n=== 链表栈测试 ===");
        runTests(new LinkedStack<>());
    }

    static void runTests(IStack<Integer> stack) {
        stack.add(10);
        stack.add(20);
        stack.add(30);
        stack.add(40);

        // 输出栈内容
        if (stack instanceof ArrayBasedStack) {
            ((ArrayBasedStack<Integer>) stack).printStack();
        } else {
            ((LinkedStack<Integer>) stack).printStack();
        }

        System.out.println("栈顶元素: " + stack.top());
        System.out.println("元素个数: " + stack.length());
        System.out.println("移除元素: " + stack.remove());
        System.out.println("移除元素: " + stack.remove());

        if (stack instanceof ArrayBasedStack) {
            ((ArrayBasedStack<Integer>) stack).printStack();
        } else {
            ((LinkedStack<Integer>) stack).printStack();
        }

        System.out.println("是否为空: " + stack.empty());
        stack.reset();
        System.out.println("清空后是否为空: " + stack.empty());
    }
}

关键操作说明

  • 入栈:将元素压入栈顶。
  • 出栈:弹出并返回栈顶元素。
  • 查看栈顶:仅返回不删除。
  • 判空与大小:检查栈是否为空及元素数量。
  • 清空:重置栈状态。

数组栈适合随机访问频繁的场景,链表栈适合插入删除操作多的场景。两种实现都遵循LIFO原则,可根据需求灵活选用。

相关文章

Linux crontab 详解

1) crontab 是什么cron 是 Linux 的定时任务守护进程;crontab 是用来编辑/查看“按时间周期执行命令”的表(cron table)。常见两类:用户 crontab:每个用户一份(crontab -e 编辑)系统级 crontab / cron.d:可指定执行用户(/etc/crontab、/etc/cron.d/*)2) crontab 时间...

富文本里可以允许的 HTML 属性

一、所有标签默认允许的安全属性(极少)class        (可选)id           (通常建议禁用)title️ 注意:id 容易被滥用做锚点注入,很多系统直接禁用class 允许的话最好只允许固定前缀(如 editor-*)二、a 标签允许属性<a href="" t...

Mac 安装 Node.js 指南

方法一:通过官网安装包(最简单,适合初学者)如果你只是想快速安装并开始使用,这是最直接的方法。访问 Node.js 官网。页面会显示两个版本:LTS (Recommended For Most Users):长期支持版,最稳定。建议选这个。Current:最新特性版,包含最新功能但可能不够稳定。下载 .pkg 安装包并运行。按照安装向导点击“下一步”即可完成。方法二:使用 Homebrew 安装(...

自定义域名解析神器 dnsmasq

什么是 dnsmasq?dnsmasq 是一个轻量级、功能强大的网络服务工具,专为小型和中等规模网络设计。它是一个综合的网络基础设施解决方案[1]。dnsmasq 能做什么?功能说明应用场景DNS 转发与缓存将 DNS 查询转发到上游服务器(ISP、Google DNS 等),并在本地缓存结果加快 DNS 查询速度,减少外部 DNS 流量本地 DNS解析本地网络设备的主机名,无需编辑&n...

linux screen 用法详情 (nohup 的替代方案)

一、screen 是什么?能干嘛?screen 是一个终端复用器,可以:在一个 SSH 会话中开多个“虚拟终端”SSH 断线后,程序仍然在后台运行随时重新连接到原来的会话特别适合:nohup 的替代方案跑脚本 / 爬虫 / 训练模型运维、远程开发二、安装 screen# CentOS / Rocky / Almayum install -y screen# Debian / Ubuntuapt i...

PHPStan 有什么用?怎么用?

PHPStan 是一个 PHP 的静态分析工具,在不运行代码的情况下就能帮你发现潜在问题,比如:传错类型(把 string 传给接受 int 的函数)访问不存在的属性 / 方法null 没处理好永远不会执行到的代码数组 key/值类型不一致返回值不符合声明注释和真实类型不匹配它非常适合:想提升代码质量、减少线上 bug、统一团队风格的人(尤其是中大型项目)。一、PHPStan 有什么用(通俗点说)...

发表评论

访客

◎欢迎参与讨论,请在这里发表您的看法和观点。