STL模板

栈stack

template<typename _Tp, typename _Sequence = deque<_Tp> >
    class stack

先入后出,只有一边开口,可以理解为箱子,先放进去的压箱底,后放进去的就在上面,会被先拿出来。
最上面的元素称为栈顶。
具体看看代码:

// 返回这个栈是否为空
bool
empty() const
{ return c.empty(); }

// 返回栈的大小
size_type
size() const
{ return c.size(); }

// 返回栈顶元素
reference
top()
{
	__glibcxx_requires_nonempty();
	return c.back();
}

// 返回栈顶元素
const_reference
top() const
{
	__glibcxx_requires_nonempty();
	return c.back();
}

// 将一个元素压入栈,成为新的栈顶
void
push(const value_type& __x)
{ c.push_back(__x); }

// 弹出栈顶元素
void
pop()
{
	__glibcxx_requires_nonempty();
	c.pop_back();
}

参考luogu.org的例题P1981
其实用队列也是可以的
对于里面所有的乘法先进行运算,这样出来的结果就会是一堆数相加。
所以把要相加的数先压入栈,然后最后再统一加上

#include <cstdio>
#include <stack>
long long n,lst;
using std::stack;
char opt;
stack <long long>plus;
int main()
{
	scanf("%lld",&lst);
	lst%=10000;
	while(scanf("%c%lld",&opt,&n)==2)
	{
		if(opt=='+')
		{
			plus.push(lst);
			lst=1;
		}
		lst=(lst*n)%10000;
	}
	plus.push(lst);
	long long ans=0;
	while(!plus.empty())
	{
		ans+=plus.top()-10000;
		plus.pop();
		ans+=(ans>>63)&10000;
	}
	printf("%lld\n",ans);
	return 0;
}

(仓促代码别想了肯定丑)

队列queue

就像真的排队一样,先进先出
先进来的……就先走
队首第一个元素就是将要被弹出的元素。
队尾的最后一个元素就是刚入队的元素

 template<typename _Tp, typename _Sequence = deque<_Tp> >
    class queue
// 返回当前队列是否为空
bool
empty() const
{ return c.empty(); }

// 返回当前队列的大小
size_type
size() const
{ return c.size(); }

// 返回队首元素
reference
front()
{
	__glibcxx_requires_nonempty();
	return c.front();
}


const_reference
front() const
{
	__glibcxx_requires_nonempty();
	return c.front();
}

// 返回队尾元素
reference
back()
{
	__glibcxx_requires_nonempty();
	return c.back();
}


const_reference
back() const
{
	__glibcxx_requires_nonempty();
	return c.back();
}

// 将元素入队尾
void
push(const value_type& __x)
{ c.push_back(__x); }

// 弹出队首元素
void
pop()
{
	__glibcxx_requires_nonempty();
	c.pop_front();
}

与此同时还有双端队列deque,和queue的用法差不多,但是支持双端队列操作。
有函数push_front();pop_front();push_back();pop_back();
参考luogu.org的例题P1540
因为这里也需要先入先出的属性,所以使用队列

#include <cstdio>
#include <queue>
using std::queue;
bool vis[1001];
int n,m,ans,opt;
queue<int> q;

int main()
{
	scanf("%d%d",&m,&n);
	while(n--)
	{
		scanf("%d",&opt);
		if(not vis[opt])
		{
			vis[opt]=true;
			++ans;
			if(q.size()==m)
			{
				vis[q.front()]=false;
				q.pop();
			}
			q.push(opt);
		}
	}
	printf("%d\n",ans);
	return 0;
}

与此同时还有优先队列priority_queue,每次保证队头元素一定是队列中最“大”的
也就是名副其实的大根堆
当然这个“大”也是你自己定义的
```cpp
priority_queue<int,vector<int>,greater<int> > p;

就可以实现小根堆
最后的greater也可以替换为自己定义的比较函数指针

列表List

嗯,这篇文章讲得很好(逃
然后我也没找到好的例题……
那就过了

集合set

他非常好满足了集合的特点:互异性
如果你重复插入某个元素和只插入一次是没有区别的。
(当然可能会浪费时间。
底层实现是红黑树,我不会(诚实)
所以他的数据是有序的!(如果你用迭代器遍历的话)
默认升序,也可以修改为降序
也可以使用反向迭代器reverse_iterator遍历,这样顺序就反过来了。

#include <bits/stdc++.h>
using namespace std;
set<int,greater<int> > s;

int main()
{
	s.insert(3);
	s.insert(2);
	s.insert(1);
	for(set<int>::iterator it = s.begin(); it != s.end();++it)
	{
		cout << *it << ' ';
	}
	return 0;
}

一些成员函数……看资料

映射map

对于每一个给定的键key都有唯一对应的值val.可以理解为数组,但是无论时间还是空间上都比数组快
(但是操作很麻烦)

多重映射multimap

对于每个给定的键key可以有多个对应的值val,但是同样不怎么实用。
好好地有数组不用用什么STL

对pair

给定两个参数类型,构造一对打包的数据类型

pair<int, int> a;
a.first;
a.second;
a=make_pair(1,2);

元组tuple

别看了c++11专用考试c++98用不上

容器containers

不是一个确切的函数,是一类模板
STL封装好的容器有vector, deque, list等

算法algorithms

就是STL里面好多好多的内置函数
比如sort, erase, copy之类的

仿函数/函数对象functors

是用结构体实现函数功能。
也不知道有什么用

struct my_functor
{
  operator()(int a,int b)
  {
    return a+b;
  }
}

然后调用

my_functor(1,2);

就会返回3
(不就是函数嘛)

迭代器iterator

很多很多类class/容器containers都自带的东西,用来遍历整个类/容器

vector<int> a;
while(cin >> x) a.push_back(x);
for(vector<int>::iterator it=a.begin(); it!=a.end();++it) cout << *it << endl;

就可以遍历整个vector
这里很容易看出iterator是定义在

template <typename T> 
class vector<T>;

里面的一个子类/结构体

posted @ 2021-09-26 13:45  IdanSuce  阅读(55)  评论(0编辑  收藏  举报