序列式容器:可序式容器 数据无序
vector数组
llist双向链表
deque双向动态队列
关系式容器:已序式容器 数据有序
map set
multimap multiset
容器必然有的功能:
增删改查
容器都有的函数:
构造 折构 插入 删除 查找 拷贝构造 元素个数
迭代器:用来定义容器中某个元素
数组 下标
链表 next
智能指针
vector
#include<bits/stdc++.h>
#include<vector>
using namespace std;
int main(){
int n;
cin >> n;
vector<int> vv(n+1);//开辟 n 个空间,全部初始化为 0
for(int i=1;i<=n;i++)cout<<vec[i]<<' ';
vector<int> vec, e[110];//动态添加
//clear() 清空容器
vec.clear();
for (int i = 1; i <= n; i++)
e[i].clear();//e->clear()是错的!
for (int i = 1; i <= n; i++) {
vec.push_back(3);//末尾放入
vec[i] = 2;//修改
}
vec.pop_back();//末尾删除
//insert,插入一个数到容器内某个位置,留给你们自行了解
//排序
sort(vec.begin(), vec.end());
for (int i = 1; i <= n; i++)
sort(e[i].begin(), e[i].end());
//查找
int t = lower_bound(vec.begin(), vec.end(), 3) - vec.begin();
//找到第一个大于等于3的数,返回它在vec容器内的下标,如果不存在会返回vec.end()
//删除,需要保证指针链接性
for (auto it = vec.begin(); it != vec.end();) {
if (*it == 4)it = vec.erase(it);//erase函数会返回删除该位的下一位的指针
it++;
}
//遍历,常用两种
for (int i = 0; i < vec.size(); i++)
cout << vec[i] << ' ';
cout << endl;
for (auto j : vec)cout << j << ' ';
//输出开头和末尾的数
cout << vec.front() << endl;
cout << vec.back();
return 0;
}
初始化vector并且初始化为0
#include<bits/stdc++.h>
using namespace std;
int n,m;
int main(){
cin>>n;
vector<int>vec(n+1);
for(int i=0;i<=n+1;i++)
cout<<vec[i]<<' ';
return 0;
}
vector的插入
注:
使用emplace_back函数可以减少一次拷贝或移动构造的过程,提升容器插入数据的效率,能使用emplace_back的场合就使用。
push_back也不是完全没用,某些场合获取到的就是已经构造好的对象,那就没必要再构造一次了,push_back进去就行了。
#include<bits/stdc++.h>
using namespace std;
int n,m;
int main(){
vector<int>a(3);
a[0]=2;
a[1]=2;
a[2]=3;
//插入尾部的操作
a.emplace_back(11);
a.push_back(66);
//插入头部的操作
a.insert(a.begin(),1);
//插入任意位置,n是想要插入的位置
//以3为例n可以是任意位置数字
int n=3;
a.insert(a.begin()+n,1);
for(int i=0;i<7;i++)
cout<<a[i]<<' ';
return 0;
}
vector的排序
与数组的排序相类似
#include<bits/stdc++.h>
using namespace std;
int n,m;
bool cmp(int a,int b){
return a>b;
}
int main(){
vector<int>a={44,55,88,4,2};
//sort(a.begin(),a.end());默认从小到大
sort(a.begin(),a.end(),cmp);
for(int i=0;i<a.size();i++){
cout<<a[i]<<' ';
}
reverse(a.begin(),a.end());//反转函数
for(auto j:a)cout<<j<<' ';
return 0;
}
vector中lower_bound二分查找函数
查找其大于一个数的第一个数返回的是其位置的指针
#include<bits/stdc++.h>
using namespace std;
int n,m;
int main(){
vector<int>a={44,55,88,99};
sort(a.begin(),a.end());
auto t=lower_bound(a.begin(),a.end(),1);
cout<<*t<<endl;
return 0;
}
#include<bits/stdc++.h>
using namespace std;
int n,m;
int main(){
vector<int>a={44,55,88,99};
sort(a.begin(),a.end());
int t=lower_bound(a.begin(),a.end(),45)-a.begin();
cout<<t;
return 0;
}
#include<bits/stdc++.h>
#include<algorithm>
using namespace std;
//lower_bound(二分函数)
int main(){
//找大于等于某数的第一个数,查找的数组必须有序
int n = 7;//7个数
int a[] = { 2,4,6,7,9,12,111 };//范围:0 ~ 6
int t = lower_bound(a, a + n, 8) - a;//数组中大于等于8的第一个数
if (t != n)//找不到会返回边界,边界是 7
cout << a[t] << endl;
int b[] = { 0,2,4,6,7,9,12,111 };//范围:1 ~ 7
t = lower_bound(b + 1, b + n + 1, 8) - b;
if (t != n + 1)//找不到会返回边界,边界是 8
cout << b[t] << endl;
return 0;
}
vector中unique去重
#include<bits/stdc++.h>
using namespace std;
int n,m;
int main(){
vector<int>a={44,44,55,55,44,44,88,99};
sort(a.begin(),a.end());//必须要排序否则只能去掉连续重复的
for(auto i:a)cout<<i<<" ";
// return 0;
cout<<endl;
a.erase(unique(a.begin(),a.end()),a.end());
for(auto i:a)cout<<i<<" ";
return 0;
}
vector中利用erase删除
#include<bits/stdc++.h>
using namespace std;
int n,m;
int main(){
vector<int>a={44,44,55,55,44,44,88,99};
sort(a.begin(),a.end());//必须要排序否则只能去掉连续重复的
for(auto it=a.begin();it!=a.end();){
if(*it==88)it=a.erase(it);
it++;
}
for(auto i:a)cout<<i<<" ";
return 0;
}
string
string a, b;
a.clear(), b.clear();//清空
cin >> a >> b;//输入a.push_back('b');//最末尾添加一个字符
a.pop_back();//删除最末尾一个字符a += b;//b字符串接到a后部,无 a -= b 语法
//遍历
for (int i = 0; i < a.size(); i++) {
cout << a[i] << ' ';//输出每个位置字符
a[i] = 'b';//修改
}//find,找到第一个 x 字符的下标
int t = a.find('a');//substr,取子串函数
string g = a.substr(0, 3);//0 下标开始包括此位置往后取 3 个字符
g = a.substr(3, 3);
g = a.substr(3);//3下标开始取到结束
引入例题查找子串个数
#include<bits/stdc++.h>
using namespace std;
int n,m;
int main(){
string s;
cin>>s;
int res=0;
for(int i=0;i<s.size();i++){
if(s.substr(i,8)=="chuanzhi")res++;
}
cout<<res;
return 0;
}
next_permutation、prev_permutation (全排列函数)
利用函数实现排列型枚举
#include<bits/stdc++.h>
using namespace std;
int n,m;
int main(){
cin>>n;
int a[n];
for(int i=0;i<n;i++){
a[i]=i+1;
}
do{
for(int i=0;i<n;i++){
cout<<a[i]<<' ';
}
cout<<"\n";
}while(next_permutation(a,a+n));
return 0;
}
#include<bits/stdc++.h>
#include<algorithm>
//next_permutation、prev_permutation (全排列函数)
using namespace std;
int main(){
int a[] = { 1,2,3 };//初始的序列,长什么样都行,无序、有重复元素也行
do
{
//每次输出比它本身字典序 大 一点的新排序
//(比它字典序大的所有排序中字典序最小的一个)
for (int i = 0; i < 3; i++)
cout << a[i];
cout << endl;
} while (next_permutation(a, a + 3));//这个数组的范围内
//逐步从大到小
cout << "---------------------------\n";
//处理完后数组恢复原样
for (int i = 0; i < 3; i++)
cout << a[i];
cout << endl << endl;
reverse(a, a + 3);
for (int i = 0; i < 3; i++)
cout << a[i];
cout << endl;
cout << "----------------------------\n";
do
{
//每次输出比它本身字典序 小 一点的新排序
//(比它字典序小的所有排序中字典序最大的一个)
for (int i = 0; i < 3; i++)
cout << a[i];
cout << endl;
} while (prev_permutation(a, a + 3));//逐步从小到大
return 0;
}
一个变量携带两个值的例子
#include<bits/stdc++.h>
#include<iostream>//pair
using namespace std;
int main(){
//一个变量携带两个值
pair<int, char> pii;
cin >> pii.first >> pii.second;
cout << pii.first << ' ' << pii.second;
//通常作为工具与其他容器结合使用
return 0;
}
栈
栈是先进后出的
#include<bits/stdc++.h>
#include<stack>//栈
int n;
using namespace std;
int main(){
cin>>n;
stack<int> sta;
for (int i = 0; i < n; i++)
sta.push(3);//插入
sta.push(5);
//遍历 + 删除
while (sta.size())
{
int t = sta.top();
cout << t << ' ';
sta.pop();
}
return 0;
}
队列
队列是先进先出的
#include<bits/stdc++.h>
#include<queue>//队列
int n;
using namespace std;
int main(){
queue<int> q;
cin>>n;
for (int i = 0; i < n; i++)
q.push(3);
q.push(5);
while (q.size())
{
int t = q.front();
q.pop();
cout << t << ' ';
}
return 0;
}
双端队列
双端队列貌似不存在先进先出和先进后出
#include<bits/stdc++.h>
#include<queue>//deque双端队列
using namespace std;
int n;
int main(){
deque<int> q;
q.clear();
cin>>n;
int t,g;
for (int i = 0; i < n; i++) {
q.push_front(2);//放前部
q.push_back(3);//放尾部
}
q.push_back(66);//头和尾必须同时插
q.push_front(66);
while (q.size())
{
t = q.front(), g = q.back();
cout << t << ' '<<g<<' ';
q.pop_back();//删后部
q.pop_front();//删前部
}
//q.clear();可以直接清空
return 0;
}
堆
主要是对最大最小的数字进行处理
#include<bits/stdc++.h>
using namespace std;
// priority_queue 优先队列、堆
int main(){
//自动排序内部数,小到大或大到小
priority_queue<int, vector<int>, greater<int>> q1;
//greater是小根堆,用vector装载内部元素
priority_queue<int, vector<int>, less<int>> q2;
//less是大根堆
q1.push(3), q2.push(2);
q1.push(2), q2.push(3);
while (q1.size())
{
int t = q1.top();//小根堆所以取出的数是所有数内最小的
q1.pop();
cout << t << ' ';
}
while (q2.size())
{
int t = q2.top();//小根堆所以取出的数是所有数内最大的
q2.pop();
cout << t << ' ';
}
return 0;
}
set、map
#include<bits/stdc++.h>
#include<set>//multimap、multiset相当于允许存储重复数据的map、set(无去重)
#include<map>//
using namespace std;
int main(){
//红黑树结构,可以自动排序去重
set<int> se;
int K;
//关键字 关键值
map<int, int> mp;//map相当于拥有了关键值的set
//插入
se.insert(3);//插入一个 3 关键字
mp.insert({ 1,2 });//插入一个 1 关键字,并给这个关键字的关键值赋值 2
mp.insert({ 1,1 });//因为 1 关键字已经存在,所以把关键值修改成 1
// mp.insert({ 1,2 }) 等价于
mp[1] = 2;
mp[1] += 2;//1 关键字的关键值 + 2
//遍历
for (auto j : se)cout << j << endl;
for (auto j : mp)
cout << j.first << ' ' << j.second << endl;//两个值
for (auto it = mp.begin(); it != mp.end(); it++)
cout << (*it).first << ' ' << (*it).second << endl;
//无括号会报错
for (auto it = se.rbegin(); it != se.rend(); it++)//反向遍历
cout << *it << endl;
//删除
mp.erase(3); se.erase(3);//删除关键字为 3 的元素
//如果是遍历删除 map 内特定的第 K 个数,跟 vector 删除一样要注意指针衔接
int k = 0;
for (auto it = mp.begin(); it != mp.end();k++) {
if(k == K)it = mp.erase(it);
else it++;
}
int t = mp.count(3);//返回指定元素出现的次数
t = mp.size();//返回map中元素的个数
//查找
auto j = mp.find(3);//查找 3 关键字在 map 内的下标
//如果不存在则 j == mp.end()
if (j != mp.end())cout << (*j).first;
auto g = mp.lower_bound(3);//查找 map 内第一个大于等于 3 的数的下标
//如果不存在则 g == mp.end()
if (g != mp.end())cout << (*g).first;
return 0;
}
set
#include<bits/stdc++.h>
using namespace std;
int main(){
set<int>a;
int n,t;
cin>>n;
while(n--){
cin>>t;
a.insert(t);
}
std::set<int>::iterator it=a.begin();
for(;it!=a.end();it++){
cout<<*it<<' ';
}
return 0;
}
se.clear();可以直接删除set
mp.clear();可以直接删除map
mp.find(3)返回一个指针auto t=mp.count(3);if(t!=mp.end())cout<<"有";
寻找前后数字if(t!=mp.end){
t++;t--;
}
mp.count(3)返回一个数字int g=mp.count(3);
map<pair<int,int>,int>mp;
储存方式
{1,2}
{2,3}
{4,4}
multimap、multiset
支持重复元素的map、set,用法一致
哈希表Hash
哈希是一种线性结构
#include<bits/stdc++.h>
#include<unordered_set>
#include<unordered_map>
//哈希表Hash
int n;
using namespace std;
int main(){
cin>>n;
unordered_map<int, int> ump;
unordered_set<int> ums;
//无自动排序,有去重,支持 O(1) 时间查找元素是否存在;map、set为 O(logn)
for (int i = 0; i < n; i++) {
ump.insert({ 1,2 });
ump[1] = 2;
ums.insert(3);
}
for (auto j : ump)cout << j.first << endl;
for (auto j : ums)cout << j << endl;
bool t = ump.count(3), g = ums.count(1);
//查找元素是否存在,存在就返回true,否则false
return 0;
}
借鉴至stl语法详解