2024年【C++】 STL详解_c+,系列教学

img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上C C++开发知识点,真正体系化!

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新

如果你需要这些资料,可以戳这里获取

front(),back(),下标[]运算符

十一:向量 vector

  1. 向量属于顺序容器,用于容纳不定长线性序列(即线性群体),提供对序列的快速随机访问(也称直接访问)

  2. 数据结构很像一个数组,所以与其他容器相比,vector 能非常方便和高效访问单个元素,支持随机访问迭代子

  3. 向量是动态结构,它的大小不固定,可以在程序运行时增加或减少

与数组不同,向量的内存用尽时,向量自动分配更大的连续内存区,将原先的元素复制到新的内存区,并释放旧的内存区;这是向量类的优点

头文件:#include

vector 基本操作

(1)头文件

#include

(2)创建vector对象

vector vec;

(3)尾部插入数字

vec.push_back(a);

(4)使用下标访问元素

cout<<vec[0]<<endl;记住下标是从0开始的

(5)使用迭代器访问元素

vector::iterator it;

for(it=vec.begin();it!=vec.end();it++)

cout<<*it<<endl;

(6)插入元素

vec.insert(vec.begin()+i,a);在第i+1个元素前面插入a;

(7)删除元素

vec.erase(vec.begin()+2);删除第3个元素

vec.erase(vec.begin()+i,vec.end()+j);删除区间[i,j-1];区间从0开始

(8)向量大小

vec.size();

vec.resize;改变大小

(9)清空

vec.clear();

vector,使用示例如下

#include <iostream>
#include <iomanip>
#include <vector>	//包含向量容器头文件
using namespace std ;
void main(){    
	vector<int>  A(10);	  //创建vector对象
	int n;	
	int primecount = 0, i, j;
	cout<<"Enter a value>=2 as upper limit: ";
	cin >> n;
	A[primecount++] = 2;//下标法访问元素
	for(i = 3; i < n; i++){ 
		if (primecount == A.size())	
			A.resize(primecount + 10); //改变容器大小
        if (i % 2 == 0)
			continue;
		j = 3;
 		while (j <= i/2 && i % j != 0)
			j += 2;        
		if (j > i/2) A[primecount++] = i;
	}
	for (i = 0; i<primecount; i++){//输出质数
		cout<<setw(5)<<A[i]; 
		if ((i+1) % 10 == 0) //每输出10个数换行一次
			cout << endl;
	} 
	cout<<endl;
}

十二:双端队列 queue

双端队列是一种放松了访问权限的队列

元素可以从队列的两端入队和出队,也支持通过下标操作符“[]”进行直接访问

与向量的对比:

功能上:和向量没有多少区别,

性能上:在双端队列起点上的插入和删除操作快

头文件:#include

十三:列表 list

链表主要用于存放双向链表,可以从任意一端开始遍历。链表还提供了拼接(splice)操作,将一个序列中的元素从插入到另一个序列中

对比:

元素的插入和删除操作对 list 而言尤为高效

与 vector 和 deque 相比,对元素的下标访问操作的低效是不能容忍的,因此 list 不提供这类操作

头文件:#include

列表,使用示例如下

#include <iostream>
#include <list>
using namespace std ;
int main(){
	list<int> Link;	//构造一个列表用于存放整数链表
	int i, key, item;    
	for(i=0;i < 10;i++)// 输入10个整数依次向表头插入{
		cin>>item;
		Link.push_front(item);
	}
	cout<<“List: ”; // 输出链表
	list<int>::iterator p=Link.begin();
    while(p!=Link.end()){ //输出各节点数据,直到链表尾
		cout <<*p << "  ";
		p++;  //使P指向下一个节点
	}
	cout << endl;
	cout << "请输入一个需要删除的整数: ";
	cin >> key;
	Link.remove(key);   
	cout << "List: "; // 输出链表
	p=Link.begin();	// 使P重新指向表头
	while(p!=Link.end()){ 
		cout <<*p << "  ";
		p++; // 使P指向下一个节点
	}
	cout << endl;
}

十四:关联容器

通过保存在数据项中的索引项,尽可能快速检索数据项

STL标准库中只包含有序关联容器set、multiset、map、multimap

**set, multiset:**数据项就是索引项; multiset允许出现重复的索引项

**map, multimap:**数据项是由索引项和其他某种类型的数据组成的一对数据; multimap允许出现重复的索引项

十五:map

  1. 增加和删除节点对迭代器的影响很小。对于迭代器来说,可以修改实值,而不能修改key

  2. 自动建立Key - value的对应。key 和 value可以是任意你需要的类型

  3. 根据key值快速查找记录,查找的复杂度基本是Log(N),如果有1000个记录,最多查找10次,1,000,000个记录,最多查找20次

map的构造函数

  1. 使用map得包含map类所在的头文件
         #include

  2. map对象是模板类,需要关键字和存储对象两个模板参数:
          map<int, string> personnel;//用int作为索引,存储string对象

map的成员函数

  1. map类已经对[]操作符进行了重载

  2. 插入2时,先在enumMap中查找主键为2的项,没发现,然后将一个新的对象插入enumMap,键是2,值是一个空字符串,插入完成后,将字符串赋为“Two”;

  3. 但是该方法会将每个值都赋为缺省值,然后再赋为显示的值,如果元素是类对象,则开销比较大。可以用以下insert()来避免开销

  4. 下标操作符给出了获得一个值的最简单方法:

CString tmp = enumMap[2];

但是,只有当map中有这个键的实例时才对,否则会自动插入一个实例,值为初始化值

  1. 我们可以使用Find()和Count()方法来发现一个键是否存在

  2. 查找map中是否包含某个关键字条目用find()方法,传入的参数是要查找的key

  3. 通过map对象的方法获取的iterator数据类型是一个std::pair对象,包括两个数据 iterator->first 和 iterator->second 分别代表关键字和存储的数据

从map中删除元素

  1. 移除某个map中某个条目用erase()

  2. 该成员方法的定义如下

iterator erase(iterator it);              //通过一个条目对象删除
iterator erase(iterator first, iterator last);//删除一个范围

size_type erase(const Key& key);   //通过关键字删除

例如:

enumMap.erase(1);//删掉关键字“1”对应的条目
enumMap.erase(enumMap.begin());//删掉第一个条目
enumMap.erase(enumMap.begin(), enumMap.begin() + 2);//删掉起始的两个条目

3. clear()就相当于

 enumMap.erase(enumMap.begin(), enumMap.end()); 

map,使用示例如下

#include <map>
#include <iostream>
#include <string>
using namespace std;
void main(){
	map< string, string > trans_map;
	typedef map< string, string >::value_type valType;
	trans_map.insert( valType( "001", "grateful" ));
	trans_map.insert( valType( "002", "them" ));
	trans_map.insert( valType( "003", "because" ));
	trans_map.insert( valType( "004", "no" ));
	trans_map.insert( valType( "005", "says" ));
	trans_map.insert( valType( "006", "thanks" ));
	trans_map.insert( valType( "007", "was" ));
    trans_map.insert( valType( "008", "suppose" ));	
	map< string,string >::iterator it;
	cout << "Here is our transformation map: \n\n";
	for(it=trans_map.begin();it!=trans_map.end();++it)
		cout<<"key: "<<(*it).first<<"\t"<<"value: " <<(*it).second<<"\n";
	cout<<"Find Key:005"<<endl;
	it=trans_map.find("105");
	if (it==trans_map.end()){
		cout<<"not found"<<endl;
	}
	else{
		cout<<"key: "<<(*it).first <<"\t"<<"value: " <<(*it).second<<"\n";
	}
}

十六:multimap

multimap 除了元素对的关键字不是唯一外,与 map 相似

头文件:#include

十七:set

set 可以被视为只有关键字而没有相关的元素值的 map,因此 set 的用户接口也发生了微小的变化:成员类型中没有:

typedef Key value_type;

typedef Cmp value_compare

操作中没有元素的下标访问操作

头文件:#include

十八:multiset

multiset 除了关键字不是唯一外,与 set 相似

头文件:#include

十九:迭代器

迭代器是面向对象版本的指针

指针可以指向内存中的一个地址

迭代器可以指向容器中的一个位置

STL的每一个容器类模版中,都定义了一组对应的迭代器类。使用迭代器,算法函数可以访问容器中指定位置的元素,而无需关心元素的具体类型

迭代器的类型

1. 输入迭代器

可以用来从序列中读取数据

2. 输出迭代器

允许向序列中写入数据

3. 前向迭代器

既是输入迭代器又是输出迭代器,并且可以对序列进行单向的遍历

4. 双向迭代器

与前向迭代器相似,但是在两个方向上都可以对数据遍历

5. 随机访问迭代器

也是双向迭代器,但能够在序列中的任意两个位置之间进行跳转

迭代器的类型表

迭代器,使用示例

#include <list>
#include <iostream>
using namespace std;
int main(){
	int i,key;
	list<int> intList;	
	list<int>::iterator it;
	cout<<"input 5 digit:";
	for(i=0;i<5;i++){
		cin>>key;
		intList.push_front(key);
	}	
    cout<<"data list:"<<endl; 	
	it=intList.end();
	while(1){
		cout.width(6);
		cout<<*(--it);
		if(it==intList.begin())
			break;
	}
	return 0;
}

二十:函数对象

  1. 一个行为类似函数的对象,它可以没有参数,也可以带有若干参数,其功能是获取一个值,或者改变操作的状态

  2. 任何普通的函数和任何重载了调用运算符operator()的类的对象都满足函数对象的特征

  3. STL中也定义了一些标准的函数对象,如果以功能划分,可以分为算术运算、关系运算、逻辑运算三大类;为了调用这些标准函数对象,需要包含头文件

二十一:已经集成的函数对象

二十二:自定义函数对象

#include <iostream>
using namespace std;
class CFunObj{
public:
	void operator()(){
		cout<<"hello,function object!"<<endl;
	}
	int operator()(int i){
		cout<<"hello, function object other!"<<endl;
		return i+1;
	}
private:
	int dat;
};

void main(){
	CFunObj fo;
	fo();
	cout<<fo(1)<<endl;
	//CFunObj()();
}	

二十三:标准C++库中的算法

  1. 算法本身是一种函数模板

  2. 不可变序列算法(non-mutating algorithms)

不直接修改所操作的容器内容的算法

  1. 可变序列算法(mutating algorithms)

可以修改它们所操作的容器的元素

  1. 算法部分主要由头文件,和组成

二十四:STL算法的头文件

是所有STL头文件中最大的一个,它是由一大堆模版函数组成的,可以认为每个函数在很大程度上都是独立的,其中常用到的功能范围涉及到比较、交换、查找、遍历操作、复制、修改、移除、反转、排序、合并等等

体积很小,只包括几个在序列上面进行简单数学运算的模板函数,包括加法和乘法在序列上的一些操作

中则定义了一些模板类,用以声明函数对象

二十五:标准函数

二十六:泛型算法例子

#include <iostream>
#include <vector>
#include <algorithm>
#include <iterator>


![img](https://img-blog.csdnimg.cn/img_convert/68fc1948463672cd58c172cca0319c45.png)
![img](https://img-blog.csdnimg.cn/img_convert/48c3498445343d76a07c54d377e9b27f.png)

**网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。**

**[需要这份系统化的资料的朋友,可以添加戳这里获取](https://bbs.csdn.net/topics/618668825)**


**一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!**

0fce41438e2af357a698bcab.png)


![](https://img-blog.csdnimg.cn/25f8ea52663f4ce982f5239436c7aeda.png)


![](https://img-blog.csdnimg.cn/4833063c2ae140ce9d945625fa607050.png)


![](https://img-blog.csdnimg.cn/e53efb4fd12e4b9e94696e8677bf8091.png)


![](https://img-blog.csdnimg.cn/3e51b20798834b96aece9d4be442ca71.png)


## 二十六:泛型算法例子



#include
#include
#include
#include

[外链图片转存中…(img-xPCN2SFI-1715750483346)]
[外链图片转存中…(img-ekLKXp2K-1715750483346)]

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以添加戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

  • 5
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值