【数据结构】栈

目录

一,前言

二,基本实现

1,接口定义

2,实现类定义

3,主要方法实现

[<1> 入栈 push](#<1> 入栈 push)

[<2> 出栈 pop](#<2> 出栈 pop)

[<3> 获取栈顶元素 peek](#<3> 获取栈顶元素 peek)

[<4> 获取栈中有效元素个数 size](#<4> 获取栈中有效元素个数 size)

[<5> 检测栈是否为空 isEmpty](#<5> 检测栈是否为空 isEmpty)

三,栈、虚拟机栈、栈帧之间的区别


一,前言

栈是一种特殊的线性存储结构,其只允许在固定的一端进行插入和删除元素操作。进行数据插入和删除操作的一端称为栈顶,另一端称为栈底。栈中的数据元素遵守后进先出的原则,即后面入栈的元素先出栈。

栈根据实现方式不同又分为链式栈和线性栈,本文演示的为链式栈。栈的具体操作如下图所示:

二,基本实现

1,接口定义

本次实现选择传递泛型,故接口类也写作泛型类。

java 复制代码
public interface IStack <T> {
    // 入栈
    T push(T val);
    // 出栈
    T pop();
    // 获取栈顶元素
    T peek();
    // 获取栈中有效元素个数
    int size();
    // 检测栈是否为空
    boolean isEmpty();
}

2,实现类定义

在本次实现中,使用无头非循环单链表作为基本结构,定义first引用记录头节点,定义usedSize基础变量记录栈中有效元素个数。

使用单链表作为基本结构是因为栈只需要在一端进行插入或删除,而单链表的头删和头插正好契合需求,该选型可让时间复杂度可达到O(1)并且无需扩容。

java 复制代码
public class StackImpl<T> implements IStack<T>{

    private Node<T> first;
    private int usedSize;

    /**
     * 无参构造方法*/
    public StackImpl() {
        this.first = null;
        this.usedSize = 0;
    }

    /**
     * 节点内部类(使用单链表)*/
    private static class Node<T> {
        T val;
        Node<T> next;
        public Node(T val) {
            this.val = val;
        }
    }
}

3,主要方法实现

<1> 入栈 push

入栈的逻辑实际上就是单链表的头插,如下图所示:

java 复制代码
    /**
     * 入栈*/
    @Override
    public T push(T val) {
        // 创建新节点
        Node<T> node = new Node<>(val);
        // 入栈
        node.next = this.first;
        this.first = node;
        // 维护栈有效元素个数
        this.usedSize ++;
        return val;
    }
<2> 出栈 pop

出栈时存在两种情况:

1,栈为空 ==> 抛出异常

2,栈不为空 ==> 头删,如下图所示:

java 复制代码
    /**
     * 出栈*/
    @Override
    public T pop() {
        // 判空
        if(isEmpty()) {
            throw new StackEmptyException("不可对空栈执行出栈操作!");
        } else {
            T oldVal = this.first.val;
            this.first = this.first.next;
            // 维护栈有效元素个数
            this.usedSize --;
            return oldVal;
        }
    }
<3> 获取栈顶元素 peek

获取栈顶元素时存在两种情况:

1,栈为空 ==> 抛出异常

2,栈不为空 ==> 返回头节点元素

java 复制代码
    /**
     * 获取栈顶元素*/
    @Override
    public T peek() {
        // 判空
        if(isEmpty()) {
            throw new StackEmptyException("不可对空栈执行获取栈顶元素操作!");
        } else {
            return this.first.val;
        }
    }

三,栈、虚拟机栈、栈帧之间的区别

直白的说,栈是一种数据结构,虚拟机栈是 JVM 划分的一块线程私有内存,而栈帧是调用方法时,在虚拟机栈内部为该方法开辟的内存单元。

相关推荐
wangchunyu1142 小时前
JAVA CompletableFuture异步编程实战
java·开发语言·python
paopaokaka_luck3 小时前
流浪动物救助与收养系统(DeepSeek AI对话、 ECharts多维分析、救助流程衔接、领养与回访衔接、 捐赠确认与公示、志愿者协作)
java·前端·javascript·人工智能·mysql·echarts·推荐算法
Thomas.Sir3 小时前
第9课:SpringBoot4.x Web开发基础:WebMvc自动配置、静态资源、请求参数接收
java·spring boot
程序 代码狂人3 小时前
切片表与分区表的区别(数据开发面试版)
java·大数据·开发语言·数据仓库·算法
2501_944521594 小时前
Deepmerge 跨端三方库仓颉适配全流程
java·python·eclipse·github
南归北隐5 小时前
Spring AI Alibaba Graph框架实现MCP数据库查询实战
java·后端·spring ai·mcp·spring ai mcp
古法老登瞎折腾5 小时前
大数据智能运维实战(九):让 AI 查日志——找到异常,也保留上下文
java·大数据·运维·人工智能·spring ai·mcp
ai大模型-探索者6 小时前
Function Call与MCP(区别、联系与实战)
java·服务器·网络
略略略咯咯6 小时前
啊啊啊啊啊
java·服务器·数据库
SL_staff6 小时前
运维救火实战:钉钉API变更致薪资计算中断,如何用可视化逻辑引擎5分钟热修复
java·开源·全栈