一起学算法(栈篇)
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 )? 主要是指程序可以访问、检测和修改它本身状态或行…...

小红书2020校招测试开发后端笔试题卷三
//完全背包求组合数 #include <iostream> #include<vector> #include<set> #include<map> #include<algorithm> using namespace std; int value[300]; // vector<int>vis; // vector<int>vis1; map<vector<int>,int>m…...

python数据可视化Matplotlib
1.绘制简单的折线图 # -*- coding: utf-8 -*- import matplotlib.pyplot as pltinput_values [1, 2, 3, 4, 5] squares [1, 4, 9, 16, 25] plt.style.use(seaborn) fig, ax plt.subplots() ax.plot(input_values, squares, linewidth3) # 线条粗细# 设置图表标题并给坐标…...

firewalld防火墙
firewalld防火墙 它属于包过滤防火墙。工作在网络层,是centos7自带的默认防火墙。主要是取代iptables。 firewalld的两种配置模式: 分别是运行时配置和永久配置。 iptable是静态防火墙 firewalld是动态防火墙 它是按照区域来划分的,有9…...

iMacros WebBrowser Component for .NET
iMacros WebBrowser Component for .NET 在几分钟内实现应用程序自动化 快速轻松地将iMacro集成到您的应用程序中。不需要单独的安装程序。 无缝集成 iMacros与您的.NET应用程序无缝集成,作为Microsoft WebBrowser控件的替代品。它甚至可以用作每个.NET应用程序中的…...

3,堆,桶排序,排序总结【p4-p5】
桶排序,排序总结 3.1堆3.1.1堆结构3.1.1.1完全二叉树3.1.1.2堆分为大根堆和小根堆3.1.1.2.1案例1-去掉最大数字,使剩下的数字依然是大根堆3.1.1.2.2案例23.1.1.2.3案例33.1.1.2.4案例4-方便制造大根堆方法 3.1.2堆排序3.1.2.1案例-堆排序的扩展3.1.2.1.1…...

使用langchain与你自己的数据对话(四):问答(question answering)
之前我已经完成了使用langchain与你自己的数据对话的前三篇博客,还没有阅读这三篇博客的朋友可以先阅读一下: 使用langchain与你自己的数据对话(一):文档加载与切割使用langchain与你自己的数据对话(二):向量存储与嵌入使用langc…...

如何快速开拓海外华人市场?附解决方案!
开拓华人市场对于企业来说是非常必要的。华人市场庞大且潜力巨大,拥有巨额的消费能力。随着华人经济的不断增长,越来越多的企业开始意识到华人市场的重要性。 通过开拓华人市场,企业可以获得更多的销售机会,并且在竞争激烈的市场…...

【云原生-制品管理】制品管理的优势
制品介绍制品管理-DevOps制品管理优势总结 制品介绍 制品管理指的是存储、版本控制和跟踪在软件开发过程中产生的二进制文件或“制品”的过程。这些制品可以包括编译后的源代码、库和文档,包括操作包、NPM 和 Maven 包(或像 Docker 这样的容器镜像&…...

Java爬虫----HttpClient方式(获取数据篇)
目录 一、爬虫的定义 二、获取数据 (1)基于Get方式的请求(无参) (2)基于Get方式请求(有参) (3)基于Post方式的请求(无参) &…...

计算机视觉实验:图像增强应用实践
本次实验主要从基于统计、函数映射的图像增强方法和基于滤波的图像增强方法两种方法中对一些图像增强的算法进行实现。主要的编程语言为python,调用了python自带的PIL图像库用于读取图像,利用numpy进行图像运算,最后使用opencv第三方库进行对…...