一起学算法(栈篇)
1.栈的概念
1.栈的定义
栈是仅限在表尾进行插入和删除的线性表,栈又被称为先进后出的线性表,简称“LIFO”
我们这次用数组作为我们栈的底层数据结构,代码会放到结尾供大家参考使用
2.栈顶的定义
栈是一个线性表,我们允许插入和删除的一端称为栈顶
3.栈底的定义
和栈顶相对的另一端称为栈底,实际上栈底的元素我们不需要关心
4.栈的创建
//数据容器private T[] data;//容积private int capacity;//实际存放的元素个数private int size;
2.入栈
1.入栈的定义
栈元素的插入操作叫做入栈,也可以称为进栈、压栈
2.动画演示
图中是以链表为底层数据结构的,大家看图了解个大概就可以了,具体可以看代码是怎么实现的
3.代码实现
//在末尾添加元素public void addTail(T val) {//this.data[size]=val;this.add(this.size, val);}//在中间插入元素public void add(int index, T val) {if (index < 0 || index > size) {throw new IllegalArgumentException("index is invalid!");}//判断数组是否满if(this.size==this.capacity){//数组满的话扩容原来数组的两倍int newCapacity=this.capacity*2;T[] newDate=(T[]) new Object[newCapacity];//创建一个新的数组//进行数组迁移for (int i = 0; i < this.size; i++) {newDate[i]=this.data[i];}this.capacity=newCapacity;this.data=newDate;}
3.出栈
1.出栈的定义
栈元素的删除操作叫做出栈,也可称为弹栈
2.动画演示
3.代码演示
//移出末尾public T removeTail() {
// T val=this.data[size-1];
// this.size-=1;
// return val;return this.remove(this.size);}//中部移出public T remove(int index) {if (index < 0 || index > size) {throw new IllegalArgumentException("index is invalid!");}T val = this.data[index];for (int i = index; i < this.size; i++) {this.data[i] = this.data[i+1];}this.size -= 1;if(this.size<=this.capacity/4&&this.capacity/2>1){int newCapacity=this.capacity/2;T[] newDate=(T[])new Object[newCapacity];for (int i = 0; i < this.size; i++) {newDate[i]=this.data[i];}this.capacity=newCapacity;this.data=newDate;}
4.查询栈顶
1.获取栈顶的定义
一般我们可以去查看栈顶的元素是什么
2.动画演示
3.代码演示
public T peek(T val) {return data.getEnByIndex(this.size() - 1);}//获得指定索引的元素public T getEnByIndex(int index) {if (index < 0 || index > size) {throw new IllegalArgumentException("index is invalid!");}return this.data[index];}
基本的栈能用到的就这些基本的方法,接下来给大家一个完整的代码,供大家学习参考
public class StackDemo<T> implements Stack<T> {//以我们封装的数组作为栈的底层数据结构private arrSub<T>data;public StackDemo() {data=new arrSub<>();}public StackDemo(int capacity) {data=new arrSub<>(capacity);}@Override//弹栈public T pop() {return data.removeTail();}@Override//往栈中添加元素public void push(T val) {data.addTail(val);}@Override//查看元素个数public int size() {return data.getSize();//获得数组元素个数}@Override//判断是否为空public boolean isEmpty() {return data.isEmpty();}@Override//查看栈顶元素public T peek(T val) {return data.getEnByIndex(this.size() - 1);}@Overridepublic T peek() {return null;}@Overridepublic String toString() {StringBuilder sb = new StringBuilder("栈顶[");T[] arr = data.getData();for (int i = size() - 1; i >= 0; i--) {sb.append(arr[i]);if (i != 0) {sb.append(",");}}sb.append("]栈底");return sb.toString();}public static void main(String[] args) {Stack<String> stack = new StackDemo<>(10);String[] fruits= {"apple", "banana", "peach", "watermelon", "strawberry", "pear", "orange", "grape"};for (int i = 0; i < fruits.length; i++) {stack.push(fruits[i]);}System.out.println(stack);while (!stack.isEmpty()) {System.out.println("ele-->" + stack.pop());System.out.println(stack + "栈中元素的个数:" + stack.size());}}
}
public class arrSub<T> {//数据容器private T[] data;//容积private int capacity;//实际存放的元素个数private int size;public arrSub(int capacity) {this.capacity = capacity;this.data = (T[]) new Object[this.capacity];this.size = 0;}public arrSub() {this.capacity = 10;}// 判断数据容器是否为空public boolean isEmpty() {return this.size == 0;}public T[] getData(){return this.data;}//获得数组的容积public int getCapacity() {return this.capacity;}//获取元素的个数public int getSize() {return this.size;}//首行添加元素public void addTop(T val) {
// for (int i = size-1; i >=0 ; i--) {
// this.data[i+1]=this.data[i];
// }
// this.data[0]=val;this.add(0, val);}//在末尾添加元素public void addTail(T val) {//this.data[size]=val;this.add(this.size, val);}//在中间插入元素public void add(int index, T val) {if (index < 0 || index > size) {throw new IllegalArgumentException("index is invalid!");}//判断数组是否满if(this.size==this.capacity){//数组满的话扩容原来数组的两倍int newCapacity=this.capacity*2;T[] newDate=(T[]) new Object[newCapacity];//创建一个新的数组//进行数组迁移for (int i = 0; i < this.size; i++) {newDate[i]=this.data[i];}this.capacity=newCapacity;this.data=newDate;}for (int i = this.size - 1; i >= index; i--) {this.data[i + 1] = this.data[i];}this.data[index] = val;this.size += 1;}//获得指定索引的元素public T getEnByIndex(int index) {if (index < 0 || index > size) {throw new IllegalArgumentException("index is invalid!");}return this.data[index];}//获得指定元素的索引public int getEnByVal(int index, T val) {if (index < 0 || index > size) {throw new IllegalArgumentException("index is invalid!");}for (int i = 0; i < this.size; i++) {if (this.data[i] == val) {return i;}}return -1;}//判断是否包含某种布局public boolean contains(T val) {for (int i = 0; i < this.size; i++) {if (this.data[i] == val) {return true;}}return false;}//修改指定索引的元素public void upLoad(T var, int index) {if (index < 0 || index > this.size) {throw new IllegalArgumentException("index is invalid!");}this.data[index] = var;}//重写toString的方法@Overridepublic String toString() {StringBuilder stringBuilder = new StringBuilder(10);for (int i = 0; i < this.size; i++) {stringBuilder.append(this.data[i] + ",");}return stringBuilder.substring(0, stringBuilder.lastIndexOf(",") == -1 ? 0 : stringBuilder.lastIndexOf(","));}//移出末尾public T removeTail() {
// T val=this.data[size-1];
// this.size-=1;
// return val;return this.remove(this.size);}//移出首部public T removeTop() {
// T val=this.data[0];
// for (int i = 1; i <this.size; i++) {
// this.data[i-1]=this.data[i];
// }
// this.size-=1;
// return val;return this.remove(0);}//中部移出public T remove(int index) {if (index < 0 || index > size) {throw new IllegalArgumentException("index is invalid!");}T val = this.data[index];for (int i = index; i < this.size; i++) {this.data[i] = this.data[i+1];}this.size -= 1;if(this.size<=this.capacity/4&&this.capacity/2>1){int newCapacity=this.capacity/2;T[] newDate=(T[])new Object[newCapacity];for (int i = 0; i < this.size; i++) {newDate[i]=this.data[i];}this.capacity=newCapacity;this.data=newDate;}return val;}public static void main(String[] args) {arrSub myArr = new arrSub(50);for (int i = 1; i <= 20; i++) {myArr.addTail(i + 10);}System.out.println(myArr);
// System.out.println("20?" + myArr.contains(20));
// System.out.println("50?" + myArr.contains(50));while (!myArr.isEmpty()) {myArr.removeTail();System.out.println(myArr);}}
leetcode题单:
从尾到头打印链表
public int[] reversePrint(ListNode head) {LinkedList<Integer> stack = new LinkedList<Integer>();while(head != null) {stack.addLast(head.val);head = head.next;}int[] res = new int[stack.size()];for(int i = 0; i < res.length; i++)res[i] = stack.removeLast();return res;}
括号的最大嵌套深度
public int maxDepth(String s) {int ans = 0, size = 0;for (int i = 0; i < s.length(); ++i) {char ch = s.charAt(i);if (ch == '(') {++size;ans = Math.max(ans, size);} else if (ch == ')') {--size;}}return ans;}
回文链表
public boolean isPalindrome(ListNode head) {if(head==null){return false;}StringBuilder s1=new StringBuilder();StringBuilder s2=new StringBuilder();while(head!=null){s1.append(head.val);s2.append(head.val);head=head.next;}s2.reverse();return s1.toString().equals(s2.toString());}
这里以数组为底层结构的队列代码供大家参考
import java.util.Optional;public class ArrQueue<T> implements Queue<T> {// 队列的容器CycleArray<T> data;// 构造函数public ArrQueue() {data = new CycleArray<>();}public ArrQueue(int capacity) {this.data = new CycleArray<>(capacity);}@Overridepublic void offer(T ele) {data.addTail(ele);}@Overridepublic T poll() {return data.removeHead();}@Overridepublic int size() {return data.getSize();}@Overridepublic boolean isEmpty() {return data.isEmpty();}@Overridepublic T peek() {Optional<T> optional = data.getFront();if (optional.isPresent()) {return optional.get();}return null;}@Overridepublic String toString() {return data.toString();}
}
import java.util.Optional;/*解决了队列删除时的时间复杂度O(n),循环队列删除时的时间复杂度为O(1)* 假设有两个索引,front-->始终指该数组的第一个元素 tail-->始终指向元素插入位置* 如果front==tail时,该循环数组为空* 如果(tail+1)%capacity=front时,该数组为满状态** */
/*** 循环队列的底层容器*/
public class CycleArray<T> {// 数据容器private T[] data;// 容积private int capacity;// 实际存放元素的个数private int size;// 声明两个索引 front--队首 tail--队尾int front = 0;int tail = 0;// front === tail 队列是空的 (tail+1)/capacity == front 队列是满的public CycleArray() {this(10);}public CycleArray(int capacity) {this.capacity = capacity + 1;//因为要浪费一个空间,所以在这里要多加一个空间this.data = (T[]) new Object[this.capacity];// 浪费一个空间this.size = 0;}public T[] getData() {return this.data;}// 1、队列是否为空public boolean isEmpty() {return this.front == this.tail;}// 2、获取数组的容积public int getCapacity() {return this.capacity;}//3、获取实际存放元素的个数public int getSize() {return this.size;}// 在队列的尾部添加元素(tail指向待插入元素的位置)public void addTail(T val) {// 当队列已满,要进行扩容if ((this.tail + 1) % this.capacity == this.front) {// 新的容积int newCapacity = 2 * (this.capacity - 1);resize(newCapacity);}// 将val插入到队列的尾部this.data[this.tail] = val;// tail向后移动this.tail = (this.tail + 1) % capacity;// 更新size的值this.size += 1;}private void resize(int newCapacity) {T[] newData = (T[]) new Object[newCapacity + 1];// 迁移数据 this.frontint cur = this.front;int index = 0;while (cur != this.tail) {newData[index++] = this.data[cur];cur = (cur + 1) % this.capacity;}// 修改属性this.capacity = newCapacity + 1;this.data = newData;this.front = 0;this.tail = this.size;}@Overridepublic String toString() {StringBuilder sb = new StringBuilder();int cur = this.front;while (cur != this.tail) {sb.append(this.data[cur]);if ((cur + 1) % this.capacity != this.tail) {sb.append(",");}cur = (cur + 1) % this.capacity;}sb.append("[" + this.front + "<-->" + this.tail + "]");return sb.toString();}//从队列中移除元素public T removeHead() {// 1、队列是否为空if (this.front == this.tail) {return null;}T val = this.data[this.front];this.front = (this.front + 1) % this.capacity;this.size--;// 缩容if (this.size <= this.capacity / 4 && this.capacity / 2 > 1) {resize(this.capacity / 2);}return val;}public Optional<T> getFront() {if (isEmpty()) {return Optional.empty();}return Optional.of(this.data[this.front]);}// 测试public static void main(String[] args) {CycleArray<Integer> myArr = new CycleArray<>(5);for (int i = 1; i <= 15; i++) {myArr.addTail(i + 25);System.out.println("添加:" + myArr);if (i % 3 == 0) {int val = myArr.removeHead();System.out.println("删除: Header是:" + val);}}}
相关文章:

一起学算法(栈篇)
1.栈的概念 1.栈的定义 栈是仅限在表尾进行插入和删除的线性表,栈又被称为先进后出的线性表,简称“LIFO” 我们这次用数组作为我们栈的底层数据结构,代码会放到结尾供大家参考使用 2.栈顶的定义 栈是一个线性表,我们允许插入…...

Ubuntu开机自启服务systemd.service配置教程(Ubuntu服务)(Linux服务)upstart
文章目录 为什么要将程序配置成服务?1. 自动启动2. 后台运行3. 定时重启4. 简化管理5. 整合系统 版本支持1. Ubuntu 14.04及更早版本:使用upstart作为默认的init系统/etc/rc.local旧版本新版本 2. Ubuntu 15.04到16.04版本:默认使用systemd作…...
大数据课程E4——Flume的Channel
文章作者邮箱:yugongshiye@sina.cn 地址:广东惠州 ▲ 本章节目的 ⚪ 了解Channel的作用和配置; ⚪ 掌握Channel的使用方法; ⚪ 掌握Channel的File Channel; ⚪ 掌握Channel的JDBC Channel; ⚪ 掌握Channel的Spillable Memory Channel; 一、Memory Ch…...
es6中的Map和Set数据结构
Map Map对象可以用于保存键值对 1.创建 一个Map对象 const map new Map() 2.Map的一些方法 set(key,value):通过键值对向Map对象中添加元素get(key):通过建拿到对应的值size:返回Map对象中所包含的键值对的个数has(key):判断Map对象中是否有对应的key,返回一个…...

MyBatis 框架基本的增删改查
提示:写代码要严谨 文章目录 前言前期准备MyBatis CRUD操作流程增加功能删除功能修改功能查询功能#{} 占位符${} 占位符两种占位符的区别❗ 映射文件总结❗ mapper 代理方式实现CRUDmapper代理开发规范增加功能删除功能修改功能查询功能 前言 提示:myba…...
Javascript--JSON
什么是 JSON? JavaScript中的JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,用于存储和表示结构化的数据。JSON使用键值对的方式组织数据,并支持基本数据类型(字符串、数字、布尔值、数组和对象&…...
Rust: error: failed to run custom build command for `openssl-sys v0.9.71`
error: failed to run custom build command for openssl-sys v0.9.71 解决 windows : openssl 不要选Light版 设置环境变量 cmd: set OPENSSL_DIR“C:\Program Files\OpenSSL-Win64” OPENSSL_DIR:C:\Program Files\OpenSSL-Win64 linux:…...

Excel修改日期格式,改变日期的筛选方式
我们有两列日期数据: 左边这一列筛选会显示: 右边这一列筛选会显示: 修改格式,将【日期1】改为【日期2】 将【日期1】的格式修改为文本格式即可 修改格式,将【日期2】改为【日期1】 选中日期2,点击【数据…...

【RabbitMQ(day2)】默认(直连)交换机的应用
文章目录 一、第一种模型(Hello World)二、第二种模型(work queue)自动确认机制的后果和公平分配 三、阐述默认交换机 这篇博客是以下资料学后的总结: 不良人的RabbitMQ的教学视频 官方启动教程 RabbitMQ中文文档 一、…...

谷粒商城第八天-商品服务之品牌管理的整体实现(直接使用逆向生成的代码;含oss文件上传)
目录 一、总述 二、前端部分 2.1 创建好品牌管理菜单 2.2 复制组件 编辑2.3 复制api 编辑 2.4 查看效果 编辑2.5 需要优化的地方 2.6 具体优化实现 2.6.1 优化一:将表格的状态列(这里是是否显示列)修改为开关ÿ…...

阿里云率先荣获容器集群稳定性先进级认证
7 月 25 日,由中国信通院发起的“2023 稳保体系”评估结果在可信云大会现场公布,阿里云容器服务 ACK 成为首批通过“云服务稳定运行能力-容器集群稳定性”评估的产品,并荣获“先进级”认证。 云原生技术正在激活应用构建新范式,构…...
【SpringBoot笔记37】SpringBoot基于@ServerEndpoint、@OnMessage等注解的方式集成WebSocket
这篇文章,主要介绍SpringBoot基于@ServerEndpoint、@OnMessage等注解的方式集成WebSocket。 目录 一、基于注解集成WebSocket 1.1、WebSocket常见注解 1.2、创建WebSocket服务端 1.3、配置ServerEndpointExpor...

PyTorch(安装及卸载)
目录 1. 安装 2. 卸载 参考文献 为什么用PyTorch:简单来说,19年之前tensorflow是大哥,19年tensorflow和PyTorch双龙并行,20年之后PyTorch一往无前。宗旨,哪个用的人多用哪个。 1. 安装 1. 先打开Anaconda Prompt&…...

webScoket
webScoket是什么? 支持端对端通讯可以由客户端发起,也可以有服务端发起用于消息通知、直播间讨论区、聊天室、协同编辑等 做一个简单的webScoket 客户端配置: 1、新建一个页面叫web-scoket.html <!DOCTYPE html> <html lang"…...

【C语言初阶(20)】调试练习题
文章目录 前言实例1实例2 前言 在我们开始调试之前,应该有个明确的思路;程序是如何完成工作的、变量到达某个步骤时的值应该是什么、出现的问题大概会在什么位置。这些东西在调试之前都需要先确认下来,不然自己都不知道自己在调试个什么东西…...

MicroPython ESP32网页实时更新DHT11数据显示
MicroPython ESP32网页实时更新DHT11数据显示 📌相关篇《MicroPython ESP32 读取DHT11温湿度传感器数据》📍《【Micropython esp32/8266】网页点灯控制示例》 ✨本例综合以上两篇文章内容实现:在本地网页中显示DHT11温度传感器数据。可以做到…...

JavaWeb之HTML基础篇(一)
系列文章目录 HTML基础篇(一) 文章目录 系列文章目录HTML基础篇(一)[TOC](文章目录) 前言一、HTML简介1.1介绍1.2HTML文件的书写规范1.3 HTML标签介绍1.4 HTML常见的标签 二、CSS的简介2.1css技术介绍2.2 CSS与HTML结合的三种方式…...
TVM_深度学习编译器
TVM_深度学习编译器 TVM所做的是要比传统compiler更偏上层的,你可以把它理解成source-to-source compiler,需要其他的后端(backend)来生成最后的指令。比如当编译的Target是Intel CPU时,翻译的顺序是Relay IR -> TVM IR/ Halide IR -> LLVM IR,之后交给LLVM生成最后…...
Flutter InheritedWidget 共享状态管理
InheritedWidget和React中的context功能类似,可以实现跨组件数据的传递。 定义一个共享数据的InheritedWidget,需要继承自InheritedWidget 这里定义了一个of方法,该方法通过context开始去查找祖先的HYDataWidget(可以查看源码查找…...
什么是反射?Java反射?反射的优缺点
目录 什么是反射(Reflection )?Java反射?反射的优缺点获取Class对象的三种方式:java反射技术的应用场景 什么是反射(Reflection )? 主要是指程序可以访问、检测和修改它本身状态或行…...

19c补丁后oracle属主变化,导致不能识别磁盘组
补丁后服务器重启,数据库再次无法启动 ORA01017: invalid username/password; logon denied Oracle 19c 在打上 19.23 或以上补丁版本后,存在与用户组权限相关的问题。具体表现为,Oracle 实例的运行用户(oracle)和集…...

Linux 文件类型,目录与路径,文件与目录管理
文件类型 后面的字符表示文件类型标志 普通文件:-(纯文本文件,二进制文件,数据格式文件) 如文本文件、图片、程序文件等。 目录文件:d(directory) 用来存放其他文件或子目录。 设备…...
在鸿蒙HarmonyOS 5中实现抖音风格的点赞功能
下面我将详细介绍如何使用HarmonyOS SDK在HarmonyOS 5中实现类似抖音的点赞功能,包括动画效果、数据同步和交互优化。 1. 基础点赞功能实现 1.1 创建数据模型 // VideoModel.ets export class VideoModel {id: string "";title: string ""…...

无法与IP建立连接,未能下载VSCode服务器
如题,在远程连接服务器的时候突然遇到了这个提示。 查阅了一圈,发现是VSCode版本自动更新惹的祸!!! 在VSCode的帮助->关于这里发现前几天VSCode自动更新了,我的版本号变成了1.100.3 才导致了远程连接出…...

基于Docker Compose部署Java微服务项目
一. 创建根项目 根项目(父项目)主要用于依赖管理 一些需要注意的点: 打包方式需要为 pom<modules>里需要注册子模块不要引入maven的打包插件,否则打包时会出问题 <?xml version"1.0" encoding"UTF-8…...

《基于Apache Flink的流处理》笔记
思维导图 1-3 章 4-7章 8-11 章 参考资料 源码: https://github.com/streaming-with-flink 博客 https://flink.apache.org/bloghttps://www.ververica.com/blog 聚会及会议 https://flink-forward.orghttps://www.meetup.com/topics/apache-flink https://n…...
Angular微前端架构:Module Federation + ngx-build-plus (Webpack)
以下是一个完整的 Angular 微前端示例,其中使用的是 Module Federation 和 npx-build-plus 实现了主应用(Shell)与子应用(Remote)的集成。 🛠️ 项目结构 angular-mf/ ├── shell-app/ # 主应用&…...
【无标题】路径问题的革命性重构:基于二维拓扑收缩色动力学模型的零点隧穿理论
路径问题的革命性重构:基于二维拓扑收缩色动力学模型的零点隧穿理论 一、传统路径模型的根本缺陷 在经典正方形路径问题中(图1): mermaid graph LR A((A)) --- B((B)) B --- C((C)) C --- D((D)) D --- A A -.- C[无直接路径] B -…...
Python竞赛环境搭建全攻略
Python环境搭建竞赛技术文章大纲 竞赛背景与意义 竞赛的目的与价值Python在竞赛中的应用场景环境搭建对竞赛效率的影响 竞赛环境需求分析 常见竞赛类型(算法、数据分析、机器学习等)不同竞赛对Python版本及库的要求硬件与操作系统的兼容性问题 Pyth…...

WebRTC调研
WebRTC是什么,为什么,如何使用 WebRTC有什么优势 WebRTC Architecture Amazon KVS WebRTC 其它厂商WebRTC 海康门禁WebRTC 海康门禁其他界面整理 威视通WebRTC 局域网 Google浏览器 Microsoft Edge 公网 RTSP RTMP NVR ONVIF SIP SRT WebRTC协…...