C++语法基础篇-STL容器和常用函数
STL是提高C++编写效率的一个利器。
STL容器
1.变长数组 vector
/*
变长数组 Vector 使用倍增的思想
*/
#include<iostream>
#include<vector>
using namespace std;
int main(){
//定义:
vector<int> a; //定义a为存储类型为int 的变长数组
vector<int> b[100]; //定义b为 第一维长100 第二维为变长的数组
//自定义结构体
struct Rec{
int x,y;
};
//vector<Rec> c; //自定义的结构体类型也可以保存在vector中
//函数:
a.size(); //返回vector的实际长度(包含的元素个数)
a.empty(); //返回一个bool类型,表明vector是否为空。二者的时间复杂度都是O(1)。
//所有的STL容器都支持这两个方法,含义也相同,之后我们就不再重复给出。
a.clear(); //将vector清空
a.end();//返回的是最后一个元素的下一个地址
a.begin(); //a.begin()返回的是a的第一个元素的地址!
a.front(); //返回vector的第一个元素 等价于a[0]
a.back(); //返回vector的最后一个元素 等价于a[a.size()-1]
a.push_back(x); //在a的最后添加一个元素x
a.pop_back(); //在移除a的最后一个元素
//迭代器:
vector<int>::iterator it = a.begin(); //定义一下a的迭代器(类似于指针)
it+2=a[2]; *a.begin()=[0]; //a.begin()返回的是a的第一个元素的地址!
a.end();//返回的是最后一个元素的下一个地址
//遍历:
vector<int> d({1,2,3}) ;//初始化一个vector
//方式一:数组下标
for(int i=0;i<d.size();i++) cout<<d[i]<<" ";
cout<<endl;
//方式二:迭代器遍历 其中vector<int>::iterator 可以用auto替换
for(vector<int>::iterator i=d.begin();i!=d.end();i++){
cout<<*i<<' ';
}cout<<endl;
//方式三:增强for
for(auto x:d)cout<<x<<' ';
cout<<endl;
return 0;
}
2.队列 queue
/*
队列 queue 先入先出
*/
#include<iostream>
#include<queue>//头文件中包含queue(循环队列)和priority_queue(优先队列)两个容器
using namespace std;
int main(){
//循环队列queue的定义
queue<int> q;
queue<double> a;
struct Rec{
int x,y;
};
queue<Rec> b;
//循环队列函数
q.push()//对尾插入一个元素
q.pop(x)//对头移出一个元素
q.front()//返回队头元素
q.back()//返回队尾元素
q=queue<int>(); //重新初始化队列,因为其中不包含清空的函数
//优先队列 priority_queue的定义
priority_queue<int> a;//默认是大根堆
priority_queue<int,vector<int>,geater<int>> b;//小根堆
priority_queue<pair<int,int>> c;// pair类型
Rea struct{
int a,b;
//重写大于号,因为是属于自定义数据类型,优先队列中比较大小需要我们来自定义一下
bool operator < (const Rea& t){
return a < t.a
}
};
priority_queue<Rea>;
//优先队列常用函数
a.push(x) //插入一个数值
a.pop() //删除最大值
a.top() //取出最大值
//特殊指出:队列、优先队列、栈,没有clear函数,清空只需要重新初始化即可!
return 0;
}
3.栈 stack
/*
栈 先入后出
*/
#include<iostream>
#include<stack>
using namespace std;
int main(){
//定义
stack<int> stk;
//函数
stk.push(x) //向栈中插入一个元素x
stk.pop // 删除栈顶元素
stk.top // 返回栈顶元素
return 0;
}
4.双端队列 deque
/*
双端队列 deque 队列的两端都可以入和出
*/
#include<iostream>
#include<deque>
using namespace std;
int main(){
//deque的定义
deque<int> a;
//常用函数地址
a.begin(); a.end(); //返回deque的头/尾迭代器
a.fornt(); a.back(); //返回deque的头元素或最后一个元素
a[0];//随机取出一个元素
a.clear()//清空所有元素
push_back(1); push_front(1) //从队尾、对头入队
pop_back(); pop_back()//从队尾、对头出队
return 0;
}
5.有序集合 set
/*
有序集合 set
*/
#include<iostream>
#include<set> //set头文件中包含 set和multiset两个容器,分别是"有序集合"和"有序多重集合"
//前者的元素不能重复,而后者可以包含若干个相等的元素。
//set和multiset的内部实现是一棵红黑树,它们支持的函数基本相同。
using namespace std;
int main(){
//定义
set<int> a; //元素不可重复,重复的相关操作默认无效
multiset<int> b; //元素可以重复
//当set中是自定义结构体类型的数据时,set需要重载 < ,因为我们的set是会将其中元素从小到大排序的
//函数
a.size();//实际元素的个数
a.clear();//清空
a.empty();//判断是否为空
a.begin();//第一个元素的迭代器
a.end();//返回最后一个元素的下一个位置的迭代器
a.insert(x);//插入一个元素x
a.find(x); //返回值为x的迭代器 ,如果找不到返回a.end(); 常用于:if(a.find(x) == a.end())
a.lower_bound(x)//找到大于等于 x 的最小元素的迭代器
a.upper_bound(x)//找到大于 x 的最小元素的迭代器
a.erase(it)//删除一个迭代器
a.count(x)//统计x的个数,由于set时有序不重复的,所以存在x返回1不存在返回0
//迭代器
return 0;
}
6.无序集合 unordered_set
/*
无序集合unordered_set 底层实现(Hash)哈希表
*/
//上述set区别,1.其中的元素无序、2.不含upper_bound()和lower_bound()这两个方法,其余一致
#include<iostream>
#include<unordered_set>
using namespace std;
int main(){
unordered_set<int> a; //不能存放重复元素
unordered_multiset<int> b;//可以存放重复元素
return 0;
}
7.键值对 map
/*
键值对 map //底层实现同set一样是红黑树(平衡树)
*/
#include<iostream>
#include<map>
using namespace std;
int main(){
//定义
map<int,int> a;
map<string,vector<int>> b;
//函数
size();empty();clear();begin();end();//均与set类似。
b.insert("sqx",{1,2,3,5});//插入一个<K,V>键值对
b["sqx"]={1,2,3,5};
cout<< b["sqx"][2]<<" "<<endl; //输出3
a.find("sqx");//查询是否存在key
return 0;
}
常用函数
1.reverse函数 *
/*
reverse函数
*/
#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;
int main()
{
vector<int> a({1,2,3,4,5});
int b[]={1,2,3,4,5};
reverse(a.begin(),a.end());
reverse(b,b+5); //reverse函数是前闭后开的!
for(int x : a){
cout << x <<" ";
}
cout<<endl;
for(int i=0;i<sizeof b;i++){
cout<< a[i] << " " ;
}
return 0;
}
2.unique函数
/*
unique函数
*/
#include<iostream>
#include<algorithm>
using namespace std;
int main(){
//去重数组
int a[] = {1,2,3,4,4,6,6,7,9};
int m = unique(a,a+9) - a ; //unique返回的是去重过后最后一个元素的下一个元素的指针!
//减去a是为了求得不重复的元素个数
for(int i=0 ; i< m ; i++) cout<<a[i]<<" ";
cout<<endl;
//去重vector
vector<int> b({1,2,3,4,4,6,6,7,9});
b.erase(unique(b.begin(),b.end()),b.end()); //将重复元素去除!
for(int x : b) cout<<x<<" ";
return 0;
}
3.random_shuffle函数
/*
random_shuffle函数
*/
#include<iostream>
#include<algorithm>
#include<vector>
#include<ctime>
using namespace std;
int main(){
//random_shuffle:打乱数组或Vector中的顺序!
vector<int> b({1,2,3,4,4,6,6,7,9});
srand(time(0)); //为随机种子传入时间参数,使得每次产生的随机结果都不一样!
random_shuffle(b.begin(),b.end());
for(int x : b) cout<<x<<" ";
cout<<endl;
return 0;
}
4.sort函数 *
/*
sort函数
*/
#include<iostream>
#include<algorithm>
#include<ctime>
#include<cstdio>
using namespace std;
//定义一个结构体类型数组
struct Rec{
int x,y;
}a[5];
//排序条件函数
bool cmp(int a,int b){ // a是否应该排在b的前面
return a<b; //如果a<b,那么a排在b的前面
}
bool cmp2(Rec a,Rec b){
return a.x<b.x; //按照结构体中的x的大小,从小到大排序
}
int main(){
//将随机序列排序sort
vector<int> b({1,2,3,4,4,6,6,7,9});
srand(time(0)); //为随机种子传入时间参数,使得每次产生的随机结果都不一样!
random_shuffle(b.begin(),b.end());
sort(b.begin(),b.end()); //排序 默认是从小到大排序!
for(int x : b) cout << x << " ";
cout << endl ;
//实现从大到小排序,添加参数 greater<int>()
sort(b.begin(),b.end(),greater<int>());
for(int x : b) cout << x << " ";
cout << endl ;
//自定义排序方式,添加自定义参数cmp
sort(b.begin(),b.end(),cmp);
for(int x : b) cout << x << " ";
cout << endl ;
//为自定义结构体类型数据排序
for(int i=0;i<5;i++){
a[i].x=-i; //初始化数组
a[i].y=i;
}
//遍历数组
for(int i = 0 ; i < 5 ; i++ ) printf("(%d,%d)",a[i].x,a[i].y);
cout << endl ;
sort(a,a+5,cmp2);
for(int i = 0 ; i < 5 ; i++ ) printf("(%d,%d)",a[i].x,a[i].y);
return 0;
}
5.二分函数
/*
lower_bound / upper_bound 二分函数
*/
#include<iostream>
#include<algorithm>
using namespace std;
int main(){
int a[] = {1,2,3,4,5,6};
int *p = lower_bound(a,a+6,x); //返回的是 >= x的第一个元素的指针 ,
//如果x大于6那么返回的是a.end(),是个随机数
cout<< *p <<endl;
return 0;
}
6.find函数 *
/*
find函数 :find()查找第一次出现的目标字符串(全匹配)
rfind() 反向查找字符串,即找到最后一个与子串匹配的位置(全匹配)(从前往后搜索)
*/
#include<iostream>
#include<cstdio>
using namespace std;
int main() {
string s1 = "abcdef";
string s2 = "de";
int ans = s1.find(s2);//在S1中查找子串S2
//int ans = s1.find(s2, 2);//从S1的第二个字符开始查找子串S2
cout << ans << endl;
return 0;
}
//输出结果:3
//find函数查到返回的是 第一个字符的索引!没查到返回-1
7.round函数
这里使用一个四舍五入函数round
对于小数而言,round()函数仅仅保留到整数位,即仅仅对小数点后一位四舍五入,
如果想要保留小数位数,则可以先乘后除
思考:4.850000保留一位小数就变成了4.8用的x=(a2+b3+c*4+d)/10,是精度问题吗?
用round函数可得4.9