vector
定义vector
vector : 长度根据需要而自动变化的数组
使用vector: #include
vector <int> name;
vector<double> name;
vector<char> name;
vector<结构体名字> name;
下面定义二维数组:
vector<vector<int> > name; //注意 > > 之间需要加空格,这种写法长度是动态的
vector<int> a[100]; //这种写法长度是固定的
访问vector
通过下标访问
vector<double> vi;
//通过vi[0],vi[1],.........,vi[vi.size()-1]
vi.size() // 返回vi的里面的个数
通过迭代器访问
迭代器(iterator), 是一种类似指针的东西
vector<typename>::iterator it;
这样子, 就把 it 声明为一个 vector::iterator 类型的变量
比如:
vector<int> vi;
for(int i=1;i<6;i++)
{
vi.push_back(i);
}
vector<int>::iterator it = vi.begin(); // vi.begin()是vi首元素的地址,it指向这个地址
for(int i=0;i<5;i++)
{
printf("%d",*(it+i)); //得到结果,1 2 3 4 5
}
//可以看出vi[i] 和 *(vi.begin()+i) 是等价的的
但是,注意了:
vi.end() // 取尾元素地址的下一个地址
此外,迭代器还支持 ++it 和 it++ 这样的写法
vector<int> vi;
for(int i=1;i<6;i++)
{
vi.push_back(i);
}
for(vector<int>::iterator it = vi.begin();it != vi.end();it++)
{
printf("%d",*it); //得到结果,1 2 3 4 5
}
但是需要注意的是, 迭代器只有在 vector 和 string 中才能使用
vector中函数
push_back()
push_back函数:
- c++中的vector头文件里面就有这个push_back函数;
- 在vector类中作用为在vector尾部加入一个数据;
- string中也有这个函数,作用是字符串之后插入一个字符。
pop_back()
删除vector的尾元素
vi.pop_back()
size()
vi.size()
获得vector长度
clear()
清空vector中的所有元素
insert()
vi.insert(it,数值);
vector<int> vi;
for(int i=1;i<6;i++)
{
vi.push_back(i);
}
vector<int>::iterator it = vi.begin();
vi.insert(it+2,-1); //把-1插入到vi[2]的位置
//1 2 -1 3 4 5
erase()
erase(it) // 删除迭代器指向位置的元素
erase(frist,last); //删除 [first,last) 这个区间的元素
erase(vi.begin()+1,vi.begin()+4); //删除了 vi[1],vi[2],vi[3]
set
set是集合, 是一个内部自动有序,并且不会有重复元素的容器
#include
set<int> name;
set<int> double;
set<int> a[100]; //这样a[0]~a[99]每一个都是一个set集合
set只能通过迭代器访问其中的元素,不能通过下标进行访问
set<int>::iterator it;
set<int> st;
st.insert(2);
st.insert(3);
st.insert(5);
st.insert(2);
for(set<int>::iterator it;it!=set.end();it++)
{
printf("%d",*it); //输出 2 3 5
}
需要注意的是 不支持 it<set.end() 这样的写法
除了vector, string 其余的STL模板都不支持 *(it + i) 的写法
set中常用函数
set<int> vi;
insert()
vi.insert(6);
find()
find(value) 返回 set 中 值为value 的迭代器
erase()
删除单个元素
可以使用迭代器
set<int> vi;
vi.insert(100);
vi.insert(200);
vi.erase(vi.find(200)); //把200删除
也可以直接使用value
set<int> vi;
vi.insert(100);
vi.insert(200);
vi.erase(200); //把200删除
删除一个区间元素
vi.erase(first,last);
first, last 都是地址 删除 [first,last) 之间的元素
size()
获得set中元素个数
clear()
清空set中的所有元素
string
#include<string>
#include<iostream>
using namespace std;
string str='abcd';
可以通过下标访问string中的元素
printf('%c',str[0]);
string str1;
cin>>str1;
cout<<str1;
注意 string 类型的不能直接用printf 来输出
需要通过 c_str() 把string类型转化为字符数组才能用 printf 进行输出
printf("%s",str1.c_str());
string 类型除了通过下标进行访问,还可以通过迭代器进行访问
string str = 'abcd';
for(string::iterator it = str.begin();it != str.end();it++)
{
printf("%c",*it);
}
operator+=
string 的加法 ,可以将两个 string 类型拼接起来
string str1 = 'abc';
string str2 = '123';
string str3 = str1 + str2; // str3 是 abc123
compare operator
两个 string 类型变量 可以直接 用 < , > , <= , != 等进行比较,比较的规则是 字典序
length() 或者 size()
返回长度
insert()
insert(pos,string) 在 位置 pos (pos是下标值) 插入 字符串 string
insert(it,it1,it2)
it 是原字符串欲插入位置, it1 , it2 是待插入字符串的首位迭代器
string str1 = 'abcd';
string str2 = '123';
str1.insert(str1.begin()+2, str2.begin(),str2.end());
erase()
string str = 'abcde';
str.erase(str.begin()+4); //删除str[4]这里是e
// str.erase(frist,last); // 删除 [frist,last)之间的
str.erase(str.begin(),str.begin()+1);
clear() 删除 string 中所有元素
substr()
substr(pos,len) // 返回从 pos 位置开始 ,长度 为 len 的字符串
这里的pos是下标,不是迭代器
string::npos
find()
str.find(str1); // 当 str1是str的子串时 ,返回 str1 第一次出现的位置,如果不是子串返回-1
str.find(str1,pos); // 从 str的pos号位置开始寻找子串,找到了返回子串第一次出现位置,没有返回-1
replace()
str.replace(pos,len,str1); // str从pos开始,长度为len的地方替换为str1
str.replace(it1,it2,str1); // str[it1,it2) 范围的内容替换为str1
PAT[A] 1060 Are they equal
题目实际上就是 要求把两个浮点数 A,B 写成 0.a1a2… * 10^β
写成科学计数法, 然后比较10的幂次方是不是一样,保留出的有效数字是不是一样
#include<iostream>
#include<string>
using namespace std;
int n; //有效位数
string deal(string s,int &e) //e是10的几次方
{
int k=0; // s的下标,初始为0,指向了s[0]
while(s.length()>0 && s[0]=='0'){
s.erase(s.begin()); //去掉s的前导零
}
if(s[0]=='.'){//去掉前导零后是小数点,说明s是小于1的数
s.erase(s.begin());
while(s.length()>0 && s[0]=='0'){
//去掉小数点后非零位之前的所有零
s.erase(s.begin());
e--; //每去掉一个0,指数e减1
}
}
else{//去掉前导零后第一个不是小数点,那么找到后面的小数点
while(k<s.length() && s[k]!= '.')
{
k++;
e++;
}
if(k<s.length()) s.erase(s.begin()+k);
}
if(s.length()==0) e=0; //如果去掉前导0后这个数长度没了,说明这个数是0
int num = 0;
int k = 0;
string res;
while(num<n) //只要精度还没有到n
{
if(k<s.length()) res += s[k++]; //只要还有数字,那么就添加到res当中去
else res+='0';
num++;
}
return res;
}
int main()
{
string s1,s2,s3,s4;
cin>>n>>s1>>s2;
int e1=0,e2=0;
s3 = deal(s1,e1);
s4 = deal(s2,e2);
if(s3 == s4 && e1 ==e2){
cout<<"YES 0."<<s3<<"*10^"<<e1<<endl;
}
else{
cout<<"NO 0."<<s3<<"*10"<<e1<<" 0."<<s4<<"*10^"<<e2<<endl;
}
return 0;
}
map
map可以将任何类型(包括STL容器)映射到任何类型(包括STL容器)
map<typename1, typename2> mp;
map<string,int> mp;
map<set<int>,string> mp;
map元素的访问
可以通过键来访问
#include<map>
#include<cstdio>
using namespace std;
int main()
{
map<char,int> mp; // 把字符类型映射到int类型
mp['c'] = 20;
mp['c'] = 30; // 20被覆盖
printf("%d\n",mp['c']);
return 0;
}
也可以通过迭代器来访问
map<type1,type2>::iterator it;
使用
it->first; 访问键
it->second; 访问值
#include<cstdio>
#include<map>
using namespace std;
int main()
{
map<char,int> mp;
mp['c'] = 20;
mp['d'] = 30;
mp['f'] = 40;
for(map<char,int>::iterator it=mp.begin();it != mp.end();it++)
printf("%c %d\n",it->first,it->second);
return 0;
}
需要注意的是:map会对其中的元素根据元素的键的值从小到大排序
map常用函数
map<char,int> mp;
mp.find(key); // 返回键为key的迭代器
mp.erase(it); //it是要删除的元素的迭代器
mp.erase(first,last);// 删除[frist,last)之间的元素,frist, last都是迭代器
mp.size(); //得到映射对数
mp.clear(); //清空map中的所有元素
map的键和值是唯一的,如果需要一个键对应多个值,那么只能使用multimap
queue
queue<typename> q;
q.front();//访问队首元素
q.back();//访问队尾元素
q.push(value); //入队尾
q.pop();// 队首出队
q.empty(); //检查队是否为空
q.size(); //返回队中元素个数
在使用front和back函数之前,必须使用empty函数判断队列是否为空
priority_queue
优先级队列,队首元素一定是当前优先级最高的那个元素
可以在任何时候向优先级队列里面push元素,优先级队列底层的数据结构堆会随时调整结构,使得每次的队首元素都是优先级最大的
#include<queue>
using namespace std;
priority_queue<int> pq;
优先级队列没有front和back,只能通过top()访问队首元素
常用的一些函数
pq.pop(); //队首元素出队
pq.push(value); //入队
pq.top();// 访问队首元素
pq.empty(); //是否为空
pq.size(); //元素个数
优先级的设定
基本数据类型的优先级设置
int , double, char 等可以直接使用的基本数据类型, 一般默认为按照字典序
下面以int类型为例:
priority_queue<int> q;
priority_queue<int, vector<int>,less<int>> q;
priority_queue<int,vector<int>,greater<int>> q;
#include <iostream>
#include <queue>
#include <vector>
using namespace std;
struct Node{
int x;
int y;
};
struct cmp1{
bool operator() (int a,int b){
return a < b; //大根堆
}
};
struct cmp2{
bool operator() (int a,int b){
return a > b; //小根堆,和sort的cmp的顺序理解不一样,貌似正好反着,sort中 > 是大的在前, 这里是大的在后
};
int main()
{
priority_queue<int,vector<int>,cmp1 > pq;
priority_queue<int,vector<int>,cmp2> pq2;
pq.push(1),pq2.push(1);
pq.push(2),pq2.push(2);
pq.push(3),pq2.push(3);
cout << pq.top()<<" "<< pq2.top() <<endl;
return 0;
}
结构体的优先级设置
首先,让我们来看看什么叫做友元(friend)
如果想要以价格低的水果为优先级高,只需要把return中的 < 改为 > 即可
stack
#include<stack>
stack<int> s;
s.push(value); //入栈
s.pop(); //弹栈
s.top(); //获得栈顶元素
s.empty(); //是否为空
s.size(); //元素个数
pair
pair用于将两个元素绑定在一起构成一个结合体但是又不想因此而单独写一个结构体的情况下
struct pair{
type1 name1;
type2 name2;
};
使用pair需要添加头文件
#include<utility>
using namespace std;
pair<string,int> p("haha",5);
pair<string,int> b;
b.first = "heihei";
b.second = 6;
c = make_pair("lala",7);
pair常常用来作为map的输入
map<string,int> mp;
mp.insert(make_pair("haha",5));
mp.insert(pair<string,int>("lala",10));
algorithm
#include<algorithm>
using namespace std;
max(x,y); //返回x,y中大的那个
min(x,y);
abs(x); //x必须是整数,浮点数使用math头文件下的fabs
swap(x,y); //交换x,y的值
reverse(it1,it2); // 把[it1,it2)之间的元素进行翻转,当然it1,it2是指针或者迭代器
next_permutation(); //给出一个序列在全排列中的下一个序列
fill(); // 把数组中某一个区间赋相同值
int a[10];
fill(a,a+5,66); //把a[0] ~ a[4] 赋值66
sort(首元素地址,尾元素地址的下一个地址,比较函数);
lower_bound 和 upper_bound都得用于有序数组中
lower_bound(first,last,value); //返回[frist,last) 第一个大于等于 value 的值的指针
upper_bound(frist,last,value)l // 返回[frist,last) 第一个大于 value 的值的指针