【数据结构】栈

目录

一,前言

二,基本实现

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 划分的一块线程私有内存,而栈帧是调用方法时,在虚拟机栈内部为该方法开辟的内存单元。

相关推荐
邪修king1 小时前
Re:Linux系统篇(二十六):文件系统(二):Ext 文件系统底层详解:从 inode、块组到软硬链接,结合 Windows 讲透文件管理本质
android·java·linux
mmmmath_31 小时前
LeetCode.018.四数之和
数据结构·算法·leetcode
Yyyyyy~1 小时前
【java】类和对象
java·开发语言
重生之小比特2 小时前
【Java SE】抽象类和接口
java·开发语言
Lyyaoo.2 小时前
【设计模型】策略模式
java
淡海水2 小时前
11-02-Unity-Mono-vs-IL2CPP-两种脚本后端的数据结构行为差异
数据结构·unity·游戏引擎·il2cpp·mono
譕痕2 小时前
Idea 集成 智能体开发工具“千问(qwen)”
java·ide·spring·语言模型
用户8181870627462 小时前
第27章 消息丢失/重复消费的全链路排查(生产者→Broker→消费者)
java·后端
梦帮科技2 小时前
Next.js 16 模块化单体实战:App Router、领域模块与 Route Handler 分层
css·数据结构·链表·正则表达式·node.js·json·html5