算法通过村第四关-栈青铜笔记|手写栈操作
文章目录
- 前言
- 1. 栈的基础概要
- 1.1 栈的特征
- 1.2 栈的操作
- 1.3 Java中的栈
- 2. 栈的实现(手写栈)
- 2.1 基于数组实现
- 2.2 基于链表实现
- 2.3 基于LinkedList实现
- 总结
前言
提示:我自己一个人的感觉很好 我并不想要拥有你 除非你比我的独处更加宜人 --瓦尔桑·希雷
1. 栈的基础概要
1.1 栈的特征
栈和队列是比较特殊的线性表,为什么特殊呢?(又称为访问受限的线性表)。栈常用于表达式、符号等运算的基础,也是递归的底层实现。理论上递归可以做的题目栈都是可以做的,只是有些问题用栈相对复杂一些。
栈的底层实现是我们常见的链表或者顺序表,栈与线性表的最大区别在于数据的存取操作被限制了,其插入和删除操作只允许在线性表的一端进行。一般而言,我们把允许操作的一端称为栈顶(top),不可以操作的一端称为栈底(bottom),同时插入元素的操作称为入栈(push)删除元素的操作称为出栈(pop)。若栈中没有任何元素,则称为空栈,栈的结构如图所示:

1.2 栈的操作
栈的常见操作主要有:
- push(E):增加一个元素E
- pop():弹出元素E
- peek():显示栈顶元素,但是不出栈
- empty():判断栈是否为空
我们在设计自己的栈的时候,不管是使用数组还是链表,都需要实现以上的几个方法。
一道经典的题目,入栈顺序为1234,所有可能的出栈序列是什么?
这个题是什么意思呢?举个例子,我们可以先让1,2入栈,然后2,1出栈,再让3,4入栈,然后一次出栈,就可以得到2143的序列。
4个元素的全排列有4!= 24,栈要求符合先进后出,根据这个条件我们可以排除:
1234 √ 1243 √ 1324 √ 1342 √ 1423 × 1432 √
2134 √ 2143 √ 2314 √ 2341 √ 2413 × 2431 √
3124 × 3142 × 3214 √ 3241 √ 3412 × 3421 √
4123 × 4132 × 4213 × 4231 × 4312× 4321 √
14中可能,10中不可能。
1.3 Java中的栈
Java中的栈,uitl中就提供了栈Stack类,使用起来也不复杂,我们看一下例子:
import java.util.Stack;public class MainTest {public static void main(String[] args) {Stack<Integer> stack = new Stack<>();// 入栈stack.push(1);stack.push(2);stack.push(3);stack.push(4);// 出栈stack.pop();while (!stack.isEmpty()) {// 展示但是不删除System.out.println(stack.peek());// 删除System.out.println(stack.pop());}}
}
2. 栈的实现(手写栈)
我们在学习栈的过程中,需要了解一些问题,top栈顶指针的指向,有的地方指向栈顶再往上一个空位,有的地方指向栈顶元素。我们确定好设计就行,(根据题目调整,有时候也可以直接问面试官 top指向哪里)这里采用指向栈顶空位置。
如果我们自己要实现栈,可以使用数组,链表Java中提供了LinkedList三种基本实现方式,我们都可以看一下。
2.1 基于数组实现
采用顺序表实现的栈,内部以数组为基础,实现对元素的存取操作。在应用中还要之一每次入栈之前要确保栈的容量是否足够,不够需要考虑扩容的问题。
我们画一下入栈的过程:

出栈的过程:

出栈先将栈顶元素取出,然后top–
展示代码:
import java.util.Arrays;
class Mystack<T> {private Object[] stack;// 栈顶指针private int top;
public Mystack() {// 初始长度为10stack = new Object[10];}
/*** 判断是否为空** @return*/public boolean isEmpty() {return top == 0;}
/*** 返回栈顶元素但是不删除** @return*/public T peek() {T t = null;if (top > 0) {t = (T) stack[top - 1];}return t;}
/*** 入栈操作** @param t*/public void push(T t) {expandCapacity(top + 1);stack[top] = t;top++;}
public T pop() {T t = peek();if (!isEmpty()) {// 清除元素stack[top - 1] = null;top--;}return t;}
/*** 确保容量** @param size*/public void expandCapacity(int size) {int len = stack.length;if (size > len) {size = size * 3 / 2 + 1;stack = Arrays.copyOf(stack, size);}}
public static void main(String[] args) {Mystack<String> stack = new Mystack<>();System.out.println(stack.peek());// nullSystem.out.println(stack.isEmpty());// truestack.push("java");stack.push("is");stack.push("beautiful");stack.push("language");System.out.println(stack.pop());// languageSystem.out.println(stack.isEmpty());// falseSystem.out.println(stack.peek()); // beautiful}
}
2.2 基于链表实现
链表用来实现栈也很简单,头插法(在头部操作链表就可以了)。
我们先画个图:

在链表的那一章我们介绍过没有虚拟节点时对链表头部元素进行插入和删除的操作,不记得的可以回顾一下算法通过村第二关-链表青铜笔记_师晓峰的博客-CSDN博客,这里基于链表实现栈的操作时完全一样的。
代码实现:
class ListStack<T> {// 构造节点class Node<T> {public T t;private Node next;}public Node<T> head;ListStack() {head = null;}/*** 入栈操作* @param t*/public void push(T t) {if (t == null) {throw new IllegalStateException("参数不能为空");}// 头节点为空if (head == null) {head = new Node<T>();head.t = t;head.next = null;}else {Node<T> temp = head;head = new Node<T>();head.t = t;head.next = temp;}}/*** 出栈操作* @return*/public T pop(){if (head == null) {return null;}T t = head.t;head = head.next;return t;}public T peek(){if (head == null) {return null;}return head.t;}/*** 判断是否为空** @return*/public boolean isEmpty() {return head == null;}public static void main(String[] args) {ListStack stack = new ListStack();System.out.println(stack.isEmpty());// truestack.push("Java");stack.push("is");stack.push("beautiful");System.out.println(stack.peek());// beautifulSystem.out.println(stack.pop());// beautifulSystem.out.println(stack.isEmpty());// false}
}
2.3 基于LinkedList实现
这里就很简单了,直接上代码就行;
import java.util.LinkedList;/*** 基于Java的LinkedList来实现栈* @param <T>*/
public class LinkedListStack<T> {private LinkedList<T> ll;LinkedListStack(){ll = new LinkedList<T>();}/*** 入栈操作* @param t*/public void push( T t){ll.addFirst(t);}/*** 出栈但是不删除* @return*/public T peek(){T t = null;if (!ll.isEmpty()){t = ll.peek();}return t;}public T pop(){return ll.removeFirst();}public boolean isEmpty(){return ll.isEmpty();}public static void main(String[] args) {LinkedListStack<String> stack = new LinkedListStack();System.out.println(stack.isEmpty());//trueSystem.out.println(stack.peek());//nullstack.push("java");stack.push("is");stack.push("beautiful");System.out.println(stack.peek());//beautifulSystem.out.println(stack.pop());//beautifulSystem.out.println(stack.isEmpty());//false}
}
总结
提示:记住栈的特性,先进后出
相关文章:
算法通过村第四关-栈青铜笔记|手写栈操作
文章目录 前言1. 栈的基础概要1.1 栈的特征1.2 栈的操作1.3 Java中的栈 2. 栈的实现(手写栈)2.1 基于数组实现2.2 基于链表实现2.3 基于LinkedList实现 总结 前言 提示:我自己一个人的感觉很好 我并不想要拥有你 除非你比我的独处更加宜人 --…...
Python计算加速利器
迷途小书童的 Note 读完需要 6分钟 速读仅需 2 分钟 1 简介 Python 是一门应用非常广泛的高级语言,但是,长久以来,Python的运行速度一直被人诟病,相比 c/c、java、c#、javascript 等一众高级编程语言,完全没有优势。 那…...
PyTorch 深度学习实践 第10讲刘二大人
总结: 1.输入通道个数 等于 卷积核通道个数 2.卷积核个数 等于 输出通道个数 1.单通道卷积 以单通道卷积为例,输入为(1,5,5),分别表示1个通道,宽为5,高为5。假设卷积核大小为3x3,…...
Linux特殊指令
目录 1.dd命令 2.mkfs格式化 3.df命令 4.mount实现硬盘的挂载 5.unshare 1.dd命令 dd命令可以用来读取转换并输出数据。 示例一: if表示infile,of表示outfile。这里的/dev/zero是一个特殊文件,会不断产生空白数据。 bs表示复制一块的大…...
MPI之主从模式的一般编程示例
比如,我们可以选举0号进程为master进程,其余进程为slaver进程 #include "mpi.h" #include <unistd.h> #include <iostream>int main(int argc, char *argv[]) {int err MPI_Init(&argc,&argv);int rank,size;MPI_Comm_r…...
基于野狗算法优化的BP神经网络(预测应用) - 附代码
基于野狗算法优化的BP神经网络(预测应用) - 附代码 文章目录 基于野狗算法优化的BP神经网络(预测应用) - 附代码1.数据介绍2.野狗优化BP神经网络2.1 BP神经网络参数设置2.2 野狗算法应用 4.测试结果:5.Matlab代码 摘要…...
C语言面向对象的编程思想
面向对象编程 面向对象编程Object-Oriented Programming,OOP) 作为一种新方法,其本质是以建立模型体现出来的抽象思维过程和面向对象的方法。模型是用来反映现实世界中事物特征的。任何一个模型都不可能反映客观事物的一切具体特征࿰…...
MPI之非阻塞通信中通信完成检测接口简介
在之前的文章中,简单的写了一个非阻塞的通信代码介绍最最基本的使用: int main(int argc, char *argv[]) {int err MPI_Init(&argc,&argv);int rank,size;MPI_Comm_rank(MPI_COMM_WORLD,&rank);MPI_Comm_size(MPI_COMM_WORLD, &size);…...
Excel:如何实现分组内的升序和降序?
一、POWER 1、构建辅助列D列,在D2单元格输入公式: -POWER(10,COUNTA($A$2:A2)3)C2 2、选中B1:D10,注意不能宣导A列的合并单元格,进行以下操作: 3、删除辅助列即可 二、COUNTA 第一步,D2建立辅助列…...
深度学习论文: Segment Any Anomaly without Training via Hybrid Prompt Regularization
深度学习论文: Segment Any Anomaly without Training via Hybrid Prompt Regularization Segment Any Anomaly without Training via Hybrid Prompt Regularization PDF: https://arxiv.org/pdf/2305.10724.pdf PyTorch代码: https://github.com/shanglianlm0525/CvPytorch Py…...
【算法训练-字符串】一 最长无重复子串
废话不多说,喊一句号子鼓励自己:程序员永不失业,程序员走向架构!本篇Blog的主题是最长无重复子串或最长无重复子数组,这类题目出现频率还是很高的。 最长无重复子串【MID】 先来看字符串数据结构的题目 题干 解题思…...
【数据结构】手撕顺序表
一,概念及结构 顺序表是用一段物理地址连续的存储单元依次存储数据元素的线性结构,一般情况下采用数组存储; 在数组上完成数据的增删查改。 1, 静态顺序表:使用定长数组存储元素。 2.,动态顺序表࿱…...
景联文科技数据标注:人体关键点标注用途及各点的位置定义
人体关键点标注是一种计算机视觉任务,指通过人工的方式,在指定位置标注上关键点,例如人脸特征点、人体骨骼连接点等,常用来训练面部识别模型以及统计模型。这些关键点可以表示图像的各个方面,例如角、边或特定特征。在…...
typescript基础之never
TypeScript 的 never 类型是一种特殊的类型,它表示的是那些永远不存在的值的类型。例如,一个抛出异常或无限循环的函数的返回值类型就是 never,因为它们永远不会返回任何值。never 类型是所有类型的子类型,也就是说,任…...
电子电路学习笔记之NCP304LSQ37T1G ——超低电流电压检测器
超低电流电压检测器是一种专门用于检测极小电流值的设备。它们常用于电子元件或电路中,用于监测电流的存在和程度。这些检测器通常具有高灵敏度和高精度,能够测量微安级别或更小的电流。 超低电流电压检测器的应用领域广泛,例如电池管理系统…...
【计算机组成原理】一文快速入门,很适合JAVA后端看
作者简介: CSDN内容合伙人、CSDN新星计划导师、JAVA领域优质创作者、阿里云专家博主,计算机科班出身、多年IT从业经验、精通计算机核心理论、Java SE、Java EE、数据库、中间件、分布式技术,参加过国产中间件的核心研发,对后端有…...
10万字智慧政务大数据平台项目建设方案222页[Word]
导读:原文《10万字智慧政务大数据平台项目建设方案222页[Word]》(获取来源见文尾),本文精选其中精华及架构部分,逻辑清晰、内容完整,为快速形成售前方案提供参考。 1.1 项目建设目标 推进市一级政府搭建数字政府建设的规划要求,结合市一级政府“互联网+政务服务”建设…...
Python-主线程控制子线程-4
需求:在Python-主线程控制子线程-3的基础上,新增使用UDP接收指令功能,代替从键盘输入指令 # 修改后的程序,主线程可以获取子线程的结果 import threading import time import queue import tracebackfrom loguru import logger i…...
设计模式二十二:策略模式(Strategy Pattern)
定义一系列算法,将每个算法封装成独立的对象,并使这些对象可互相替换。这使得在运行时可以动态地选择算法,而不必改变使用算法的客户端代码。策略模式的主要目标是将算法的定义与使用分离,使得客户端可以根据需要灵活地选择和切换…...
【c语言】结构体内存对齐,位段,枚举,联合
之前学完结构体,有没有对结构体的大小会很疑惑呢??其实结构体在内存中存储时会存在内存对齐,捎带讲讲位段,枚举,和联合,跟着小张一起学习吧 结构体内存对齐 结构体的对齐规则: 第一个成员在与结…...
使用VSCode开发Django指南
使用VSCode开发Django指南 一、概述 Django 是一个高级 Python 框架,专为快速、安全和可扩展的 Web 开发而设计。Django 包含对 URL 路由、页面模板和数据处理的丰富支持。 本文将创建一个简单的 Django 应用,其中包含三个使用通用基本模板的页面。在此…...
连锁超市冷库节能解决方案:如何实现超市降本增效
在连锁超市冷库运营中,高能耗、设备损耗快、人工管理低效等问题长期困扰企业。御控冷库节能解决方案通过智能控制化霜、按需化霜、实时监控、故障诊断、自动预警、远程控制开关六大核心技术,实现年省电费15%-60%,且不改动原有装备、安装快捷、…...
Golang dig框架与GraphQL的完美结合
将 Go 的 Dig 依赖注入框架与 GraphQL 结合使用,可以显著提升应用程序的可维护性、可测试性以及灵活性。 Dig 是一个强大的依赖注入容器,能够帮助开发者更好地管理复杂的依赖关系,而 GraphQL 则是一种用于 API 的查询语言,能够提…...
Java-41 深入浅出 Spring - 声明式事务的支持 事务配置 XML模式 XML+注解模式
点一下关注吧!!!非常感谢!!持续更新!!! 🚀 AI篇持续更新中!(长期更新) 目前2025年06月05日更新到: AI炼丹日志-28 - Aud…...
自然语言处理——Transformer
自然语言处理——Transformer 自注意力机制多头注意力机制Transformer 虽然循环神经网络可以对具有序列特性的数据非常有效,它能挖掘数据中的时序信息以及语义信息,但是它有一个很大的缺陷——很难并行化。 我们可以考虑用CNN来替代RNN,但是…...
关于 WASM:1. WASM 基础原理
一、WASM 简介 1.1 WebAssembly 是什么? WebAssembly(WASM) 是一种能在现代浏览器中高效运行的二进制指令格式,它不是传统的编程语言,而是一种 低级字节码格式,可由高级语言(如 C、C、Rust&am…...
AspectJ 在 Android 中的完整使用指南
一、环境配置(Gradle 7.0 适配) 1. 项目级 build.gradle // 注意:沪江插件已停更,推荐官方兼容方案 buildscript {dependencies {classpath org.aspectj:aspectjtools:1.9.9.1 // AspectJ 工具} } 2. 模块级 build.gradle plu…...
如何更改默认 Crontab 编辑器 ?
在 Linux 领域中,crontab 是您可能经常遇到的一个术语。这个实用程序在类 unix 操作系统上可用,用于调度在预定义时间和间隔自动执行的任务。这对管理员和高级用户非常有益,允许他们自动执行各种系统任务。 编辑 Crontab 文件通常使用文本编…...
Linux nano命令的基本使用
参考资料 GNU nanoを使いこなすnano基础 目录 一. 简介二. 文件打开2.1 普通方式打开文件2.2 只读方式打开文件 三. 文件查看3.1 打开文件时,显示行号3.2 翻页查看 四. 文件编辑4.1 Ctrl K 复制 和 Ctrl U 粘贴4.2 Alt/Esc U 撤回 五. 文件保存与退出5.1 Ctrl …...
Qemu arm操作系统开发环境
使用qemu虚拟arm硬件比较合适。 步骤如下: 安装qemu apt install qemu-system安装aarch64-none-elf-gcc 需要手动下载,下载地址:https://developer.arm.com/-/media/Files/downloads/gnu/13.2.rel1/binrel/arm-gnu-toolchain-13.2.rel1-x…...
