STL大全
排序最速传说——sort
我们都学过一些排序的写法,比如冒泡排序,快速排序之类的东西,举个例子来说吧,这是快速排序的代码:
#include<iostream>
using namespace std;
int a[100001];
void quicksort(int l,int r)
{
int i=l,j=r;
int mid=a[(l+r)/2];
do
{
while(a[i]<mid) i++;
while(a[j]>mid) j--;
if(i<=j)
{
swap(a[i],a[j]);
i++;j--;
}
}while(i<=j);
if(l<j) quicksort(l,j);
if(r>i) quicksort(i,r);
}
int main()
{
int arr=0;
int n;
cin>>n;
for(int i=1;i<=n;++i)
cin>>a[i];
quicksort(1,n);
for(int i=1;i<=n;++i)
{
arr++;
if(arr==1) cout<<a[i];
else cout<<" "<<a[i];
}
return 0;
}
而这个操作,sort只要一行
sort(a+1,a+1+n);
a是要排序的数组的名称,+1的意思是从下标为1的开始,+n+1的含义是从1到n。然后a数组中1-n的元素都被排序好了。
sort默认是从小到大排序,但是如果你想让他从大到小排序的话也可以,只需要这样做
int bool cmp(int a,int b)
{
return a>b;
}
sort(a+1,a+n+1,cmp);
同理你也可以在cmp中进行其他的修改,让他可以对结构体进行排序。
为什么说是最速传说?据说这东西吸了氧谁都比不过。
“超级数组”map
map可以对两个元素形成映射关系,先来看他的定义、
map<int,int>mp;
map后面的尖括号里面的两个分别表示下标和存储数据的类型(如果当一个数组来用的话),也就是说,用这个当数组,甚至可以用字符串当下标,当然只有这一点是不足以让他成为超级数组的,正常情况下,开1e9的数组是肯定会爆的,但是,我们的map他没存储东西的数组是不占空间的,所以能完成下面的操作:
#include<bits/stdc++.h>
#define int long long
using namespace std;
signed main()
{
map<int,int>mp;
mp[1000100000]=114514;
cout<<mp[1000100000]<<endl;
return 0;
}
运行结果:

所以他才被成为超级数组。
但是这个东西有一个很大的缺陷就是在数据很多的时候跑的很慢,所以能用普通数组解决的问题不会用map。
最后提一嘴:unordered_map和map的区别的话,map里面是用hash映射,前者不会排序,所以在效率上要高于普通的map。
精简结构体——pair
pair这个东西我不常用,因为一般pair能干的结构体也可以做,但还是有必要了解一下的。
pair可以存放两个元素,使用的时候直接调用,调用下面再说
先来看一下定义
pair<int,int>p;
看到这个是不是有点眼熟?像极了map,pair的尖括号里面分别表示存放的两个数据的类型
调用的时候也是非常的方便
int p1=p.first;
int p2=p.second;
这样就可以分别调用p存放的两个数据了。
在定义pair的时候,如果觉得一直pair<int,int>太麻烦了,你可以用自带的一个函数,
make_pair(1,1);
我并不觉得很方便,我一般不用。
队列
给你一个左右开口的容器,左进右出,可以知道先进去的一定先出来,所以可以用他的一些性质来实现一些操作,比如bfs就需要用到队列。
手写队列比较麻烦,这里贴一下代码自行体会
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=1e5+10,maxn2=31*maxn;
int q[maxn];
int hh,tt;
int main()
{
int m;
cin>>m;
hh=1;
tt=0;
while(m--)
{
char op[11];
cin>>op;
if(!strcmp(op,"push"))
{
int x;
cin>>x;
q[++tt]=x;
}
else if(!strcmp(op,"pop"))
{
hh++;
}
else if(!strcmp(op,"empty"))
{
if(hh<=tt)
cout<<"NO"<<endl;
else
cout<<"YES"<<endl;
}
else if(!strcmp(op,"query"))
{
cout<<q[hh]<<endl;
}
}
}
当然一般情况下我们都不用这么麻烦因为c++有个自带的STL函数叫queue,直接把队列的相关操作打包好了,用这个东西需要 #include <queue> ,但是我习惯用万能头,下面是关于queue的几个常用操作
q.back()返回最后一个元素
q.empty()如果队列空则返回真
q.front()返回第一个元素
q.pop()删除第一个元素
q.push()在末尾加入一个元素
q.size()返回队列中元素的个数
当然还有其他的用法,并且有很多地方可以用这个来节省一些时间,但这不是这篇文章的重点。
栈
栈就是一个只有上面有开口的容器,进来出去都只能用这一个口,容易发现最后进去的反而会最先出来,然后我们就可以利用这个东西来进行一些操作比如关于后缀表达式之类的问题。
中缀表达式
就是最常见的我们日常使用的表达式,比如:\(1+(2+3)\times 4-5\).
中缀表达式是一种通用的算术或逻辑公式表示方法,操作符以中缀形式处于操作数的中间。中缀表达式是人们常用的算术表示方法。
虽然人的大脑很容易理解与分析中缀表达式,但对计算机来说中缀表达式却是很复杂的,因此计算表达式的值时,通常需要先将中缀表达式转换为前缀或后缀表达式,然后再进行求值。对计算机来说,计算前缀或后缀表达式的值非常简单。
前缀表达式
前缀表达式的运算符位于两个相应操作数之前,前缀表达式又被称为前缀记法或波兰式。
像上面的式子由中缀转成前缀就是:\(- + 1 \times + 2 3 4 5\)
或许加个括号更好理解他的运算顺序:\((- (+ 1( \times (+ 2 3) 4)) 5)\)
md怎么好像更乱了
那么如何计算前缀表达式的值呢?
- 从右至左扫描表达式
- 遇到数字时,将数字压入堆栈,遇到运算符时,弹出栈顶的两个数,用运算符对它们做相应的计算(栈顶元素 \(op\) 次顶元素),并将结果入栈
- 重复上述过程直到表达式最左端,最后运算得出的值即为表达式的结果
示例:
计算上面举例的表达式的值。
- 从右至左扫描,将\(5\),\(4\),\(3\),\(2\)压入堆栈;
- 遇到\(+\)运算符,弹出\(2\)和\(3\)(\(2\)为栈顶元素,\(3\)为次顶元素),计算\(2+3\)的值,得到\(5\),将\(5\)压入栈;
- 遇到\(\times\)运算符,弹出\(5\)和\(4\),计算\(5\times 4\)的值,得到\(20\),将\(20\)压入栈;
- 遇到\(1\),将\(1\)压入栈;
- 遇到\(+\)运算符,弹出\(1\)和\(20\),计算\(1+20\)的值,得到\(21\),将\(21\)压入栈;
- 遇到\(-\)运算符,弹出\(21\)和\(5\),计算\(21-5\)的值,得到\(16\)为最终结果
可以看到,用计算机计算前缀表达式是非常容易的,不像计算后缀表达式需要使用正则匹配
当然这个一般不用
后缀表达式
这才是重点。
后缀表达式与前缀表达式类似,只是运算符位于两个相应操作数之后,后缀表达式也被称为后缀记法或逆波兰式.
例如上面那个中缀表达式转成后缀就是:\(1 2 3 + 4 \times + 5 -\)
与前缀表达式类似,只是顺序是从左至右:
- 从左至右扫描表达式
- 遇到数字时,将数字压入堆栈,遇到运算符时,弹出栈顶的两个数,用运算符对它们做相应的计算(次顶元素\(op\) 栈顶元素 ),并将结果入栈
- 重复上述过程直到表达式最右端,最后运算得出的值即为表达式的结果
示例:
计算上面举例的表达式的值
- 从左至右扫描,将\(1\),\(2\),\(3\)压入栈;
- 遇到\(+\)运算符,\(3\)和\(2\)弹出,计算\(2+3\)的值,得到\(5\),将\(5\)压入栈;
- 遇到\(4\),将\(4\)压入栈
- 遇到\(\times\)运算符,弹出\(4\)和\(5\),计算\(5\times4\)的值,得到\(20\),将\(20\)压入栈;
- 遇到\(+\)运算符,弹出\(20\)和\(1\),计算\(1+20\)的值,得到\(21\),将\(21\)压入栈;
- 遇到\(5\),将\(5\)压入栈;
- 遇到\(-\)运算符,弹出\(5\)和\(21\),计算\(21-5\)的值,得到\(16\)为最终结果
ybt计算后缀表达式的值
当然这里需要用栈。
code:
远古时代马蜂
#include<bits/stdc++.h>
using namespace std;
int a[99];
stack<long long>q;
int main()
{
string s;
getline(cin,s);
long long len=s.size(),o=0,p=1;
for(int i=0;i<len-1;i++)
{
if(s[i]>='0'&&s[i]<='9')
{
a[o]=s[i]-48;
o++;
}
else if(s[i]==' ')
{
long long b=0;
while(o--)
{
b+=a[o]*p;
p*=10;
}
o=0;p=1;
q.push(b);
}
else if(s[i]=='/')
{
long long y=q.top();
q.pop();
long long x=q.top();
q.pop();
q.push(x/y);
}
else if(s[i]=='*')
{
long long y=q.top();
q.pop();
long long x=q.top();
q.pop();
q.push(x*y);
}
else if(s[i]=='-')
{
long long y=q.top();
q.pop();
long long x=q.top();
q.pop();
q.push(x-y);
}
else if(s[i]=='+')
{
long long y=q.top();
q.pop();
long long x=q.top();
q.pop();
q.push(x+y);
}
}
cout<<q.top()<<endl;
return 0;
}
ybt计算中缀表达式
这里我们需要先把中缀表达式转成后缀表达式,然后再进行计算,因为中缀表达式对我们来说很好算,但计算机并不擅长。
code:
同上的远古代码
#include<bits/stdc++.h>
using namespace std;
stack<int>shu;
stack<char>q;
string s;
int len;
inline int level(char ch)
{
if(ch=='-'||ch=='+')return 1;
if(ch=='*'||ch=='/')return 2;
return 0;
}
inline void yunsuan()
{
int a=shu.top();shu.pop();
int b=shu.top();shu.pop();
char ch=q.top();q.pop();
if(ch=='-')shu.push(b-a);
if(ch=='+')shu.push(b+a);
if(ch=='*')shu.push(b*a);
if(ch=='/')shu.push(b/a);
}
void solve()
{
int x=0,flag=0;
for(int i=0;i<len;i++)
{
if(s[i]>='0'&&s[i]<='9')
{
x=x*10+(s[i]-'0');
flag=1;
}
else
{
if(flag)
{
shu.push(x);
x=0;
flag=0;
}
if(s[i]=='(')
{
q.push(s[i]);
continue;
}
if(s[i]==')')
{
while(q.top()!='(') yunsuan();
q.pop();
continue;
}
while(!q.empty()&&level(q.top())>=level(s[i]))yunsuan();
q.push(s[i]);
}
}
if(flag)
shu.push(x);
while(!q.empty())
yunsuan();
cout<<shu.top()<<endl;
}
bool check()
{
if(len==1)return level(s[0])>0?0:1;
for(int i=1;i<len;i++)
if(level(s[i])&&level(s[i-1]))return 0;
int sum=0;
for(int i=0;i<len;i++)
{
if(s[i]=='(')sum++;
if(s[i]==')')sum--;
}
return sum==0;
}
int main()
{
cin>>s;
len=s.size()-1;
if(!check())
cout<<"NO"<<endl;
else
solve();
return 0;
}
双端队列——deque
deque函数:
deque容器为一个给定类型的元素进行线性处理,像向量一样,它能够快速地随机访问任一个元素,并且能够高效地插入和删除容器的尾部元素。但它又与vector不同,deque支持高效插入和删除容器的头部元素,因此也叫做双端队列。deque类常用的函数如下。
(1) 构造函数
deque():创建一个空deque
deque(int nSize):创建一个deque,元素个数为nSize
deque(int nSize,const T& t):创建一个deque,元素个数为nSize,且值均为t
deque(const deque &):复制构造函数
(2) 增加函数
void push_front(const T& x):双端队列头部增加一个元素X
void push_back(const T& x):双端队列尾部增加一个元素x
iterator insert(iterator it,const T& x):双端队列中某一元素前增加一个元素x
void insert(iterator it,int n,const T& x):双端队列中某一元素前增加n个相同的元素x
void insert(iterator it,const_iterator first,const_iteratorlast):双端队列中某一元素前插入另一个相同类型向量的[forst,last)间的数据
(3) 删除函数
Iterator erase(iterator it):删除双端队列中的某一个元素
Iterator erase(iterator first,iterator last):删除双端队列中[first,last)中的元素
void pop_front():删除双端队列中最前一个元素
void pop_back():删除双端队列中最后一个元素
void clear():清空双端队列中最后一个元素
(4) 遍历函数
reference at(int pos):返回pos位置元素的引用
reference front():返回手元素的引用
reference back():返回尾元素的引用
iterator begin():返回向量头指针,指向第一个元素
iterator end():返回指向向量中最后一个元素下一个元素的指针(不包含在向量中)
reverse_iterator rbegin():反向迭代器,指向最后一个元素
reverse_iterator rend():反向迭代器,指向第一个元素的前一个元素
(5) 判断函数
bool empty() const:向量是否为空,若true,则向量中无元素
(6) 大小函数
Int size() const:返回向量中元素的个数
int max_size() const:返回最大可允许的双端对了元素数量值
(7) 其他函数
void swap(deque&):交换两个同类型向量的数据
void assign(int n,const T& x):向量中第n个元素的值设置为x
两个栈底的栈——双端栈
他并不是STL。
双端栈是指将一个线性表的两端当做栈底分别进行入栈和出栈操作.
在顺序栈的共享技术中,最常用的就是两个栈共享,即双端栈。利用栈底位置不变,栈顶变化的特性。首先申请一个一维数组空间,data[n],将两个栈的栈低分别放在数组的两端,分别是0和n-1,由于是栈顶动态变化的,这样可以形成互补,使得每个栈可用的最大空间与需求有关,由此可见,两个共享栈比两个栈分别申请n/2哥空间利用率高。


其实我不会但是我要鸽掉了。
STL大全的更多相关文章
- Effective STL 中文版(大全)
Effective STL 中文版(大全) 作者:winter 候捷说,对于STL,程序员有三个境界,开始是使用STL,然后是理解STL,最后是补充STL.Effective STL是一本非常好的书, ...
- [C++]C++ STL库函数大全
#include <assert.h> //设定插入点 #include <ctype.h> //字符处理 #include <errno.h> //定义错误码 # ...
- STL用法大全
1. 概述 泛型编程思想最早缘于A.Stepanov提出的部分算法可独立于数据结构的论断.20世纪90年代初A.Stepanov和Meng Lee根据泛型编程的理论用C++共同编写了STL.但直 ...
- STL入门大全(待编辑)
前言:这个暑假才接触STL,仿佛开启了新世界的大门(如同学完结构体排序一般的快乐\(≧▽≦)/),终于彻底领悟了大佬们说的“STL大法好”(虽然我真的很菜www现在只学会了一点点...)这篇blog主 ...
- [转]C/C++ 程序员必须收藏的资源大全
from: https://github.com/jobbole/awesome-cpp-cn C++ 资源大全中文版 我想很多程序员应该记得 GitHub 上有一个 Awesome – XXX 系列 ...
- Delphi 控件大全
delphi 控件大全(确实很全) delphi 控件查询:http://www.torry.net/ http://www.jrsoftware.org Tb97 最有名的工具条(ToolBar ...
- Ubuntu常用命令大全(转)
点评:Ubuntu常用命令大全,学习ubuntn系统的朋友可以收藏下,用ctrl+F查找即可 一.文件/文件夹管理 ls 列出当前目录文件(不包括隐含文件) ls -a 列出当前目录文件(包括隐含文件 ...
- C#与C++相比较之STL篇
引言 Program into Your Language, Not in It--<代码大全>.如何深入一门语言去编程?我认为有三步:熟悉它:知道它的局限性:扩展它.如何熟悉?不必说,自 ...
- 《转载》强大全面的C++框架和库推荐!
C++ 资源大全 关于 C++ 框架.库和资源的一些汇总列表,内容包括:标准库.Web应用框架.人工智能.数据库.图片处理.机器学习.日志.代码分析等. 标准库 C++标准库,包括了STL容器,算法和 ...
- STL库学习笔记(待补充QAQ
几百年前就说要学STL了然后现在还没动呢QAQ总算还是克服了懒癌决定学下QAQ 首先港下有哪几个vector listset map stack queue,大概就这些? 然后因为有几个基本操作每个都 ...
随机推荐
- java相关部分配置
一.mybatis逆向工程 ① generator.properties jdbc.driverLocation=D:/testDir/Maven/repository_g/mysql/mysql-c ...
- vue3学习大全(1)
# vue3.0 Vue3.0 在北京时间2020年9月19 日凌晨,发布了 3.0 版本,代号:*One Piece* ## 1.新特性 Vue 3 中一些需要关注的新功能包括: - [组合式 AP ...
- Postman挂载外部文件,实现参数化
一般来说,对一个接口进行测试,只能用边界值和等价类的方法,因此就会涉及到各种参数,使用Postman参数化,比较便捷: 但是自己这篇写得实在太浅陋了,将流花兄的博客内容附下,可以直接看他的 https ...
- 搬运 nginx代理https
oauth2-client在Nginx代理后遇到的问题和解决方案 2020-01-17 2020-05-27 TECH 30 MINUTES READ (ABOUT 4442 WORDS) OAu ...
- sql几种不同的权限
DDL:Data Definition Language DDL允许用户定义数据,也就是创建表.删除表.修改表结构这些操作.通常,DDL由数据库管理员执行. DML:Data Manipulation ...
- JSON常见用法
https://blog.csdn.net/weixin_43631296/article/details/105253434
- 使用react-vite-antd,修改antd主题,报错 [vite] Internal server error: Inline JavaScript is not enabled. Is it set in your options? It is hacky way to make this function will be compiled preferentially by less
一般报错 在官方文档中,没有关于vite中如何使用自定义主题的相关配置,经过查阅 1.安装less yarn add less (已经安装了就不必再安装) 2.首先将App.css改成App.les ...
- Javaweb学习笔记第十六弹--Vue、Element
Vue(一套前端框架,MVVM主要用于实现数据的双向绑定) Vue快速入门 //新建HTML页面,引入Vue.js文件 <script src="js.Vue.js"> ...
- Spring--AOP简介+入门案例
AOP简介 面向切面编程:在不惊动原始设计的基础上,进行功能增强 各个要应用该功能的对象叫做连接点,那个功能叫做通知,表面上的代码没有发生变化,私下里发生变化的连接点,会出现切入点,切入点与通知通过切 ...
- Gym 101490K Safe Racing (dp转换, 超超超级详细,包你看懂)
题意:给你一个长为L的圆形跑道,让你放置警示牌,相邻两个警示牌相隔距离不能超过S,让你求有多少种方案数放置.数据L,S都是1e6. 来个例子:L = 13, S = 5.一个圈表示长度为1. 思路:因 ...