【数据结构】栈

目录

一,前言

二,基本实现

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

相关推荐
cpolar技术支持7 小时前
Spring Boot 接口本地正常,异地前端却报跨域?用 cpolar 跑通 CORS 预检与白名单
java·springboot·cpolar·前后端分离·cors
wuminyu8 小时前
Virtual Thread重投递至ForkJoinPool任务队列过程解析
java·linux·c语言·jvm·c++
小蒜学长8 小时前
在线保险服务与管理平台的设计与实现(代码+数据库+LW)
java·数据库·spring boot·后端·服务平台·在线保险
All for pursuit.8 小时前
【回溯-6】79.单词搜索
数据结构·c++·算法·leetcode
掉进电商坑三年没爬出来的东叔8 小时前
青龙面板进阶:一个面板聚合多平台签到,所有积分自动领
java·开发语言
Benny_Tang8 小时前
AT_arc180_d [ARC180D] Division into 3 题解
数据结构·c++·算法
殷色玫瑰9 小时前
C++ STL:stack、queue、priority_queue 与容器适配器详解
java·开发语言·数据结构·c++·算法·visualstudio
IT方大同9 小时前
java输入输出+方法
java·开发语言·python
Yyyyyy~9 小时前
【Java】String
java
Wang's Blog9 小时前
Java框架 SpringCloud 快速入门: 服务拆分之服务远程调用
java·开发语言·spring cloud