【日撸 Java 300行】Day 14(栈)

目录

Day 14:栈

一、栈的基本知识

二、栈的方法

1. 顺序表实现栈

2. 入栈

3. 出栈 

三、代码及测试

拓展:

小结 


Day 14:栈

Task:

  • push 和 pop 均只能在栈顶操作.
  • 没有循环, 时间复杂度为 O(1).

一、栈的基本知识

        详细的介绍,可以参考这篇学习笔记:【数据结构】栈-CSDN博客。本博文中只选取部分知识点讲解。

        简单来说,我们可以把栈理解成一种 “运算受限” 的线性表,即后进先出(Last In First Out,简称LIFO)或先进后出(First In Last Out,简称FILO)的原则进行的线性表,因此,栈又称为LIFO表或FILO表。

        对于栈这种数据结构的定位,我们可以从栈这个字本身出发。
        “ 栈 ”是一个用于存储货物的房间,就像我们古代用于旅人驻脚歇店的客栈,人们不会在这久居,不过是中转站罢了。

        这个翻译可谓很灵性了,计算机中的“ 栈 ”(Stack)也确实也可以理解为暂时存储的容器。比如在函数调用时,底层编译器会把我们当前的数据放于这个临时的容器中存储,避免在进入函数后当前上下文环境的信息丢失,之后,待到函数返回后再从Stack中取出。

        当然,这种数据中转存储的数据类型我们不是说都称之为栈,还包括有有队列性质的高速缓存与各种正常的顺序存储的文件系统等,只是说栈有些独有方面的特例。

二、栈的方法

1. 顺序表实现栈

        同时需要注意的一点,根据线性表的分类(顺序表和链表) ,我们可以用这两种方式来实现栈的构建,即分为顺序栈和链栈。本博文中通过顺序表来实现栈,具体构造原理可以参考学习笔记,这里不做展开。

	/*** The depth.*/public static final int MAX_DEPTH = 10;/*** The actual*/int depth;/*** The data*/char[] data;/************************ Construct an empty char stack.**********************/public CharStack() {depth = 0;data = new char[MAX_DEPTH];}// Of the first constructor/************************ Overrides the method claimed in Object, the superclass of any class.**********************/public String toString() {String resultString = "";for (int i = 0; i < depth; i++) {resultString += data[i];} // Of for ireturn resultString;}// Of toString

        这里的属性与静态顺序表中的内容无差,构造函数完成栈深度(长度)初始化,空间开辟遵循静态链表开辟的方法——使用new开辟固定“MAX_DEPTH”大小的空间。

        但注意,栈是于栈顶一端进行删除与插入的结构,而为了顺序表的实现方便,我们往往在下标较大处插入,因此我们定义栈顶在数组的最右侧
        所以,按照从左向右打印的习惯,toString()函数完成的就是栈底向栈顶的打印过程。

2. 入栈

        本质上就是加入一个元素,只不过位置被限定在栈顶。
        从顺序表的角度来看,其意义就是在顺序表的最后一个元素后面再插入一个元素。
        由于位置固定,所以我们只需要给末尾元素之后的空位赋值并且让栈深度+1即可(对于从0开始记录的任何表,表长都默认值最后一个元素的下一个位置)

	/************************ Push an element.* * @param paraChar The given char.* @return Success or not.**********************/public boolean push(char paraChar) {if (depth == MAX_DEPTH) {System.out.println("Stack full.");return false;} // Of ifdata[depth] = paraChar;depth++;return true;}// Of push

        对于任何顺序表的插入都不要忘记判断表满的情况,因此,这里先进行一次判满的判断,这是栈的基本健壮性保证。
        之后的入栈操作怎么写,要根据你的栈顶指针的默认指向来确定。
        这里我们用depth来表示栈深度,同时,自然也用于表示栈顶指针。这种情况的话,depth默认指向的位置刚好就是尾元素后面的空位,刚好可以直接插入,于是可以使用:

		data[depth] = paraChar;depth++;

        我们可以做如下简写:

        data[depth++] = paraChar;

         当然,若栈顶指针假设指向末尾元素本身的话,这里我们假设这个变量为top。在插入元素时需要保证栈顶指针要先移动到末尾元素后面的空位才能进行插入,于是就要使用:

		top++;data[top] = paraChar;

         当然,也可以简写成:

        data[++top] = paraChar;

        习惯上,我们会将入栈操作定义为 Boolean 类型,这是因为布尔信息能够明确的告诉我们该操作是否成功。

3. 出栈 

        同顺序表一样,元素删除需要先判断是否为空,以保证程序的健壮性。
        出栈时,使用resultChar先接收栈顶数据,之后再进行栈指针的下移操作,实现逻辑上元素减少(但是实际上这个值还是存放在原指针所指的位置的),因为我们确定栈元素的多少仅依靠栈顶指针的具体值而定。

        这个操作与入栈的操作是完全相逆的,而且也会因为栈顶指针的含义不同而变化,即:栈顶指针指向栈顶有效元素的上方的一个无数据位,一般我们令其值为 -1。由于这里我们采用的是 depth(深度),所以最小值为0,但观察可知,实际操作中读取的 depth - 1,是等效的。

	public char pop() {if (depth == 0) {System.out.println("Nothing to pop.");return '\0';} // Of ifchar resultChar = data[depth - 1];depth--;return resultChar;}// Of pop

三、代码及测试

package datastructure.stack;/*** Char stack. I do not use Stack because it is already defined in Java.** @author: Changyang Hu joe03@foxmail.com* @date created: 2025-05-13*/
public class CharStack {/*** The depth.*/public static final int MAX_DEPTH = 10;/*** The actual depth.*/int depth;/*** The data*/char[] data;/************************ Construct an empty char stack.**********************/public CharStack() {depth = 0;data = new char[MAX_DEPTH];}// Of the first constructor/************************ Overrides the method claimed in Object, the superclass of any class.**********************/public String toString() {String resultString = "";for (int i = 0; i < depth; i++) {resultString += data[i];} // Of for ireturn resultString;}// Of toString/*** ********************** @Title: push* @Description: Push an element.** @param paraChar The given char.* @return Success or not.* @return boolean **********************/public boolean push(char paraChar) {if (depth == MAX_DEPTH) {System.out.println("Stack full.");return false;} // Of ifdata[depth] = paraChar;depth++;return true;}// Of push/*** ********************** @Title: pop* @Description: Pop an element.** @return The popped char.* @return char **********************/public char pop() {if (depth == 0) {System.out.println("Nothing to pop.");return '\0';} // Of ifchar resultChar = data[depth - 1];depth--;return resultChar;}// Of pop/*** ********************** @Title: main* @Description: The entrance of the program.** @param args Not used now.* @return void **********************/public static void main(String args[]) {CharStack tempStack = new CharStack();for (char ch = 'a'; ch < 'm'; ch++) {tempStack.push(ch);System.out.println("The current stack is: " + tempStack);} // Of for chchar tempChar;for (int i = 0; i < 12; i++) {tempChar = tempStack.pop();System.out.println("Poped: " + tempChar);System.out.println("The current stack is: " + tempStack);} // Of for i}// Of main}// Of CharStack

拓展:

        栈:【数据结构】栈-CSDN博客


小结 

        通过顺序表来实现栈操作,本身并不复杂,只是说一些要点需要我们在使用前就想好:

  • 采用 depth(指向栈顶的下一个元素)还是 top(指向栈顶)作为下标
  • 采用顺序表来实现还是链表(链表相关参考学习笔记)

        栈虽然本身简单,但是其在数据传输中的战略地位极高。 

        栈实现了“ 调用 ”思想的核心。栈的临时存储与栈出数据总是最近一次栈入的数据的特性非常符合嵌套调用与返回的特性。所以如今我们使用的各种函数都用到了栈的思想,任何使用函数完成的算法体系都可以使用栈完成模拟。

        栈贯穿了计算机的各个邻域,栈的概念在硬件中就早有使用,因为栈的实现,促成了操作系统的中断特性的实现,而中断的特性又促成后来批处理操作系统的诞生,是当代计算机的奠基石。也许毫不夸张说,没有栈,就没有我们如今的计算机的基础。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/905424.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

dotnet core c#调用Linux c++导出函数

1.声明C++导出函数 platform_export.h // // Created by dev on 5/6/25. //#ifndef PLATFORM_EXPORT_H #define PLATFORM_EXPORT_H #if defined(_WIN32)#ifdef LIB_EXPORTS#define LIB_API __declspec(dllimport)#else#define LIB_API __declspec(dllimport)#endif #else#ifde…

SparkSQL操作Mysql

前面的课程我们学习了如何从csv文件中读入数据&#xff0c;这相当于是对csv这种类型的数据的操作。那么接下来&#xff0c;我们一起看看&#xff0c;如何写Spark程序来操作mysql数据库。先来给大家介绍一下我们这节课的主要学习内容&#xff1a; &#xff08;1&#xff09;安装…

语言学中的对象语言与元语言 | 概念 / 区别 / 实例分析

注&#xff1a;英文引文&#xff0c;机翻未校。 语言学中的“对象语言”和“元语言” 刘福长 现代外语 1989年第3期&#xff08;总第45期&#xff09; 在阅读语言学著作时&#xff0c;我们有时会遇到这样两个术语&#xff1a;对象语言&#xff08;object language&#xff0…

livenessProbe 和 readinessProbe 最佳实践

在 Kubernetes 中&#xff0c;livenessProbe 和 readinessProbe 是确保应用高可用性的关键机制&#xff0c;但配置不当可能导致应用频繁重启或流量中断。以下是配置这两个探针的最佳实践&#xff1a; 1. 核心区别与作用 探针类型目的失败后果livenessProbe检测应用是否 存活&…

集成管理工具Gitlab

GitLab 是一个功能强大的开源代码托管和协作平台&#xff0c;集成 GitLab 可以显著提升团队的开发效率。下面我将为你介绍如何集成 GitLab&#xff0c;包括安装配置和基本使用流程。 一、GitLab 安装与配置 GitLab 有多种安装方式&#xff0c;推荐使用官方 Omnibus 包安装&am…

Electron-Vue3、Electron-React、Electron-Angular打造舆情监控系统项目

Electron是一个跨平台的桌面应用开发框架&#xff0c;可以让我们用html css js的技术开发跨平台桌面上可以安装的软件。视频详解: Electron教程 ElectronVue跨平台桌面软件开发教程-2024年更新&#xff08;大地老师&#xff09; 从Electron环境搭建开始到手把手教你调试、Elect…

08.webgl_buffergeometry_attributes_none ,three官方示例+编辑器+AI快速学习

本实例主要讲解内容 这个Three.js示例展示了无属性几何体渲染技术&#xff0c;通过WebGL 2的gl_VertexID特性和伪随机数生成算法&#xff0c;在着色器中动态计算顶点位置和颜色&#xff0c;而不需要在CPU端预先定义几何体数据。 核心技术包括&#xff1a; WebGL 2的顶点ID特…

Ubuntu 22.04搭建OpenStreeMap地址解析服务(保姆级教程)

1.数据准备 1.1.全球数据 下载地址&#xff1a;https://planet.openstreetmap.org/ 1.2.特定区域的数据 下载地址&#xff1a;Geofabrik Download Server 2.安装必要的软件包 2.1.更新系统软件包 sudo apt updatesudo apt upgrade 2.2.安装所需要的软件包 执行下面的命…

Ubuntu 22.04.5 LTS上部署Docker及相关优化

以下是在Ubuntu 22.04.5 LTS上部署Docker及相关优化的步骤&#xff1a; 安装Docker 更新系统&#xff1a;在安装Docker之前&#xff0c;先确保系统是最新的&#xff0c;执行以下命令&#xff1a;sudo apt update sudo apt upgrade -y安装依赖包&#xff1a;安装一些必要的依赖…

React -> AI组件 -> 调用Ollama模型, qwen3:1.7B非常聪明

使用 React 搭建一个现代化的聊天界面&#xff0c;支持与 Ollama 本地部署的大语言模型进行多轮对话。界面清爽、功能完整&#xff0c;支持 Markdown 渲染、代码高亮、<think> 隐藏思考标签、流式渐进反馈、暗黑模式适配等特性。 &#x1f9e9; 核心功能亮点 ✅ 模型选择…

vue2/3 中使用 @vue-office/docx 在网页中预览(docx、excel、pdf)文件

1. 安装依赖&#xff1a; #docx文档预览组件npm install vue-office/docx vue-demi0.14.6#excel文档预览组件npm install vue-office/excel vue-demi0.14.6#pdf文档预览组件npm install vue-office/pdf vue-demi0.14.6 vue2.6版本或以下还需要额外安装 vue/composition-api …

【应用密码学】实验五 公钥密码2——ECC

一、实验要求与目的 1.复习CCC基本概念&#xff0c;并根据实验平台提供的资料完成验证性实验。 2.编程练习&#xff1a;以书上例题小模数p为例编程实现ECC的基本运算规则。 二、实验内容与步骤记录&#xff08;只记录关键步骤与结果&#xff0c;可截图&#xff0c;但注意排版…

rust-candle学习笔记9-使用tokenizers加载qwen3分词,使用分词器处理文本

参考&#xff1a;about-pytorch&#xff0c; about-tokenizers 在魔搭社区链接下载qwen3的tokenizer.json文件 添加依赖库&#xff1a; cargo add tokenizers tokenizers库初体验&#xff1a; use tokenizers::tokenizer::{self, Result, Tokenizer};fn main() -> Resu…

【MySQL】存储引擎 - ARCHIVE、BLACKHOLE、MERGE详解

&#x1f4e2;博客主页&#xff1a;https://blog.csdn.net/2301_779549673 &#x1f4e2;博客仓库&#xff1a;https://gitee.com/JohnKingW/linux_test/tree/master/lesson &#x1f4e2;欢迎点赞 &#x1f44d; 收藏 ⭐留言 &#x1f4dd; 如有错误敬请指正&#xff01; &…

5.Redission

5.1 前文锁问题 基于 setnx 实现的分布式锁存在下面的问题&#xff1a; 重入问题&#xff1a;重入问题是指 获得锁的线程可以再次进入到相同的锁的代码块中&#xff0c;可重入锁的意义在于防止死锁&#xff0c;比如 HashTable 这样的代码中&#xff0c;他的方法都是使用 sync…

C语言主要标准版本的演进与核心区别的对比分析

以下是C语言主要标准版本的演进与核心区别的对比分析 K&R C&#xff08;1978年&#xff09; 定位‌&#xff1a;非标准化的原始版本&#xff0c;由Brian Kernighan和Dennis Ritchie定义 特性‌&#xff1a; 基础语法&#xff1a;函数声明无参数列表&#xff08;如int func…

【C++设计模式之Template Method Pattern】

C设计模式之Template Method Pattern 模式定义核心思想动机(Motivation)结构&#xff08;Structure&#xff09;实现步骤应用场景要点总结 模式定义 模式定义&#xff1a; 定义一个操作中的算法的骨架(稳定)&#xff0c;而将一些步骤延迟(变化)到子类中。Template Method使得子…

【动态导通电阻】p-GaN HEMTs正向和反向导通下的动态导通电阻

2024 年,浙江大学的 Zonglun Xie 等人基于多组双脉冲测试方法,研究了两种不同技术的商用 p-GaN 栅极 HEMTs 在正向和反向导通模式以及硬开关和软开关条件下的动态导通电阻(RON)特性。实验结果表明,对于肖特基型 p-GaN 栅极 HEMTs,反向导通时动态 RON 比正向导通高 3%-5%;…

PDFMathTranslate:科学 PDF 文件翻译及双语对照工具

PDFMathTranslate&#xff1a;科学 PDF 文件翻译及双语对照工具 在科研和学习过程中&#xff0c;我们经常会遇到大量的英文 PDF 文献&#xff0c;翻译这些文献成为了一项繁琐且耗时的工作。PDFMathTranslate 是一款强大的科学 PDF 文件翻译及双语对照工具&#xff0c;它能够保…

Flutter PIP 插件 ---- 为iOS 重构PipController, Demo界面,更好的体验

接上文 Flutter PIP 插件 ---- 新增PipActivity&#xff0c;Android 11以下支持自动进入PIP Mode 项目地址 PIP&#xff0c; pub.dev也已经同步发布 pip 0.0.3&#xff0c;你的加星和点赞&#xff0c;将是我继续改进最大的动力 在之前的界面设计中&#xff0c;还原动画等体验一…