Leetcoder Day9|栈与队列part01

news2024/9/22 19:40:51

语言:Java/C++ 

目录

理论基础

C++

队列

Java

队列

​编辑

232.用栈实现队列

225. 用队列实现栈

Queue

Deque

今日心得


理论基础

又是考研时数据结构里接触到的老朋友,栈是先进后出,队列是先进先出。

C++

现在刷题除了思路还要重点关注程序语言中的细节,卡哥给了C++中栈需要注意的一些问题:

  1. C++中stack 是容器么?
  2. 我们使用的stack是属于哪个版本的STL?
  3. 我们使用的STL中stack是如何实现的?
  4. stack 提供迭代器来遍历stack空间么?

栈和队列是STL(C++标准库)里面的两个数据结构,目前常用的C++中的STL有以下三种:

  1. HP STL 其他版本的C++ STL,一般是以HP STL为蓝本实现出来的,HP STL是C++ STL的第一个实现版本,而且开放源代码。
  2. P.J.Plauger STL 由P.J.Plauger参照HP STL实现出来的,被Visual C++编译器所采用,不是开源的。
  3. SGI STL 由Silicon Graphics Computer Systems公司参照HP STL实现,被Linux的C++编译器GCC所采用,SGI STL是开源软件,源码可读性甚高。

提供push 和 pop 等接口

所有元素必须符合先进后出(FILO)规则

栈不提供走访功能,也不提供迭代器(iterator)

因此C++中的栈是以底层容器完成其所有的工作,对外提供统一的接口,底层容器是可插拔的(也就是说可以控制使用哪种容器来实现栈的功能)
所以 STL中栈往往不被归类为容器,而被归类为container adapter(容器适配器)。

从上图可见,栈的底层实现可以是vector,deque,list 都是可以的, 主要就是数组和链表的底层实现。常用的SGI STL,如果没有指定底层实现,默认是以deque为缺省情况下的底层结构。deque是一个双向队列,实现栈时,只要封住一段,只开通另一端就可以了。

也可以指定vector为栈的底层实现,初始化语句如下:

std::stack<int, std::vector<int> > third;  // 使用vector为底层容器的栈
队列

队列为先进先出(FIFO),同样不允许有遍历行为,不提供迭代器, SGI STL中队列一样是以deque为缺省情况下的底部结构。也不被归类为容器,而被归类为container adapter( 容器适配器)。

也可以指定 list 为起底层实现,初始化queue的语句如下:
std::queue<int, std::list<int>> third; // 定义以list为底层容器的队列

Java

栈的底层实现有两种:

  1. 基于数组的实现:顺序栈(ArrayList)
  2. 基于链表的实现:链式栈(LinkedList)

栈的基本操作包括入栈(push),即将元素添加到栈顶;出栈(pop),即将栈顶元素移除;以及访问栈顶元素(peek)

// 基于数组实现链表
public class Stack<E> {
    private E[] elementData; // 栈中的元素
    private int size; // 当前栈中元素个数
 
    public Stack() {
        elementData = (E[]) new Object[10]; // 默认长度为10
    }
 
    public Stack(int initCap) {
        elementData = (E[]) new Object[initCap]; // 初始长度
    }
 
    // 入栈
    public void push(E value) {
        // 扩容
        if(size == elementData.length) {
            int oldLength = elementData.length;
            int newLength = oldLength << 1;
            elementData = Arrays.copyOf(elementData, newLength);
        }
        // 在数组尾部添加元素
        elementData[size++] = value;
    }
 
    // 出栈,返回原来的栈顶元素
    public E pop () {
        if(getSize() == 0) {
            throw new NoSuchElementException("栈中没有元素!");
        }
        // 得到原来的栈顶元素位置
        E oldVaule = elementData[size - 1];
        size--;
        elementData[size] = null;
        return oldVaule;
    }
 
    // 查看栈顶元素
    public E peek() {
        if(getSize() == 0) {
            throw new NoSuchElementException("栈中没有元素!");
        }
        return elementData[size - 1];
    }
 
    // 获取当前栈的长度
    public int getSize() {
        return size;
    }
 
    @Override
    public String toString() {
        StringBuilder stringBuilder = new StringBuilder();
        stringBuilder.append("[");
        for (int i = 0; i < size; i++) {
            stringBuilder.append(elementData[i]);
            if(i != size - 1) {
                stringBuilder.append(",");
            }
        }
        stringBuilder.append("]");
        return stringBuilder.toString();
    }
}
队列

队列是一种仅支持在表尾进行插入操作、在表头进行删除操作的线性表,插入端称为队尾,删除端称为队首。

队列和栈相同也是可以使用数组和链表实现,但是对于队列来说使用链表的结构效率更高

/**
 * 基于链表的队列
 */
public class LinkedQueue{
    private Node head;
    private Node tail;
    private int size;
    private class Node {
        private int data;
        private Node next;
 
        public Node(int data) {
            this.data = data;
        }
    }
 
    // 入队
    public void offer(int value) {
        Node node = new Node(value);
        if(head == null) {
            head = tail = node;
        } else {
            tail.next = node;
            tail = node;
        }
        size++;
    }
 
    // 出队(队首元素出队)
    public int poll() {
        if(size == 0) {
            throw new NoSuchElementException("对列为空!");
        } else {
            int oldValue = head.data;
            Node tempHead = head;
            head = head.next;
            tempHead.next = null;
            size--;
            return oldValue;
        }
    }
 
    // 查看队首元素
    public int peek() {
        if(size == 0) {
            throw new NoSuchElementException("对列为空!");
        }
        return head.data;
    }
 
    public String toString() {
        StringBuilder stringBuilder = new StringBuilder();
        stringBuilder.append("front[");
        Node node = head;
        while (node != null) {
            stringBuilder.append(node.data);
            if(node.next != null) {
                stringBuilder.append(",");
            }
            node = node.next;
        }
        stringBuilder.append("]tail");
        return stringBuilder.toString();
    }
}
这里还要列出一下队列中Queue和Deque的基本操作:
Queue:
Queue的6个方法:

压入元素(添加):add()、offer()
相同:未超出容量,从队尾压入元素,返回压入的那个元素。
区别:在超出容量时,add()方法会对抛出异常,offer()返回false

弹出元素(删除):remove()、poll()
相同:容量大于0的时候,删除并返回队头被删除的那个元素。
区别:在容量为0的时候,remove()会抛出异常,poll()返回false

获取队头元素(不删除):element()、peek()
相同:容量大于0的时候,都返回队头元素。但是不删除。
区别:容量为0的时候,element()会抛出异常,peek()返回null。

普通队列(Queue)是指实现了先进先出的基本队列,例如 ArrayBlockingQueue 和 LinkedBlockingQueue,其中

ArrayBlockingQueue是用数组实现的普通队列,如下图所示

 LinkedBlockingQueue 是使用链表实现的普通队列,如下图所示:

⚠️一般情况下 offer() 和 poll() 方法配合使用,put() 和 take() 阻塞方法配合使用,add() 和 remove() 方法配合使用。程序中常用的是 offer() 和 poll() 方法,这两个方法比较友好,不会报错。

Deque(双端队列):

双端队列(Deque)是指队列的头部和尾部都可以同时入队和出队的数据结构,如下图所示:


​​​​​​​
232.用栈实现队列

使用栈实现队列的下列操作:

push(x) -- 将一个元素放入队列的尾部。
pop() -- 从队列首部移除元素。
peek() -- 返回队列首部的元素。
empty() -- 返回队列是否为空。

说明:

  • 你只能使用标准的栈操作 -- 也就是只有 push to top, peek/pop from top, size, 和 is empty 操作是合法的。
  • 你所使用的语言也许不支持栈。你可以使用 list 或者 deque(双端队列)来模拟一个栈,只要是标准的栈操作即可。
  • 假设所有操作都是有效的 (例如,一个空的队列不会调用 pop 或者 peek 操作)。
这道题首先就是捋清栈和队列的区别,栈的所有操作只能从栈顶进行,如进去的顺序是1、2、3、4,出去的顺序是4、3、2、1,而队列是队尾进,队首出,进和出的顺序是一样的,因此不难看出,我们需要两个栈来实现队列,一个将1、2、3、4压入栈中再逐一弹出,弹出顺序为4、3、2、1再进入另一个栈中,再次弹出,顺序就是1、2、3、4了。这个是整体的一个思路,但是如果涉及到出栈,判空等操作,需要更加注意细节。而peek本质上和pop是一样的。
class MyQueue {

    Stack<Integer> stackIn;
    Stack<Integer> stackOut;

    //initialize
    public MyQueue() {
        stackIn=new Stack<>();  //输入栈
        stackOut=new Stack<>(); //输出栈
    }
    // 如果stackOut为空,那么将stackIn中的元素全部放入stackOut中
    private void dumpStackIn(){
        if(!stackOut.isEmpty()) return;
        while(!stackIn.isEmpty()){
            stackOut.push(stackIn.pop());
        }
    }

    public void push(int x) {
        stackIn.push(x);  //将元素放入输入栈
    }
    
    public int pop() {
        dumpStackIn();
        return stackOut.pop();

    }
    
    public int peek() {
        dumpStackIn();
        return stackOut.peek();
    }
    
    public boolean empty() {
        return stackIn.isEmpty() && stackOut.isEmpty();

    }
}

/**
 * Your MyQueue object will be instantiated and called as such:
 * MyQueue obj = new MyQueue();
 * obj.push(x);
 * int param_2 = obj.pop();
 * int param_3 = obj.peek();
 * boolean param_4 = obj.empty();
 */

225. 用队列实现栈

使用队列实现栈的下列操作:

  • push(x) -- 元素 x 入栈
  • pop() -- 移除栈顶元素
  • top() -- 获取栈顶元素
  • empty() -- 返回栈是否为空

注意:

  • 你只能使用队列的基本操作-- 也就是 push to back, peek/pop from front, size, 和 is empty 这些操作是合法的。
  • 你所使用的语言也许不支持队列。 你可以使用 list 或者 deque(双端队列)来模拟一个队列 , 只要是标准的队列操作即可。
  • 你可以假设所有操作都是有效的(例如, 对一个空的栈不会调用 pop 或者 top 操作)。

在理论基础中,有涉及到了Java中队列的两种类型,Queue和Deque。其实队列的形式有很多,常见的有8种,这是其中最常使用的两种。因为知道了双端队列的技巧,所以用队列实现栈很容易就想到了使用双端队列,从一头进和出队列即可。用普通的队列亦可实现:如将1、2、3、4入队,将除了4以外的其他元素弹出并再次入队,弹出4,即可实现pop操作。

Queue

class MyStack {
    
    Queue<Integer> queue;
    public MyStack() {
        queue=new LinkedList<>();
    }
    private void rePush(){
        int size=queue.size();
        while(size-->1)
        {
            queue.offer(queue.poll());//把前size-1个重新入队,同时size--
        }

    }
    public void push(int x) {
        queue.offer(x);
        rePush(); //将队列中的前n-1个元素弹出并放回队列
    }
    
    public int pop() {
        return queue.poll();
    }
    public int top() {
        return queue.peek();
    }
    
    public boolean empty() {
        return queue.isEmpty();

    }
}
  • 时间复杂度: pop为O(n),其他为O(1)
  • 空间复杂度: O(n)

我在第一次写的时候,在push中使用了一次rePush操作,又在top中使用了一次,导致进行了两次重入队,输出错误,要记住如果在push里已经放入并重新入队,其他操作里就不需要了。

Deque

class MyStack {
    
    Deque<Integer> deque;
    public MyStack() {
        deque=new ArrayDeque<>();
    }

    public void push(int x) {
        deque.offerLast(x);
    }
    
    public int pop() {
        return deque.pollLast();
    }
    public int top() {
        return deque.peekLast();
    }
    
    public boolean empty() {
        return deque.isEmpty();

    }
}

今日心得

使用栈和队列时,一定也要关注底层实现,并且要熟悉基本操作。

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

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

相关文章

【算法与数据结构】494、LeetCode目标和

文章目录 一、题目二、解法三、完整代码 所有的LeetCode题解索引&#xff0c;可以看这篇文章——【算法和数据结构】LeetCode题解。 一、题目 二、解法 思路分析&#xff1a;本题和这道题【算法与数据结构】1049、LeetCode 最后一块石头的重量 II类似&#xff0c;同样可以转换成…

Windows系统使用手册

点击前往查看&#x1f517;我的博客文章目录 Windows系统使用手册 文章目录 Windows系统使用手册Windows10解决大小核调度问题Windows系统安装软件Windows系统Typora快捷键Windows系统压缩包方式安装redisWindows安装dockerWindows系统的docker设置阿里源Windows系统下使用doc…

JAVA正则表达式第二个作用:爬取

目录 本地数据爬取&#xff1a; 本地爬取练习&#xff1a; 网络爬取&#xff1a; ----- 以下为均本地数据爬取&#xff1a; 带条件爬取 贪婪爬取和非贪婪爬取&#xff1a; 例题 1&#xff1a;使获取 1 为不贪婪 *例题 2&#xff1a;使获取 0、1 都为不贪婪 之前介绍了正…

mp4文件可以转成mp3音频吗

现在是个非常流行刷短视频一个年代&#xff0c;刷短视似乎成了人们休闲娱乐的一种方式&#xff0c;在日常刷短视频过程中&#xff0c;肯定会有很多同学被短视频 bgm 神曲洗脑&#xff0c;比如很多被网红翻唱带火的歌曲&#xff0c;例如其中"不负人间”&#xff0c;就是其中…

从零开始,自己搭建一个autonomous mobile robot做gazebo仿真(1):mobile robot建模与添加差速控制器

这样一个简单的mobile robot模型 首先写xacro文件&#xff0c;创建 link joint transmission <?xml version"1.0"?> <robot xmlns:xacro"http://www.ros.org/wiki/xacro" name"whill_modelc" ><xacro:property name"PI&q…

Unity导出Android项目踩坑记录

导出的时候需要注意以下地方的配置&#xff1a; 1、buildSetting-> 设置ExportProject 2、buildsetting ->playerSetting ->设置IL2CPP 3、设置ndk edit->preferences->external tools->ndk 如果unity的ndk版本和android项目里的ndk版本不一致会报错&…

尝试着在Stable Diffusion里边使用SadTalker进行数字人制作

首先需要标明的是&#xff0c;我这里是图片说话类型&#xff0c;而且是看了知识星球AI破局俱乐部大航海数字人手册进行操作的。写下这篇文章是防止我以后遗忘。 我使用的基础软件是Stable Diffusion&#xff0c;SadTalker是作为插件放进来的&#xff0c;需要注意的是这对自己的…

Swagger + Knife4j 接口文档的整合

Swagger 接口文档的整合&#xff1a; 引入依赖&#xff08;Swagger 或 Knife4j&#xff09;。自定义 Swagger 配置类。定义需要生成接口文档的代码位置&#xff08;Controller&#xff09;。注意&#xff1a;线上环境不要把接口暴露出去&#xff01;&#xff01;&#xff01;可…

统计学-R语言-6.1

文章目录 前言参数估计的原理总体、样本和统计量点估计区间估计评价估计量的标准有效性 总体均值的区间估计一个总体均值的估计&#xff08;大样本&#xff09;一个总体均值的估计&#xff08;小样本估计&#xff09; 练习 前言 本篇文章将开始介绍参数估计的相关知识。 参数估…

【超实用】用Python语言实现定时任务的八个方法,建议收藏!

在日常工作中,我们常常会用到需要周期性执行的任务,一种方式是采用 Linux 系统自带的 crond 结合命令行实现。另外一种方式是直接使用Python。接下来整理的是常见的Python定时任务的八种实现方式。 利用while True: + sleep()实现定时任务 位于 time 模块中的 sleep(secs) 函…

【ARM Cortex-M 系列 1.1 -- Cortex-M33 与 M4 差异 详细介绍】

请阅读【嵌入式开发学习必备专栏 之 Cortex-Mx 专栏】 文章目录 背景Cortex-M33 与 M4 差异Cortex-M33Cortex-M4关系和差异举例说明 背景 在移植 RT-Thread 到 瑞萨RA4M2&#xff08;Cortex-M33&#xff09;上时&#xff0c;遇到了hardfault 问题&#xff0c;最后使用了Cortex…

物理层网路设备

目录 一、物理层网络设备-中继器 二、物理层网络设备-集线器 三、在物理层扩展局域网 一、物理层网络设备-中继器 中继器的介绍&#xff1a; 线路上传输的信号功率由于存在损耗会逐渐衰减&#xff0c;衰减到一定程度时信号失真会导致接收错误。中继器就是为解决这一问题而…

小埋公司的IPO方案的题解

目录 原题描述&#xff1a; 题目描述 输入格式 输出格式 输出格式 样例 #1 样例输入 #1 样例输出 #1 样例 #2 样例输入 #2 样例输出 #2 提示 题目大意&#xff1a; 主要思路&#xff1a; 但是but 代码code&#xff1a; 时间限制: 500ms 空间限制: 65536kB 原题…

Wayfair 开启2024年的裁员模式

周五的时候 Wayfair 的 CEO 公开信中表示&#xff0c;将削减 1650 个工作岗位。 通篇读下来的意思就是公司目前还是非常健康的状态&#xff0c;新冠导致的在线购物激增让 Wayfair 在短时间内的销售从 90 亿美元增加到 180 亿美元。 几乎是翻倍了&#xff0c;而且这个让 Wayfai…

Unity vs Godot :哪个游戏引擎更适合你?

Unity vs Godot &#xff1a;哪个游戏引擎更适合你&#xff1f; 游戏引擎的选择对开发过程和最终产品质量有着重大影响。近年来&#xff0c;Godot和Unity这两款引擎受到广泛关注。本文将从多个维度对两者进行比较&#xff0c;以期为开发者提供正确的选择建议。 Godot和Unity都有…

[Error]连接iPhone调试时提示Failed to prepare the device for development.

环境&#xff1a; iPhone 7 Plus iOS 15.8 Xcode14.2 问题&#xff1a; 连接iPhone设备运行时&#xff0c;设备旁提示如下文案。 Failed to prepare the device for development. 这时强行点击运行按钮&#xff0c;会弹窗提示如下文案。 The run destination ZDMiPhone is n…

分类预测 | Matlab实现WOA(海象)-XGboost分类【24年新算法】基于海象优化算法(WOA)优化XGBoost的数据分类预测

分类预测 | Matlab实现WOA(海象)-XGboost分类【24年新算法】基于海象优化算法(WOA)优化XGBoost的数据分类预测 目录 分类预测 | Matlab实现WOA(海象)-XGboost分类【24年新算法】基于海象优化算法(WOA)优化XGBoost的数据分类预测分类效果基本描述程序设计参考资料 分类效果 基本…

第一篇【传奇开心果系列】beeware开发移动应用:轮盘抽奖移动应用

系列博文目录 beeware开发移动应用示例系列博文目录一、项目目标二、开发传奇开心果轮盘抽奖安卓应用编程思路三、传奇开心果轮盘抽奖安卓应用示例代码四、补充抽奖逻辑实现五、开发传奇开心果轮盘抽奖苹果手机应用编程思路六、开发传奇开心果轮盘抽奖苹果手机应用示例代码七、…

B站提示:“当前浏览器版本较低……”可行的解决方案(edge浏览器)

文章目录 问题研究和分析使用User-Agent Switcher for Chrome插件的解决方法使用userAgent switcher的解决方法 问题研究和分析 问题&#xff1a;使用最新版浏览器访问B站&#xff0c;首页总是有一条横幅提示&#xff1a;当前浏览器版本较低&#xff0c;为保证您的使用体验&am…

怎么用小程序将身份证转为结构化Excel?

随着科技的不断发展&#xff0c;我们的生活变得越来越智能化。现在&#xff0c;我们可以使用金鸣表格文字识别小程序来识别身份证并转为结构化的excel&#xff0c;并且可自动核对真伪&#xff0c;保留头像。金鸣表格文字识别小程序是一种基于人工智能技术的应用程序&#xff0c…