常用的C++ STL

1. 顺序式容器

(1) vector(动态数组)

功能:

  1. 定义整型数组
    vector<int> a; 定义一个动态数组a,自动默认初始化为空
    vector<int> a(100); 定义一个动态数组a,有100个为0的元素
    vector<int> a(100, 6); 定义一个动态数组,有100个为6的元素

  2. 定义string型数组
    vector<string> a(10, "null"); 10个值为null的元素
    vector<string> a(100,"hello"); 10个值为hello的元素
    vector<string> b(a.begin(), a.end()); b是a的复制

  3. 定义结构型数组:
    struct point {int x, y;};
    vector<point> a; a是用来存坐标的

  4. 赋值:a.push_back(值); 在尾部添加元素

  5. 统计元素的个数:a.size();

  6. 判断vector是否为空:a.empty();

  7. a.insert(a.begin() + i, k); 在第i个元素前面插入k

  8. a.insert(a.end(), 10, 5); 在尾部插入10个值为5的元素

  9. a.pop_back(); 删除末尾元素

  10. a.erase(a.begin() + i, a.end() + j); 删除区间[i, j - 1]的元素

  11. a.erase(a.begin()+2); 删除第3个元素

  12. a.resize(n); 将数组大小调为n

  13. a.clear(); 清空

  14. reverse(a.begin(), a.end()); 用函数reverse()翻转数组

  15. sort(a.begin(), a.end()); 排序

vector 例题

圆桌问题
Problem Description
圆桌上围坐着2n个人。其中n个人是好人,另外n个人是坏人。如果从第一个人开始数数,数到第m个人,则立即处死该人;然后从被处死的人之后开始数数,再将数到的第m个人处死……依此方法不断处死围坐在圆桌上的人。试问预先应如何安排这些好人与坏人的座位,能使得在处死n个人之后,圆桌上围坐的剩余的n个人全是好人。

Input
多组数据,每组数据输入:好人和坏人的人数n(<=32767)、步长m(<=32767);

Output
对于每一组数据,输出2n个大写字母,‘G’表示好人,‘B’表示坏人,50个字母为一行,不允许出现空白字符。相邻数据间留有一空行。

Sample Input

2 3
2 4

Sample Output

GBBG

BGGB
 

约瑟夫环问题

#include<cstdio>
#include<iostream>
#include<cstring>
#include<string>
#include<cmath>
#include<map>
#include<vector>
#include<algorithm>

#define IOS ios::sync_with_stdio(false); cin.tie(0); cout.tie(0)
#define ll long long
#define int ll
#define INF 0x3f3f3f3f
#define PI acos(-1)
#define MOD 1e9 + 7
#define mem(a, b) memset(a, b, sizeof a)
using namespace std;
int read(){int w = 1, s = 0;char ch = getchar();while (ch < '0' || ch>'9') { if (ch == '-') w = -1; ch = getchar(); }while (ch >= '0' && ch <= '9') { s = s * 10 + ch - '0';ch = getchar(); }return s * w;}
const int N = 70000;
vector<int> v;
bool ans[N];
signed main() {
	int n, m;
	while (~scanf("%lld%lld", &n, &m)) {
		v.clear(); //清空
		for (int i = 1; i <= n + n; i++) {
			v.push_back(i);
			ans[i] = true;//先都初始化为好人,true为好人,false为坏人 
		}
		int cnt = v.size(), cur = 0;
		//当坏人还没杀完,就一直循环 
		while (cnt > n) {
			cur = (cur + m - 1) % cnt;//因为圆桌是一个环,所以要取余 
			ans[v[cur]] = false;//把这个位置记为坏人
			//v.erase(a.begin()+i); 删除第i个元素
			v.erase(v.begin() + cur); //删除第cur个元素	
			cnt--;
		} 
		//输出 
		for (int i = 1; i <= n + n; i++) {
			if (ans[i]) printf("G");
			else printf("B");
			if (i % 50 == 0) printf("\n");
		}
		//这题的格式有点问题 
		if((n << 1) % 50 != 0) 
            printf("\n");
        printf("\n");
	}
	return 0;
}

(2) stack(栈)

栈的相关操作:


#include<stack>               头文件
stack<Type> s;                定义一个栈,Type为数据类型
s.top();                      返回栈顶元素,但不会在栈里删除该元素
s.pop();                      删除栈顶元素,但不会返回。
出栈(两步操作):先用s.top()获得栈顶元素,再用s.pop()弹栈
s.size();                     返回栈中元素的个数
s.empty();                    判断栈是否为空


栈 —— 简单例题(HDU 1062)

题意:翻转字符串
题解:用栈的先进后出的特点来做

#include<cstdio>
#include<iostream>
#include<cstring>
#include<string>
#include<cmath>
#include<map>
#include<vector>
#include<stack> 
#include<algorithm>

#define IOS ios::sync_with_stdio(false); cin.tie(0); cout.tie(0)
#define ll long long
#define int ll
#define INF 0x3f3f3f3f
#define PI acos(-1)
#define MOD 1e9 + 7
#define mem(a, b) memset(a, b, sizeof a)
#define print(n) printf("%lld\n", n);
using namespace std;
int read(){int w = 1, s = 0;char ch = getchar();while (ch < '0' || ch>'9') { if (ch == '-') w = -1; ch = getchar(); }while (ch >= '0' && ch <= '9') { s = s * 10 + ch - '0';ch = getchar(); }return s * w;}
const int N = 1010;
char str[N];
signed main() {
	int t = read();
	while (t--) {
		char ch;
		stack<char> s;
		while (true) {
			ch = getchar();//每次读入一个字符 
			if (ch == ' ' || ch == '\n' || ch == EOF) {
				while (!s.empty()) {
					printf("%c", s.top());//输出栈顶元素 
					s.pop();//弹栈 
				}
				//结束 
				if (ch == '\n' || ch == EOF) break; 
				printf(" ");
			}
			else s.push(ch);//入栈 
		}
		printf("\n"); 
	}
	return 0;
}

栈较复杂例题(HDU 1237)

简单计算器

Problem Description
读入一个只包含 +, -, *, / 的非负整数计算表达式,计算该表达式的值。

Input
测试输入包含若干测试用例,每个测试用例占一行,每行不超过200个字符,整数和运算符之间用一个空格分隔。没有非法表达式。当一行中只有0时输入结束,相应的结果不要输出。

Output
对每个测试用例输出1行,即该表达式的值,精确到小数点后2位。

Sample Input
1 + 2
4 + 2 * 5 - 7 / 11
0

Sample Output
3.00
13.36

对数字运算进行模拟:
① 如果遇到 ’ + ’ 或 ’ - ',先将相应的数字push入栈(如果是 ’ - ’ 则push数字的相反数)
② 如果遇到优先级大的 ’ * ’ 或 ’ / ’ 先将相应数字与栈顶元素进行运算后将结果push进入
③ 最后将栈中所有元素相加。

#include<cstdio>
#include<iostream>
#include<cstring>
#include<string>
#include<cmath>
#include<vector>
#include<map>
#include<stack>
#include<algorithm>
 
#define IOS ios::sync_with_stdio(false); cin.tie(0); cout.tie(0)
#define ll long long
#define int ll
#define INF 0x3f3f3f3f
#define PI acos(-1)
#define MOD 1e9 + 7
using namespace std;
int read()
{
    int w = 1, s = 0;
    char ch = getchar();
    while (ch < '0' || ch>'9') { if (ch == '-') w = -1; ch = getchar(); }
    while (ch >= '0' && ch <= '9') { s = s * 10 + ch - '0';ch = getchar(); }
    return s * w;
}
signed main()
{
    char c, s;
    char s;
    double n;
    //开头特殊处理:0 +'\n'时结束;
    while(~scanf("%lf%c",&n,&c)) {
        if(n == 0 && c=='\n') break;
        stack<double>stk;
        double ans=0;
        while(!stk.empty()) stk.pop();
        stk.push(n);
        while(~scanf("%c %lf",&s,&n)) {
            if (s == '+') stk.push(n);
            if (s == '-') stk.push(-n);
            if (s == '*') {
                double tmp = stk.top() * n;
                stk.pop();
                stk.push(tmp);
            }
            if (s=='/') {
                double tmp = stk.top() * 1.0 / n;
                stk.pop();
                stk.push(tmp);
            }
            c = getchar();
            if (c == '\n') break;
        }
        while (!stk.empty()) {
            ans += stk.top();
            st.pop();
        }
        printf("%.2lf\n",ans);
    }
    return 0;
}

(3) queue(队列)

queue的操作:
#include<queue>         头文件
queue<Type> q;          定义队列
q.push(s);              把s放入队列
q.front();              获取队首元素,但不会删除
q.pop();			    删除队首元素
q.back();			    返回队尾元素
q.size();				返回队列中元素个数
q.empty();				检查队列是否为空

栈和队列的简单例题(HDU 1702)

在这里插入图片描述
题意:模拟栈和队列:
栈是 FILO(先进后出 First In Last Out)
队列是 FIFO(先进先出 First In First Out)

#include<cstdio>
#include<iostream>
#include<cstring>
#include<string>
#include<cmath>
#include<map>
#include<vector>
#include<functional>
#include<algorithm>
#include<stack>
#include<queue>
#define IOS ios::sync_with_stdio(false); cin.tie(0); cout.tie(0)
#define ll long long
#define int ll
#define INF 0x3f3f3f3f
#define PI acos(-1)
#define MOD 1000000007
#define mem(a, b) memset(a, b, sizeof a)
#define print(n) printf("%lld\n", n)
using namespace std;
int read()
{
	int w = 1, s = 0;
	char ch = getchar();
	while (ch < '0' || ch>'9') { if (ch == '-') w = -1; ch = getchar(); }
	while (ch >= '0' && ch <= '9') { s = s * 10 + ch - '0';ch = getchar(); }
	return s * w;
}
signed main() {
	int t = read();
	while (t--) {
		string str;
		queue<int> q;
		stack<int> stk;
		int n = read();
		cin >> str;
		for (int i = 1; i <= n; i++) {
			string s;
			cin >> s;
			//队列 
			if (str == "FIFO") {
				if (s == "IN") {
					int a = read();
					q.push(a);//IN,放进队列 
				} else {
					if (q.empty()) printf("None\n");//如果队列为空,此时还要求输出的话,那么就是None 
					else {
						printf("%lld\n", q.front());//输出队首元素
						q.pop(); //删除队首元素 
					}
				}
			} else {
				if (s == "IN") {
					int a = read();
					stk.push(a);//IN,放入栈中 
				} else {
					if (stk.empty()) printf("None\n");//如果栈为空,此时还要求输出的话,那么就是None 
					else {
						printf("%lld\n", stk.top());//输出栈顶元素 
						stk.pop();//弹栈:删除栈顶元素 
					}
				}
			}
		}
	}
	return 0;
}

2. 关联式容器

(1) set(集合)

  1. set与数组不同的是,在set中每个元素的值都是唯一的。
  2. set插入数据时,能够根据元素的值自动进行排序。
  3. set中数元素的值并不能直接被改变。
set的有关操作:
set<Type> a;            定义一个set
a.insert(x);		    把x放进set
a.erase(x);			    删除元素x
a.clear();              清空set
a.empty(); 			    判断set是否为空
a.size();				返回set中元素个数
a.find(x);				返回一个迭代器,指向键值x
a.lower_bound(x);		返回一个迭代器,指向键值不小于x的第一个元素
a.upper_bound(x);		返回一个迭代器,指向键值不大于x的第一个元素

set 简单例题 (HDU 2094)

#include<cstdio>
#include<iostream>
#include<cstring>
#include<string>
#include<cmath>
#include<map>
#include<vector>
#include<functional>
#include<algorithm>
#include<stack>
#include<set>
#include<queue>

#define IOS ios::sync_with_stdio(false); cin.tie(0); cout.tie(0)
#define ll long long
#define int ll
#define INF 0x3f3f3f3f
#define PI acos(-1)
#define MOD 1000000007
#define mem(a, b) memset(a, b, sizeof a)
#define print(n) printf("%lld\n", n)
using namespace std;
int read()
{
	int w = 1, s = 0;
	char ch = getchar();
	while (ch < '0' || ch>'9') { if (ch == '-') w = -1; ch = getchar(); }
	while (ch >= '0' && ch <= '9') { s = s * 10 + ch - '0';ch = getchar(); }
	return s * w;
}
signed main() {
	int n;
	while (cin >> n && n) {
		string winner, loser;
		set<string> all, lose;
		//利用了set中每个元素的值都是唯一的
		for (int i = 1; i <= n; i++) {
			cin >> winner >> loser;
			//把所有人放入all集合中 
			all.insert(winner);
			all.insert(loser);
			//把输的人放到lose集合中 
			lose.insert(loser);
		}
		//冠军没输过,如果能确定冠军,就是其他人都输过了,那么all.size() - lose.size() == 1 
		if (all.size() - lose.size() == 1) printf("Yes\n");
		else printf("No\n");
		//清空两个集合 
		all.clear();
		lose.clear(); 
	}
	return 0;
}

(2) map(一对一映射)

之所以要用到map,这么一个简单的例子:有n个学生,每个学生有姓名name和学号id,现在给出学生的name,要找对应的id。

那就是要把该学生的 name 和 id 通过一个东西来绑定。

如果没有用map的话,那么可以用结构体

struct Student{
	string name;
	int id;
}s[N];

但是如果用结构体的话,给出 name 来找到 id 就需要线性查找这个时间复杂度是 O ( n ) O(n) O(n) 的。

如果用map的话,可以对这个优化。因为map效率高的原因是它用平衡二叉搜索树来存储和访问。

map的相关操作:
map<string, int> stu;            定义map<Type, Type>;
stu["QYIF"] = 09                 绑定了name为 "QYIF" 的人,它的学号为 9

用map就可以直接用 stu["QYIF"] 来表示 "QYIF" 这个人的学号。

map + 迭代器的简单例题 (HDU 2648)

在这里插入图片描述
题意:这个叫 Dandelion 的女孩,喜欢购物,她很喜欢这个叫 memory 的商店,临近年关,现在她想知道这家商店每天的价格排名。

题解:给这个memory商店初始化排名为1,用迭代器遍历,如果it->second (其他商店的价格比memory高)那么就rank++;就可以了

#include<cstdio>
#include<iostream>
#include<cstring>
#include<string>
#include<cmath>
#include<map>
#include<vector>
#include<functional>
#include<algorithm>
#include<stack>
#include<set>
#include<queue>

#define IOS ios::sync_with_stdio(false); cin.tie(0); cout.tie(0)
#define ll long long
#define int ll
#define INF 0x3f3f3f3f
#define PI acos(-1)
#define MOD 1000000007
#define mem(a, b) memset(a, b, sizeof a)
#define print(n) printf("%lld\n", n)
using namespace std;
signed main() {
    IOS;
	int n, m, price;
	while (cin >> n) {
		map<string, int> shop;
		string str;
		for (int i = 1; i <= n; i++) cin >> str;
		int m;
		cin >> m;
		while (m--) {
		    for (int i = 1; i <= n; i++) {
		        cin >> price >> str;
		        shop[str] += price;//给商店加上价格
		    }
		    int rank = 1;
		    map<string, int>::iterator it;//迭代器
		    //遍历
		    for (it = shop.begin(); it != shop.end(); it++) {
		        if (it->second > shop["memory"]) rank++;//如果遇到比memory这个商店的价格高就+1
		    }
		    printf("%lld\n" ,rank);
		}
	}
	return 0;
}

3. sort() 排序函数

#include<algorithm>             头文件
sort(a, a + n)                  格式1
sort(a, a + n, cmp)				格式2 (cmp为排序的规则)

拓展用法:
vector<int> a = {3, 2, 4, 6, 7}
sort(a.begin(), a.end()); 				正常用法
sort(a.begin(), a.end(), 4); 			对前4个元素进行排序,输出2 3 4 6 7
sort(a.begin(), a.end(), less<int>); 	从小到大排序
sort(a.begin(), a.end(), greater<int>); 从大到小排序
sort(a.begin(), a.end(), cmp)  			自定义排序,cmp是自定义函数

对结构变量排序:
struct stu{
	string name;
	int id;
};
bool cmp(struct stu* a, struct stu *b) {
	//自定义排序,例如id从小到大排序
	return a->id < b->id;
}
vector<struct Stu*> message; //将学生信息存入message
sort(message.begin(), message.end(), cmp);

4. next_permutation()和prev_permutation()

next_permutation() 下一个排列组合。
prev_permutation() 上一个排列组合。
例如3个字符 a、b、c next_permutation() 能按照字典序返回6个组合,分别是:abc、acb、bac、bca、cab、cba

  • 4
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值