0x11 栈

这篇具有很好参考价值的文章主要介绍了0x11 栈。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

0x11 栈

栈是一种“先进后出”的线性数据结构。栈只有一端能够进出元素,我们一般称这一端为栈顶,另一端为栈底。添加或删除栈中元素时,我们只能将其插入到栈顶(进栈),或者把栈顶元素从栈顶取出(出栈)。

实现一个栈,支持查找栈中最小值的操作,要求时间复杂度为O(1)

我们可以建立两个栈,一个栈A记录原本的数据,另一个栈B储存栈A中以栈底开头的的每段数据最小值,就像下面一样:

A: 9 2 1 5 3 0 2 <—

B: 9 2 1 1 1 0 0 <—

1.表达式计算

栈的一大用途是做算术表达式的计算。算术表达式通常有前缀、中缀、后缀三种表达方式。

中缀表达式,我们最常见的表达式,例如:3 * ( 1 - 2 )。

前缀表达式,又称波兰式,形如“op A B”,其中op是一个运算符,A,B是另外两个前缀表达式。例如:* 3 - 1 2。

后缀表达式,有又称逆波兰式,形如“A B op”,例如:1 2 - 3 *。

前缀和后缀表达式的值的定义是,先递归求出A,B的值,二者再做op运算的结果。这两种表达式不需要使用括号,其运算方案是唯一确定的。对于计算机来说,它最容易理解后缀表达式,我们可以使用栈来 O ( N ) O(N) O(N)地求出它的值。

后缀表达式求法

1.建立一个用于存数的栈,逐一扫描该后缀表达式中的元素。

(1)如果遇到一个数,则把该数入栈。

(2)如果遇到运算符,就取出栈顶的两个数进行运算,然后把结果入栈。

2.扫描完成后,栈中恰好有一个元素,就是该后缀表达式的值。

如果想要计算机求解我们常用的中缀表达式的值,最快的方式就是把中缀表达式转化成后缀表达式,再使用上述方法求值。这个转化过程同样可以使用栈来 O ( n ) O(n) O(n)完成。

中缀表达式转化成后缀表达式

1.建立一个用于存运算符的栈,逐一扫描该中缀表达式中的值。

(1)如果遇到一个数,输出该数。

(2)如果遇到左括号,把左括号入栈。

(3)如果遇到右括号,不断取出栈顶并输出,直到栈顶为左括号,然后把左括号出栈。

(4)如果遇到运算符,只要栈顶符号的优先级大于等于新符号,就不断取出栈顶并输出,最后把新符号入栈。优先级为乘除>加减>左括号。

2.依次取出并输出栈中所有的剩余符号,最终输出的序列就是与原中缀表达式等价的后缀表达式。

当然我们也可以不转化成后缀表达式,而是使用递归法直接求解中缀表达式的值,其时间复杂度为 O ( N 2 ) O(N^2) O(N2)

中缀表达式的递归求法

目标:求解中缀表达式S[1~N]的值

子问题:求解中缀表达式S的子区间表达式S[L~R]的值。

1.在L~R中考虑没有被任何括号包含的运算符:

(1)若存在加减号,选其中最后一个,分成左右两半递归,结果相加减,返回。

(2)若存在乘除号,选其中最后一个,分成左右两半递归,结果相乘除,返回。

2.若不存在没有被任何括号包含的运算符:

(1)若首尾字符是括号,递归求解S[L+1~R-1],把结果返回。

(2)否则,说明区间S[L~R]是一个数,直接返回。

2.单调栈

如下图所示,在一个水平上方有若干个矩形,求包含与这些矩形的并集内部的最大矩形的面积(在下图中,答案就是阴影部分的面积),矩形个数 ≤ 1 0 5 \leq 10^5 105

0x11 栈,# 0x10 基本数据结构,算法,数据结构,c++

如果矩形的高度从左往右递增,我们可以尝试每个矩形的高度作为最终矩形的高度,并把宽度延伸到右边界,得到一个矩形,在所有这样的矩形中取面积的最大值就是答案。如下图所示:

0x11 栈,# 0x10 基本数据结构,算法,数据结构,c++

如果下一个矩形的高度小于上一个矩形的高度,那么该矩形想利用之前的矩形一起构成一块较大的面积时,这块面积的高度就不可能超过该矩形自身的高度。换句话说,在考虑完上图的四种情况后,下图中打叉的那部分面积就没有任何用处了。

0x11 栈,# 0x10 基本数据结构,算法,数据结构,c++

既然没有用,就把这些比该矩形高的矩形都删掉,用一个宽度累加、高度为该矩形自身高度的新矩形(就是上图的阴影部分)来代替。这样不会对后续的计算产生任何影响。于是我们维护的轮廓就变成了一个高度始终单调递增的矩形序列

详细来说,我们建立一个栈,用来保存若干个矩形,这些矩形的高度是单调递增的,我们从左往右依次扫描每个矩形:

如果矩形比当前栈顶矩形高,直接入栈。

否则不断取出栈顶,直到栈为空或者栈顶矩形的高度比当前矩形小。在出栈过程中,我们累计被弹出的矩形宽度之和,并且每弹出一个矩形,就用它的高度乘上累计的宽度去更新答案。整个出栈过程结束,我们把一个高度为当前高度、宽度为累计宽度的新矩形入栈。

整个扫描结束,我们把栈中的剩余矩形依次弹出,按照与上面相同的方法更新答案。为了简化程序我们也可以增加一个高度为0的矩形a[n+1],以避免在扫描结束后栈中有剩余矩形。

long long ans=0;
int p=0;
a[n+1]=s[p]=0;
for(int i=1;i<=n+1;++i)
{
    if(a[i]>=s[p])
        s[++p]=a[i],w[p]=1;
    else
    {
        int width=0;
        while(s[p]>a[i])
        {
            width+=w[p];
            ans=max(ans,(long long)width*s[p]);
            --p;
        }
        s[++p]=a[i],w[p]=width+1;
    }
}

这就是著名的单调栈算法,时间复杂度为 O ( n ) O(n) O(n)。借助单调性处理问题的思想在于及时排除不可能的选项,保持策略集合的高度有效性和秩序性,从而为我们做出决策提供更多的条件和可能方法。

实际应用:寻找到数组中一个数上一个或下一个更大数或更小数的位置。一个序列通过单调栈,我们可以找到序列中数A前面小于它的第一个数B。改成递减排列,也可以找到序列中数A前面大于它的第一个数B。也可以通过反向输入序列,找到序列中数A后面大于或小于它的第一个数B。文章来源地址https://www.toymoban.com/news/detail-758931.html

到了这里,关于0x11 栈的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 如何修复 Windows 11/10上的 0x8007023e Windows 更新错误

    系统更新根据 Windows 质量更新服务节奏发布到 Windows 设备。如果当您尝试在 Windows 11 或Windows 10 电脑上安装更新时,Windows 更新未能安装,错误代码为 0x8007023e,则本文旨在帮助您找到有效的解决方案,以修复错误。 如果您在 Windows 11/10 设备上安装每月更新时遇到 Windows Updat

    2024年02月07日
    浏览(62)
  • C++11 数据结构0 什么是 “数据结构“?数据,数据对象,数据元素,数据项 概念。算法的基本概念 和 算法的度量,大O表示法,空间换时间的代码

    是能输入计算机且能被计算机处理的各种符号的集合。 数值型的数据:整数和实数。 非数值型的数据:文字、图像、图形、声音等。         性质相同的 \\\"数据元素\\\" 的集合         例如一个 int arr[10],  Teacher tea[3]; 数据元素:          tea[0],tea[1],arr[2],这些都是 数据项:

    2024年04月15日
    浏览(40)
  • 示波器探头x10、x1挡位

    1、x1 信号没有经过衰减进入示波器 2、x10 信号衰减10倍进入示波器 表示示波器读出来的数要x10,如果此时示波器也可以设置为x10档,直接读数即可 。 读数方法 设示波器里面设置x a,探头x b,那么最终读数放大a/b倍就好了。比如最常用的设置,示波器里面x10,探头x10。最终读

    2024年02月11日
    浏览(31)
  • win10/win11家庭版解压缩时,出现错误代码0x80004005的解决办法

    当时解压缩的时候出现错误代码0x80004005。 就急吼吼的直接百度错误代码了。试了很多方法,什么用cmd键入“regsvr32 softpub.dll”、“regsvr32 wintrust.dll”和“regsvr32 initpki.dll” 这些的 什么弄注册表的。 全试了个遍,都没有什么卵用。 还有的说什么家庭策略组,真是服了,都特么

    2024年02月11日
    浏览(61)
  • 程序员提效 x10 的必备开源“神器”

    工欲善其事,必先利其器。我们每个人的电脑中都会有一些爱不释手的工具软件。 转Linux 桌面2年了,期间尝试过各种各样“神奇”的开源工具,作为一个开源软件爱好者,这里给大家推荐几个这些年工作、学习、生活中常用、跨平台、免费的开源”神器”~ rime 输入法框架

    2024年04月14日
    浏览(43)
  • 荣耀x10从鸿蒙3.0退回到旧版本MagicUI

    看到之前用的手机荣耀x10,放着吃灰怪可惜,不如装游戏偶尔玩下,本以为很简单事情 ,不出意外的出意外了。 手机自带应用市场没找到要用的九游app,从官网下载后安装,结果提示需要登录华为账号,之后才能安装第三方应用。以前用手机时账号都是登录着的,所以没发

    2024年02月20日
    浏览(30)
  • mac X11 XQuartz的安装与使用

    本地系统:MacOS 12.4 远程主机系统:Ubuntu 18.04 命令说明 ssh命令 ssh 命令大家很熟悉了,这里仅介绍与 X11 forwarding 相关的几个选项。 本部分译自 ssh 命令手册,可见 man ssh -X :打开 X11 forwarding。也可以通过在 configuration 文件中对每个 host 单独进行设置。 应谨慎启用 X11 forwardi

    2024年02月04日
    浏览(32)
  • Ubuntu X11VNC 远程桌面安装与使用

    通过下载安装VNC实现,远程操控Linux系统,详细安装步骤如下: 1.控制端 需下载VNC Viewer,官网地址为:Download VNC Viewer | VNC® Connect 1.1Windows选择如下: 下载完成后双击安装。 之后全部默认选择下一步,完成安装。 点击搜索栏,输入vnc ,打开vnc viewer 选择不登录进入 此时等待

    2024年02月15日
    浏览(35)
  • Ubuntu22.04修改默认窗口系统为X11

    Ubuntu22.04安装默认窗口系统为Wayland(通过设置-关于可以看到)。 用户登录时,点“未列出”,输入用户名后,在登录界面底部的齿轮图标中,选择 \\\"Ubuntu on Xorg\\\" 作为会话类型登录,系统将为当前会话使用 Xorg。如果每次手动选择 Xorg 登录,系统应该记住选择,并在下次登录时

    2024年04月12日
    浏览(25)
  • 通过X11获取屏幕截图并转为opencv Mat

    #include bits/stdc++.h #include \\\"opencv2/core.hpp\\\" #include \\\"opencv2/highgui.hpp\\\" #include \\\"opencv2/opencv.hpp\\\" #include \\\"opencv2/videoio.hpp\\\" #include X11/Xlib.h //-lX11 #include X11/Xutil.h #include X11/Xmd.h #include X11/Xatom.h using namespace std; using namespace cv; Mat getScreenShot() {     Display *dis=XOpenDisplay((char *)0);     Screen *scr = X

    2024年02月15日
    浏览(31)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包