超详尽C++中的STL容器知识

适合c++新手

超级详细的stl容器知识,不怕你看不懂注释

关于stl容器概念的引入,c++中的容器stl相当于是一个封装好的数据结构知识,如果学过java的童鞋就可以更好的理解,stl相当于Java中已经封装好了的方法,只需要进行函数调用即可

学完C语言就可以看关于stl容器的相关,准备打算法比赛,必备stl的基础知识


STL
//stl容器的话都要在头文件中标注,比如#include<int>vector
vector				
	vector,有递增的思想:每次容器内存不够时,就把容器的大小copy一遍。内存大小乘二
注意:当系统为程序分配空间时,所需时间往往与空间大小无关,与申请次数有关
比如一次性申请内存为1的数组和申请内存为100的数组,时间花销一样
但是如果申请的内容为一百的数组和申请一百个内存为1的数组,其中的时间花销相差一百倍
所以我们引人vector的概念是为了减少次数

  int main() {
	// vector 
	// 定义vector 
	vector<int> va;
	vector<int>a[]//还可以存一个a的vector数组
	vector<int> vb(10); 
	//长度为10,并且每个元素都是3 
	vector<int> vc(10,3);
	//容器vector常见操作
	a.size()	返回元素个数
	//size他的时间复杂度是o(1)的,他的返回不是全部遍历一遍而是重新定义一个变量来储存
	a.empty()	返回是否为空
	size和empty是所有stl容器都有的-
	a.clear()	清空容器内的元素
	a.front()   返回a容器的第一个数
	a.back()	返回a最后一个数
	a.push_back   向容器a最后插入一个数
	a.pop_back()	是把a容器的最后一个数删掉
	//vector的迭代器  //可以看成指针
	迭代器的概念:迭代器的作用是用来访问容器(用来保存元素的数据结构)中的元素
	所以使用迭代器,我们就可以访问容器中里面的元素
	没错!这和访问数组这个序列的指针一样,因为数组范围内的指针就是迭代器的一种。
	a.begin()	begin是vector的第0个数
	a.end()		end是vector的最后一个数的后一个数 
	[]vector支持随机选址
	for(int i = 0;i < 10;i++) va.push_back(i);
	//定义一个vector,为10个数,每次插入一个i进去然后进行遍历
	// 三种遍历方式 
	1.for(int i = 0;i < 10;i++) printf("%d ",va[i]);//这是用数组下标进行遍历
	puts("");
	2.for(vector<int>::iterator i = a.begin();i != a.end();i++) //这是用数组下标进行遍历
	a.begin=a[0]第一个数 ,a.end=a[a.size()]最后一个数
	printf("%d ",*i);
	puts("");
	3.for(auto x : va)定义一个变量x并循环遍历va,将va遍历的值赋给新定义的x变量,这是c++11的新语法,代码更简洁
    printf("%d ",x);或者用cin<<x<<edl;//这里就是cin和printf的区别了
	puts("");
	//vector的一个黑科技,支持比较运算,按照字典序来比较
	比如vector<int>a(3,4),b(4,3)
	if(a>b)//判断a,b大小,因为4 4 4大于3 3 3 3所以b>a.所以输出put(“a<b”)
	
pair
//概念:比如某种东西有两种属性,就可以用一个pair来存。这两个属性可能需要按照某一种属性来排序
pair<int,int>p //这是pair的定义方式,表示定义了一个p的二元组,两个元素都是int型的
前后两个变量可以任意,比如一个可以是int型,一个是string型
	p.first 	想取得第一个元素 
	p.second	想取得第二个元素
	pair支持比较运算,按字典序,以first为第一关键字,second为第二关键字 
	// pair的操作
	比如先定义一个pair<int,string>  p;
	构造一个pair    p = make_pair(1,"cp");
	                或者p = {20,"cpcp"};
	
 	
string	
//概念:c++把字符串进行了封装,字符数组来存string的话有很多不方便的地方。而用string容器来存的话就很方便,
	string字符串,substr,c_str() 
	定义一个字符串
	常用的字符串string的操作
	size()	//返回字符串个数
	length()	//返回字符串长度
	empty()		//判断字符串是否为空
	clear()		//清空字符串
	// string的一个有意思的地方,可以定义一个字符串,然后在这个字符串的基础上在进行添加操作
	列如:
	string sa = "123";
	sa += "456";
	cout << sa << endl;		//结果为123456
	// 子串还有个有趣的操作就是返回定义的字串的值
	比如string a=123456”
	cout << a.substr(2,3) << endl;
	//这一句话的意思是返回定义的a的123456中开始位置为2开始遍历,返回的长度为3
			//返回的结果为345()
	因为string遍历的话和数组遍历是一样的,都是从0开始的,所以这里的2表示的其实是从第三个数开始返回,就是变量123456中的3的位置开始截取,从3往后截取三段为345
	还有种写法就是cout<<a.substr(1)<<endl;	//这样直接输出从位置1开始的所有字串
	// c_str(),字符串起始的长度 
	printf("%s\n",a.c_str());	//输出的是string.a存储字符数组的地址

queue		队列	
int<queue>
	queue<int>q	
	q.push()		向队尾插入一个元素 
	q.front()		返回队头元素
	q.back()		返回队尾元素 
	q.pop() 		弹出队头元素
	q.size()		返回队列元素个数
	q.empty() 	判断队列是否为空
	//注意:队列的性质的话,是从队尾插入,队头弹出
	 并且队列中没有clear操作,因此想要把队列弄空,就可以直接重新定义一下数组
	 q=queue<int>();
	 
priortity_queue 	优先队列,默认是大根堆 
	push()		插入一个元素 
	top()		返回堆顶元素 
	pop() 		弹出队头元素 	
	// 优先队列 
	priority_queue<int> heap;							// 大根堆 	
	priority_queue<int,vector<int,greater<int>> heap;	// 小根堆 
	
stack				栈	
	push() 		向栈顶插入元素 
	top()		返回栈顶元素 
	pop() 		弹出栈顶的元素 
	size()		返回栈内元素个数
	empty() 	判断栈内是否为空
	//没有clear函数
deque			双端队列
加强版的queue,但是缺点也很明显,就是运行速度比较慢
duque<int>q	 
	q.size()		返回双端队列的元素个数
	q.empty() 	判断是否为空
	q.clear()		清除队列内函数
	q.front()		返回第一个元素
	q.back()		返回最后一个元素
	q.push_back()	向最后插入一个元素
	q.pop_back()	弹出最后一个元素
	q.push_front()	队首插入一个元素
	q.pop_front()	队首弹出第一个元素
	q.begin()/q.end()   支持比较器
	[]
	 
	 
set,map,multiset,multimap	基于平衡二叉树(红黑树),动态维护有序序列 

	size()		返回相应的容器的元素个数
	empty()		判断是否为空
	clear()		清除该容器内的元素
	begin()/end()	++,--	返回前驱和后继 
	//前驱概念:一个有序序列的前驱表示有序序列的前面一个数。后继表示后面一个数
	
set/multiset
set<int>s:
注意:set里面不能有重复元素,如果向里面插入一个重复的元素,那么插入的这个操作就会被编译器自动忽略
multiset<int>ms;
multiset里面是可以有重复元素的
这是
		insert()	插入的是一个数
		find()		查找一个数,如果没有查找到就返回一个end的迭代返回迭代器
		count()		返回一个数的个数
		erase()
			(1)	输入是一个数X,删除所有的X	删除x的时间复杂度是O(k+logn) //这里的k是x的个数
			(2) 输入是一个迭代器,删除这个迭代器 
	set最核心的操作	lower_bound/upper_bound()
			lower_bound(x)	 返回大于等于x的最小的数的迭代器 如果不存在返回end
			upper_bound(x) 	 返回大于x的最小的数的迭代器

	
	// map
	map<string,int> ma;
	ma["cp"]  = 1;
	printf("%d",ma["cp"]);
	
	return 0;
}
	map/multimap
	map的大多操作的时间复杂度都是logn的,除了size,empty,clear之外,++,--也都是logn
	
		insert()	插入的是一个pair两个数,因为map存的是一个数的映射,实际是两个数
		erase() 	输入的是pair或者迭代器
		find()		查找一个数,如果没有查找到就返回一个end的迭代返回迭代器
		lower_bound/upper_bound()		也支持这个操作
		[] 			O(logn)
		map是一个数映射成另一个数,比如
		map<string,int>a这里是把string类型的映射成int整数变量a
		首先执行插入操作的话
		a["bug"]=1;		//这里就是把bug这个string类型的字符串映射成整数的1
		cout<<a["bug"]<<endl;	//这里就是查找操作,查找a
注意:map可以像数组一样用,但是时间复杂度为o(logn),数组直接取下标的话,时间复杂度是o(1)的
// 无序的 
unordered_set,unordered_map,unordered_multiset,unordered_multimap 	哈希表 
	和上面类似,增删改查的时间复杂度是O(1) 
	缺点不支持 lower_bound/upper_bound(),不支持排序的操作,因为他的内部是没有序的,也不支持迭代器的++,-- 
bitset		压位 
很多整数只需要知道整数部分是01
//比如想开一个长度为8的bool数组。c++的bool是一个字节,那么我们就需要8个字节,如果把它压到每一位中去,一位就是8字节,那么我们存这个就只需要一位了,大大节省了内存空间,使用的空间是普通的八分之一
定义
bitset<1000>s;	
前面的那些容器的<>中写的都是数据类型,而bitset容器中写的是大小具体的值
支持的操作:
~&|^等操作
>>,<<移位操作
==,!=
[]支持某一位取出来是01
还支持count()操作,返回有多少个1
any判断是否有一个1,对的话就是ture否则就是false
none判断是否全为0
set()把所有的位置成1
set(k,v)将k位变成v
reset()把所有位变成0
flip()等价于~
flip(k)1第k位取反

(不用特地去记,用的到了的时候查一下就可以了)
	
	
	


  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值