首页 > 其他分享 >第3章. 栈(Stack)

第3章. 栈(Stack)

时间:2023-12-06 20:36:58浏览次数:23  
标签:return int list public Stack size

栈(Stack)


一、栈的相关概念

  • 栈是一种特殊的线性表,只能在一端进行操作
  • 往栈中添加元素的操作,一般叫做push,入栈。
  • 往栈中移除元素的操作,一般叫做pop,出栈(只能移除栈顶元素,也叫作:弹栈)
  • 先进后出的原则:Last IN FIRST OUT,LIFO。

二、栈的接口设计

  • int size(); // 元素的数量
  • boolean isEmpty(); // 栈是否为空
  • void push(E element); // 入栈
  • E pop(); // 出栈,并获取栈顶元素
  • E top(); // 获取栈顶元素
  • void clear(); // 清空

栈的内部实现可以利用之前学过的数据结构:动态数组、链表(单、双链表)

2.1 方法一:继承之前写的ArrayList、LinkedList
package DataStructure._04栈;
import DataStructure._02链表.LinkedList;
/**
 * @author keyongkang
 * @date 2022-07-22-15:23
 */
public class Stack<E> extends LinkedList<E> {
    public boolean isEmpty() {
        return size == 0; // 这个size在AbstractList类中
    }

    public int size() {
        return size;
    }

    public void push(E element) {
        add(element);
    }

    public E pop() {
        return remove(size - 1);
    }

    public E top() {
        return get(size - 1);
    }
    
    public void clear() {
        clear();
    }
}

但是这种方法有缺点:Stack类中因为继承了ArrayList或LinkedList。所以Stack类还可以使用ArrayList或LinkedList类的其他方法,但这些方法对栈来说是多余的。

2.2 方法二:把Java内置的ArrayList或LinkedList作为Stack的成员变量
动态数组实现栈
package DataStructure._04栈;

import java.util.ArrayList;
import java.util.List;
/**
 * @author keyongkang
 * @date 2022-07-22-15:23
 */
public class Stack<E> {
    
    // 面向接口设计,并且用动态数组实现栈
    private List<E> list = new ArrayList<>();

    // 栈是否为空
    public boolean isEmpty() {
        return list.isEmpty();
    }

    // 元素的数量
    public int size() {
        return list.size();
    }

    // 入栈
    public void push(E element) {
        list.add(element);
    }

    // 出栈,并获取栈顶元素
    public E pop() {
        return list.remove(size() - 1);
    }

    // 获取栈顶元素
    public E top() {
        return list.get(size() - 1);
    }
    
    // 清空栈
    public void clear() {
        list.clear();
    }
}
双向链表实现栈

由于Java中的链表是用双向链表实现的,所以这个用双向链表实现栈

package DataStructure._04栈;

import java.util.LinkedList;
import java.util.List;
/**
 * @author keyongkang
 * @date 2022-07-22-15:23
 */
public class Stack<E> {

    // 面向接口编程,并且用双向链表实现栈
    private List<E> list = new LinkedList<>();

    // 栈是否为空
    public boolean isEmpty() {
        return list.isEmpty();
    }

    // 元素的数量
    public int size() {
        return list.size();
    }

    // 入栈
    public void push(E element) {
        list.add(element);
    }

    // 出栈,并获取栈顶元素
    public E pop() {
        return list.remove(size() - 1);
    }

    // 获取栈顶元素
    public E top() {
        return list.get(size() - 1);
    }
    
    // 清空栈
    public void clear() {
        list.clear();
    }
}

三、Java官方的栈实现

实现方法:

  • class Stack< E > extends Vector< E >

使用:

  • 例如:Stack< Interger > stack = new Stack<>();

常用方法:

  • push(E)
  • pop()
  • peek()
  • empty()

四、栈的应用

4.1 逆波兰表达式求值
4.2 有效括号

思路:

  1. 遇见左字符,将左字符入栈
  2. 遇见右字符
  • 如果栈是空的,说明括号无效
  • 如果栈不为空,将栈顶字符出栈,与右字符匹配
    • 如果左右字符不匹配,说明括号无效
    • 如果左右字符匹配,继续扫描下一个字符
  1. 所有字符扫描完毕
  • 栈为空,说明括号有效
  • 栈不为空,说明括号无效

五、单调栈

单调栈实际上就是栈,只是利用一些巧妙的逻辑,使得每次新元素入栈后,栈内的元素都保持有序(单调递增或单调递减)。

  • 单调递增栈:栈中元素从栈底到栈顶是递增的。
  • 单调递减栈:栈中元素从栈底到栈顶是递减的。

应用场景:

  • 下一个更大元素
  • 上一个更小元素
  • 模板

int[] nextGreaterElement(int[] nums) {
    int len = nums.length;
    int[] res = new int[len];
    Stack<Integer> stack = new Stack<>();
    for (int i = len - 1; i >= 0; i --) { // 倒着往栈里面放
        while (!stack.isEmpty() && stack.top() <= nums[i]) { // 判定个子高矮
            stack.pop(); // 矮个子出列
        }
        res[i] = stack.isEmpty() ? -1 : stack.top(); // 这个元素身后第一个高个
        stack.push(nums[i]); // 进栈,接收之后的身高判定
    }
    return res;
}

标签:return,int,list,public,Stack,size
From: https://www.cnblogs.com/keyongkang/p/17880451.html

相关文章

  • openstack 常用命令
    1.创建一个磁盘cinderlist&&cindertype-list&&glanceimage-listcindercreate--volume-typeISCSI--image-id5c86aff6-2ed6-4b56-a5f2-48ae68b891fc--nametest102.创建一个虚拟机openstacknetworklist&&openstacksecuritygrouplist&&......
  • 基于kvm虚拟机创建openstack qcow2磁盘镜像
    前提知识KVM做单机管理虚拟机,Openstack集群管理虚拟机 使用工具virt-manager 虚拟机管理器(VirtualMachineManager) 目标基于Kylin-Server-V10-SP3-General-Release-2303-X86_64.iso创建qcow2格式的openstack磁盘镜像 qcow2镜像制作使用环境      IP:......
  • Windows上使用Docker搭建ChirpStack私有LoRa服务端
    1.安装docker运行docker,这里就不细说了2.下载ChirpStack项目包ChirpStack提供了一个包含示例DockerCompose配置的存储库,以帮助开始使用ChirpStack,此存储库位于chirpstack-docker:SetupChirpStackusingDockerCompose,克隆项目文件到本地电脑,可以使用以下命令:gitcloneht......
  • 每天5分钟复习OpenStack(十二)Ceph FileStore 和 BlueSotre
    一个最小化的Ceph集群需要三个组件MONMGROSD.上一章我们部署了MON,本章节我们完成剩下MGR和OSD的部署。在文末我们将重点介绍下什么是FileStore和BlueStore,并详细分析其特点,来说明为什么Ceph社区放弃了FileStore,直接采用了BlueStore.1、MGR部署创建mgr工作目录sudo-u......
  • StackGres 数据库平台工程,使用 Citus + Patroni 创建生产级高可用分布式 PostgreSQL
    系列StackGres,可私有部署的云原生数据库平台工程StackGres 数据库平台工程功能介绍与快速上手StackGres1.6数据库平台工程集群配置管理(K8SPods/PostgreSQL/PgBouncer)StackGres1.6数据库平台工程,集群高可用(Patroni3管理)什么是ShardedCluster(分片集群)Sha......
  • uva12096集合栈计算机 The SetStack Computer
    洛谷链接集合栈计算机TheSetStackComputer-洛谷|计算机科学教育新生态(luogu.com.cn)一道典型的以栈为背景的数据结构题。题目简单但是程序却并不简单(个人观点)。普及组的难度有点低了感觉。个人认为这道题目可以帮助自己熟悉或者说更好的掌握STL的使用以及妙用。难点:1......
  • 为什么stack和queue默认使用deque作为底层容器?
    在C++中,stack和queue默认使用deque作为底层容器的原因主要有以下几点:操作效率:deque(双端队列)支持在头尾两端进行插入和删除操作,且时间复杂度都为O(1),非常高效1。而vector在增长到一定长度时为了保证完全连续,需要重新申请更长的内存,并把原来的元素全部拷贝过去2。这使得vector......
  • stack和queue的底层容器封装 以及提供随机存储的容器
    在C++中,std::stack和std::queue是容器适配器,它们提供了特定的接口,依赖于某个容器类(如std::deque或std::list)来处理元素1。std::stack:std::stack默认使用std::deque作为其底层容器2。但是,你也可以在创建std::stack对象时指定其他的底层容器,只要这个容器支持......
  • java 捕获异常Exception 获取异常信息的方法 e.toString() e.getMessage() e.printSta
    Java异常中e.getMessage()和e.toString()e.printStackTrace()的区别e.getMessage():打印异常的原因e.toString():打印异常类型和异常的原因e.printStackTrace():打印完整的异常堆栈信息  总结e.getMessage()和e.toString()方法:打印的异常信息太少,没有具体......
  • dump 日志收集与分析(jmap 和 jstack 工具)讲解与实战操作
    目录一、概述二、常见的dump工具三、dump可能会导致进程卡住风险(生产谨慎操作)四、安装JDK五、jmap介绍与示例讲解1)jmap介绍2)Kafka安装(单机)1、下载安装包2、配置环境变量3、配置kafka3、配置ZooKeeper4、启动kafka5、验证3)示例讲解【示例一】执行jmap命令查看内存使用情况【......