有一些东西老忘,总结一些
1.end()为迭代器的最后一位的后一位
2.back()map和set和stack()没有
#include <bits/stdc++.h>
using namespace std;
int main(){
string a = "dasdasdsadsah";
vector<char>h;
queue<char>q;
stack<char>p;
p.push('d');
p.push('c');
q.push('q');
q.push('k');
q.push('l');
q.push('o');
h.push_back('d');
h.push_back('h');
h.push_back('w');
cout<<(a.back())<<endl;
cout<<(h.back())<<endl;
cout<<(q.back())<<endl;
/* auto p = q.find("da"); */
/* cout<<p->second<<"\n"; */
return 0;
}
结果
h
w
o
结构体内嵌比较函数bool operator < (const node &x) const {}
关于结构体内嵌比较函数:
一般情况下:
1 struct node
2 {
3 int l,r;
4 bool operator <(const node &a)const{
5 return r < a.r;
6 }
7 }a[maxn];
直接写比较函数是裸的r表示当前的值,如果r<a.r,那么就是从小到大排序,但是优先队列的是相反的,sort默认为从小到大排序,优先队列默认为从大到小。
1 struct node
2 {
3 int l,r;
4 bool operator <(const node &a)const
5 {
6 return r>a.r;
7 }
8 };
9 priority_queue<node> q;
那么这个优先队列是按r小的优先出队。
string类
常用操作 | 功能 |
---|---|
=,assign | 赋以新值 |
Swap | 交换两个字符串的内容 |
+=,append( ),push_back() | 添加字符 |
insert () | 插入字符 |
erase() | 删除字符 |
clear () | 移除全部字符 |
resize () | 改变字符数量 |
replace() | 替换字符 |
+ | 串联字符串 |
==,! =,<,<=,>,>=,compare() | 比较字符串内容 |
size(),length() | 返回字符数量,只有string有length选项 |
max_size () | 返回字符的最大可能个数 |
empty () | 判断字符串是否为空 |
reserve() | 保留内存以存储一定数量的字符 |
>>,getline() | 从 stream 中读取某值 |
<< | 将值写入 stream |
copy() | 将内容复制为一个 C - string |
c_str() | 将内容以 C - string 形式返回 |
data() | 将内容以字符数组形式返回 |
substr() | 返回子字符串位置kmp |
find() | 搜寻某子字符串或字符 |
begin( ),end() | 提供正向迭代器支持 |
rbegin(),rend() | 提供逆向迭代器支持 |
优点:支持一切数组操作,吃回车问题解决,字符串相加比较操作简单
两种输入测试: 第一种输一行相当于fgets,第二种是输入一个单词
#include <iostream>
using namespace std;
int main(){
string a,b;
getline(cin,a);
cin>>b;
cout<<a<<" "<<b<<endl;
return 0;
}
set集合
优点:有序,唯一
常用操作 | 功能 |
---|---|
s.insert(5); | 插入 |
erase(iterator) | 删除定位器iterator指向的值 |
erase(first,second) | 删除定位器first和second之间的值 |
erase(key_value) | 删除键值key_value的值,set中的删除操作是不进行任何的错误检查的,比如定位器的是否合法等等,所以用的时候自己一定要注意。 |
s.find(10); | 查找,返回给定值值得定位器,如果没找到则返回end()。 |
s.count(a) | 返回的是被查找元素的个数,如果有,返回1;否则,返回0。因为一个键值在set只可能出现0或1次,这样就变成了判断某一键值是否在set出现过了。 |
s.begin() | ,返回set容器的第一个元素 |
s.end() | ,返回set容器的最后一个元素 |
s.clear() | ,删除set容器中的所有的元素 |
s.empty() | ,判断set容器是否为空 |
s.max_size() | ,返回set容器可能包含的元素最大个数 |
s.size() | ,返回当前set容器中的元素个数 |
s.rbegin() | ,返回的值和end()相同 |
s.rend() | ,返回的值和rbegin()相同 |
s.lower_bound(k) | 就是指向第一个键k对应的第一个元素 |
s.upper_bound(k) | 就是指向大于键k的第一个元素 |
定义:set<int> s;
set<T> s;
struct cmp{
bool operator()(const int& a,const int& b){
return a > b;
}
};
struct cmp{
bool operator()(const T& t1,const T& t2){
if(t1.x != t2.x)
return t1.x < t2.x -->按x降序
return t1.y > t2.y -->x相等时按y升序
}
};
模板题uva10815 迭代器使用 + stringstream使用 + set使用 + string类使用
什么是stringstream
摘例解释stringstream
#include <sstream>
#include <iostream>
int main()
{
std::stringstream stream;
int first, second;
stream<< "456"; //插入字符串
stream >> first; //转换成int
std::cout << first << std::endl;
stream.clear(); //在进行多次转换前,必须清除stream
stream << true; //插入bool值
stream >> second; //提取出int
std::cout << second << std::endl;
}
#include <bits/stdc++.h>
using namespace std;
int main(){
set<string> q;
string s,buf;
while(cin >> s){
for(int i = 0;i < s.length();i++)
if(isalpha(s[i]))
s[i] = tolower(s[i]);
else
s[i] = ' ';
stringstream ss(s);
while(ss >> buf){
q.insert(buf);
}
}
//for(set<string>::iterator it = q.begin(); it != q.end(); it++)
for(auto it = q.begin(); it != q.end(); it++) //c++11新特性
cout<<*it<<endl;
return 0;
}
map
优点:map和set有序关联容器:红黑树 增删改O(log2n) 2是底数
map和set的插入删除效率比其他序列容器高,这是因为:
set中所有元素都是以节点的方式来存储的,其节点结构和链表类似,指向父节点和子节点。所以,在插入和删除时不需要做内存拷贝和内存移动,故而提高了效率。
常用操作 | 功能 |
---|---|
m.size(); | map元素个数 |
m.count(a) | 返回的是被查找元素的个数。如果有,返回1;否则,返回0。注意,map中不存在相同元素,所以返回值只能是1或0。 |
begin() | 返回指向map头部的迭代器 |
clear() | 删除所有元素 |
count() | 返回指定元素出现的次数 |
empty() | 如果map为空则返回true |
end() | 返回指向map末尾的迭代器 |
equal_range() | 返回特殊条目的迭代器 |
erase() | 删除一个元素删除:erase(key) erase(it) //既可以按照key值删除,也可以按照迭代器删除 |
find() | 查找一个元素 |
insert() | 插入元素 |
key_comp() | 返回比较元素key的函数 |
lower_bound(k) | 返回键值k>=给定元素的第一个位置 |
max_size() | 返回可以容纳的最大元素个数 |
rbegin() | 返回一个指向map尾部的逆向迭代器 |
rend() | 返回一个指向map头部的逆向迭代器 |
swap() | 交换两个map |
upper_bound(k) | 返回键值k>给定元素的第一个位置 |
value_comp() | 返回比较元素value的函数 |
声明:
map<string , int >mapstring; map<int ,string >mapint;
map<sring, char>mapstring; map< char ,string>mapchar;
map<char ,int>mapchar; map<int ,char >mapint;
//插入的三种方式
m["jack"] = 98; //区别是这个不报错
m.insert(pair<string,float>("jack",98));
m.insert(map<string,float>::value_type("jack",98));
hdu2063 两层map
#include <bits/stdc++.h>
using namespace std;
struct node{
map<string,int> shuiw;
};
map<string,node> q;
int main(){
string di,guo;
int n,m,jia;
cin>>n;
while(n--){
q.clear();
cin>>m;
while(m--){
cin>>guo>>di>>jia;
if(q.count(di) == 0){
node nod;
nod.shuiw[guo] = jia;
q[di] = nod;
}
else{
if(q[di].shuiw.count(guo) == 0){
q[di].shuiw[guo] = jia;
}
else{
q[di].shuiw[guo] = jia + q[di].shuiw[guo];
}
}
}
for(auto it = q.begin();it!=q.end();it++){
cout<<it->first<<"\n";
for(auto itt = it->second.shuiw.begin();itt != it->second.shuiw.end();itt++){
cout<<" |----"<<itt->first<<"("<<itt->second<<")"<<"\n";
}
}
if(n > 0){
putchar('\n');
}
}
return 0;
}
vector操作
邻接表,图论常用
常用操作 | 功能 |
---|---|
v.size() | 大小 |
v.empty() | 空为false反之亦然 |
v.push_back() | |
v.pop_back() | 见名知意 |
v.at(2); == v[2]; | 越界问题可能出现 |
v.insert(v.begin()+2,1) | 在2位置插入1 |
v,insert(v.end(),3) | 在最后插3 |
v.erase(v.begin()+2); | 删2位置 |
v.erase(v.begin()+1,v.begin()+5) | 删1到5 |
v.clear() | 清空 |
初始化定义
vector<unsigned int> v {2u, 3u, 5u, 7u, 11u, 13u, 17u, 19u};| 初始化列表中的値作为元素初始值,生成有 8 个素数的 vector 容器。
vector<int>v1; |初始化
vector<int> v2(10);| 10个默认为零的元素
vector <double> v3(10,8.6) |10个为8.6的元素
vector <<node> a[10] |a[10][]的我定义的数组
c++ 11新特性,不用写迭代器
for(auto i = v.begin();i!=v.end();i++){
cout<<*i<<" ";
}
for(auto i:v)
cout<<*i<<" ";
UVA156 map+vector模板
#include <bits/stdc++.h>
using namespace std;
map<string,int>word;
vector<string> a;
string repr(string s){
string ans = s;
for(int i = 0;i < ans.length();i++)
ans[i] = tolower(ans[i]);
sort(ans.begin(),ans.end());
return ans;
}
int main(){
string a1;
while(cin>>a1&&a1[0]!='#'){
string b1 = repr(a1);
a.push_back(a1);
if(word.count(b1) == 0)
word[b1] = 0;
word[b1]++;
}
vector<string>ans;
for(int i = 0;i < a.size();i++){
if(word[repr(a[i])] == 1) ans.push_back(a[i]);
}
sort(ans.begin(),ans.end());
for(int i = 0;i < ans.size();i++)
cout<<ans[i]<<"\n";
return 0;
}
queue队列
常用操作 | 功能 |
---|---|
q.push(4) | 加入数据 |
q.size() | 队列大小 |
q.empty() | 判断是否为空 |
q.front() | 获取队首元素 |
q.back() | 获取队尾元素 |
q.pop() | 清除队首元素 |
-------------------------------------------------- | ---------------------- |
q.top() | 优先队列队首元素 |
priority_queue q | 大的先出队 |
priority_queue <int,vector,greater > q | 小的先出队 |
priority_queue <int,vector ,cmp > | 自定义 |
HihoCoder - 1175拓扑排序
#include <bits/stdc++.h>
using namespace std;
int a[100010],du[100010],tuo[100010];
vector<int>mp[100010];
const int mod = 142857;
queue<int> q;
int main(){
int n,k,m,ans = 0,u,v,uva;
cin>>n>>m>>k;
for(int i = 0;i < k;i++){
cin>>uva;
a[uva] = 1;
}
for(int i = 0;i < m;i++){
cin>>u>>v;
mp[u].push_back(v);
du[v]++;
}
while(!q.empty()) q.pop();
for(int i = 1;i <= n;i++){
if(du[i] == 0)
q.push(i);
}
while(!q.empty()){
int temp = q.front();
q.pop();
ans = (ans + a[temp])%mod;
for(int i = 0;i < mp[temp].size();i++){
if(du[mp[temp][i]] >= 1){
du[mp[temp][i]]--;
a[mp[temp][i]]+=a[temp];
a[mp[temp][i]]%=mod;
if(du[mp[temp][i]] == 0){
q.push(mp[temp][i]);
}
}
}
}
printf("%d\n",ans);
return 0;
}
优先队列重载操作
声明 queue<int> q;
qriority_queue<int,vector<int>,cmp>;
struct cmp{
bool operator()(const int& a,const int& b){
return a > b;
}
};
struct cmp{
bool operator()(const T& t1,const T& t2){
if(t1.x != t2.x)
return t1.x < t2.x -->按x降序
return t1.y > t2.y -->x相等时按y升序
//或者我下面写的版本
}
};
两大区别,其中优先队列可以重载排序运算符,优先队列的获取顶端元素使用q.top()而不是q.front()。
lower_bound和upper_bound用法
#include <iostream>
#include <algorithm>
using namespace std;
int a[15];
int main() {
int t;
cin>>t;
while (t--) {
int n;
scanf("%d", &n);
for (int i = 0; i < n; i++){
cin>>a[i];
}
int lb = lower_bound(a, a + n + 1, 2)-a; //在[a,a+n+1)中找出大于等于2的位置,这个位置是从0开始
int ub = upper_bound(a, a + n + 1, 2)-a; //在[a,a+n+1)中找出大于2的位置,这个位置是从0开始
cout<<"序列中大于等于2第一个元素的位置:"<<lb+1<<endl;
cout<<"序列中大于2第一个元素的位置:"<<ub+1<<endl;
return 0;
}
}
poj2785 二分巧用
#include <iostream>
#include <algorithm>
using namespace std;
int n,a[4005],b[4005],c[4005],d[4005],x1[4005*4005],x2[4005*4005];
int main(){
scanf("%d",&n);
for(int i = 0;i < n;i++)
scanf("%d%d%d%d",&a[i],&b[i],&c[i],&d[i]);
int len = 0,len1 = 0,nn = n*n;
for(int i = 0;i < n;i++){
for(int j = 0;j < n;j++){
x1[len++] = a[i]+b[j];
x2[len1++] = c[i]+d[j];
}
}
sort(x2,x2+nn);
int ans = 0;
for(int i = 0;i < nn;i++){
ans = ans + (upper_bound(x2,x2+nn,-x1[i]) - lower_bound(x2,x2+nn,-x1[i]));
}
printf("%d\n",ans);
return 0;
}
sort操作
cmp重载函数
bool cmp(node a,node b){
if(a.w == b.w){
return a.x < b.x;
}
else{
return a.w > b.w;
}
}
主要边界问题
stack
先进后出
常用操作 | 功能 |
---|---|
s.push(8) | 压栈 |
s.top() | 获取栈顶 |
s.size() | 获取大小 |
s.empty() | 判断为空 |
s.pop() | 去除栈顶元素 |
hdu1506 单调栈例题
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
ll h[100010],r[100010],l[100010];
stack<int> q;
int main(){
int n;
while(cin>>n,n){
for(int i = 0;i < n;i++){
cin>>h[i];
}
while(!q.empty()) q.pop();
for(int i = 0;i < n;i++){
while(q.size() && h[q.top()] >= h[i])
q.pop();
if(q.empty()){
l[i] = 0;
}
else
l[i] = q.top()+1;
q.push(i);
}
while(!q.empty()) q.pop();
for(int i = n-1;i >= 0;i--){
while(q.size() && h[q.top()] >= h[i])
q.pop();
if(q.empty())
r[i] = n;
else
r[i] = q.top();
q.push(i);
}
ll ans = 0;
for(int i = 0;i < n;i++)
ans = max(ans,h[i] * (r[i] - l[i]));
cout<<ans<<endl;
}
return 0;
}
poj3250 单调栈模板
#include <iostream>
#include<stack>
using namespace std;
typedef long long ll;
ll niu[80100],l[80100],ans;
int main(){
int n;
cin>>n;
for(int i = 0;i < n;i++){
cin>>niu[i];
}
stack<int>q;
for(int i = 0;i < n;i++){
while(q.size() && niu[q.top()] <= niu[i]) q.pop();
/* if(q.empty()) l[i] = 0; */
/* else l[i] = q.top() + 1; */
ans += q.size();
q.push(i);
}
cout<<ans<<"\n";
return 0;
}
unordered_map
#include<tr1/unordered_map>
using namespace std::tr1;
template<class Key,
class Ty,
class Hash = std::hash<Key>,
class Pred = std::equal_to<Key>,
class Alloc = std::allocator<std::pair<const Key, Ty> > >
class unordered_map;
> class unordered_map
第1个参数Key,存储key值。 Key主键的类型,在类模板内部,使用其别名为 key_type 的成员类型
第2个参数Ty,存储mapped value。T 被映射的值的类型,在类模板内部,使用其别名为 mapped_type 的成员类型
第3个参数Hash,为哈希函数的函数对象。Hash将key作为参数,并利用函数对象中的哈希函数返回类型为size_t的唯一哈希值。默认值为std::hash<key>。
第4个参数Pred,为等比函数的函数对象。它内部通过等比操作符’=='来判断两个key是否相等,返回值为bool类型。默认值是std::equal_to<key>。在unordered_map中,任意两个元素之间始终返回false。
成员函数:
=================迭代器=========================
begin 返回指向容器起始位置的迭代器(iterator)
end 返回指向容器末尾位置的迭代器
cbegin 返回指向容器起始位置的常迭代器(const_iterator)
cend 返回指向容器末尾位置的常迭代器
=================Capacity================
size 返回有效元素个数
max_size 返回 unordered_map 支持的最大元素个数
empty 判断是否为空
=================元素访问=================
operator[] 访问元素
at 访问元素
=================元素修改=================
insert 插入元素
erase 删除元素
swap 交换内容
clear 清空内容
emplace 构造及插入一个元素
emplace_hint 按提示构造及插入一个元素
================操作=========================
find 通过给定主键查找元素,没找到:返回unordered_map::end
count 返回匹配给定主键的元素的个数
equal_range 返回值匹配给定搜索值的元素组成的范围
================Buckets======================
bucket_count 返回槽(Bucket)数
max_bucket_count 返回最大槽数
bucket_size 返回槽大小
bucket 返回元素所在槽的序号
load_factor 返回载入因子,即一个元素槽(Bucket)的最大元素数
max_load_factor 返回或设置最大载入因子
rehash 设置槽数
reserve 请求改变容器容量
#include <tr1/unordered_map>
#include <iostream>
#include <string>
using namespace std::tr1;
using namespace std;
void PrintMap(unordered_map<int, double>& m, char* pre)
{
unordered_map<int, double>::iterator tmp;
cout << pre;
for (tmp = m.begin(); tmp != m.end(); ++tmp)
{
cout << "(" << tmp->first << ", " << tmp->second << ")" << " ";
}
cout << endl;
}
int main()
{
unordered_map<int, double> m;//键的类型 int,值的类型double
m[0] = 0.99;//创建
//普通插入,使用类型转换
m.insert(unordered_map<int, double>::value_type(1, 1.99));
PrintMap(m, "插入元素之前的m:");
//插入一个范围
unordered_map<int, double> m2;
m2.insert(unordered_map<int, double>::value_type(3, 3.99));
m2.insert(unordered_map<int, double>::value_type(4, 4.99));
m2.insert(unordered_map<int, double>::value_type(5, 5.99));
m.insert(m2.begin(), m2.end());
PrintMap(m, "插入插入一个范围m:");
unordered_map<int, double>::iterator pTmp;
pTmp = m.find(4);
if (pTmp != m.end())
{
cout << "m.find(4): ";
cout << "(" << pTmp->first << ", " << pTmp->second << ")" << endl;
}
cout<<endl;
//如果key存在,则count返回1,如果不存在,则count返回0.
//键值的个数
cout<<"主键元素的个数:"<<m.count(1)<<endl;
m.clear();
PrintMap(m,"清空");
return 0;
}
unordered_set
#include <iostream>
#include <unordered_set>
using namespace std;
namespace wzj001{
void coutUnorderedSet(std::unordered_set<int>& m, string funcName) {
std::unordered_set<int>::iterator it;
std::cout << funcName << ": ";
for ( it = m.begin(); it != m.end(); it++ )
std::cout << *it << " ";
std::cout << std::endl;
}
void initUnorderSet(unordered_set<int>& tmp)
{
for(int i = 0; i < 10; i++)
tmp.insert(i);
}
string turnBoolToString(bool tmp)
{
return tmp ? "true" : "false";
}
void basicOperationUnorderedSet()
{
//定义
std::unordered_set<int> c;
// 普通插入,返回pair<迭代器,插入是否成功>
pair<unordered_set<int>::iterator, bool> c_insert = c.insert(1);
cout << "指向key的迭代器: " << *c_insert.first << " 插入是否成功 "<< turnBoolToString(c_insert.second)<<endl;
pair<unordered_set<int>::iterator, bool> c_insert2 = c.insert(2);
cout << "指向key的迭代器: " << *c_insert2.first << " 插入是否成功 "<< turnBoolToString(c_insert2.second)<<endl;
pair<unordered_set<int>::iterator, bool> c_insert3 = c.insert(1);
cout << "指向key的迭代器: " << *c_insert3.first << " 插入是否成功 "<< turnBoolToString(c_insert3.second)<<endl;
//按指定区域插入
std::unordered_set<int> c_insert_region;
c_insert_region.insert(c.begin(), c.end());
coutUnorderedSet(c_insert_region, "按指定区域插入");
//构造插入
std::unordered_set<int> c_emplace;
c_emplace.emplace(1);
c_emplace.emplace(2);
c_emplace.emplace(3);
coutUnorderedSet(c_emplace, "构造插入");
//迭代器插入
std::unordered_set<int> c_emplace_hint;
c_emplace_hint.emplace_hint(c_emplace_hint.begin(), 1);
c_emplace_hint.emplace_hint(c_emplace_hint.begin(), 2);
c_emplace_hint.emplace_hint(c_emplace_hint.begin(), 3);
coutUnorderedSet(c_emplace_hint, "迭代器插入");
//删除
std::unordered_set<int> c_erase;
initUnorderSet(c_erase);
coutUnorderedSet(c_erase, "初始化c_erase");
//指定位置删除
c_erase.erase(c_erase.begin());
coutUnorderedSet(c_erase, "指定位置删除");
//指定key删除
c_erase.erase(8);
coutUnorderedSet(c_erase, "指定key删除");
//指定区域删除
c_erase.erase(c_erase.begin(), c_erase.end());
coutUnorderedSet(c_erase, "指定区域删除");
//交换
c.swap(c_emplace);
coutUnorderedSet(c, "交换");
}
void unorderSetElementLookup()
{
//查找
std::unordered_set<int> c_find;
initUnorderSet(c_find);
std::unordered_set<int>::iterator find_iter = c_find.find(10);
if(find_iter != c_find.end())
{
cout<< "找到元素 : "<< *find_iter << endl;
}
else
cout<< "没找到 !"<< endl;
cout << "value出现次数 :" <<c_find.count(1)<< endl; //set key不可重复
pair<std::unordered_set<int>::iterator, std::unordered_set<int>::iterator> tmp = c_find.equal_range(5);
if(tmp.first != c_find.end()&& tmp.second != c_find.end())
{
cout << "该值所在区间为[" << *tmp.first << "," << *tmp.second << "]" << endl;
}
}
void unorderSetBuckets()
{
//篮子操作
std::unordered_set<int> c_buckets;
initUnorderSet(c_buckets);
cout << "篮子个数: " << c_buckets.bucket_count()<< endl;
cout << "篮子大小: " << c_buckets.bucket_size(1) << endl;
cout << "最大篮子个数: " << c_buckets.max_bucket_count() << endl;
cout << "该值所在篮子序号: " << c_buckets.bucket(3) << endl;
}
void unorderSetHashPolicy()
{
std::unordered_set<int> c_;
cout << "负载: "<< c_.load_factor()<< endl;
initUnorderSet(c_);
cout << "负载: "<< c_.load_factor()<< endl;//使用的篮子数/篮子总数 默认的篮子数为11
cout << "最大负载: "<< c_.max_load_factor() << endl;
c_.reserve(100);//预设篮子数 ,但是还没有设定
c_.rehash(3);//设定篮子数
}
void unorderSetObservers()
{
std::unordered_set<int> c_;
initUnorderSet(c_);
std::unordered_set<int>::hasher xxx = c_.hash_function();
std::unordered_set<int>::key_equal zzz = c_.key_eq();
cout << "hash_func: " << xxx(11111) << endl;
cout << "key_eq: " << turnBoolToString(zzz(11111,11111)) << endl;
}
}
int main()
{
wzj001::basicOperationUnorderedSet();
wzj001::unorderSetElementLookup();
wzj001::unorderSetBuckets();
wzj001::unorderSetHashPolicy();
wzj001::unorderSetObservers();
}