STL容器从入门到精通的底层详解

序列式容器:可序式容器         数据无序

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语法详解

  • 6
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

怀化第一深情

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值