2024年C C++最新【C++】STL—(5),2024年最新原理讲解

img
img

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

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

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

}


### size函数


**返回list中有效节点的个数。**



#include
#include
using namespace std;
int main()
{
list l1(5,3);
cout << l1.size() << endl;//5
}


### resize函数


**扩容并且初始化。**


resize函数和之前的string类和vector类函数的resize函数规则差不多:


* 当所给值大于当前的size时,将size扩大到该值,并且将扩大的数据初始化为第二个参数所给值,若未给出,则默认为容器所存储类型的默认构造函数所构造出来的值;
* 当所给值小于当前的size时,将size缩小到该值。



#include
#include
using namespace std;

int main()
{
list l1(2, 6);
for (auto e : l1)
{
cout << e << " ";
}
cout << endl; //6 6
l1.resize(4, 8); //将size扩大到4并且将扩大的值初始化为8
for (auto e : l1)
{
cout << e << " ";
}
cout << endl; //6 6 8 8
l1.resize(2); //将size缩到2
for (auto e : l1)
{
cout << e << " ";
}
cout << endl; //6 6
return 0;
}


## 插入和删除操作




| 函数声明 | 接口说明 |
| --- | --- |
| **push\_back** | **尾插** |
| **push\_front** | **头插** |
| **pop\_front** | **头删** |
| **pop\_back** | **尾删** |
| **insert** | **在指定的迭代器位置或区间插入数据** |
| **erase** | **删除指定迭代器位置或迭代器区间的数据** |
| swap | 交换两个list中的元素 |
| **clear** | **清除list中的所有元素** |


### push\_back和pop\_back


push\_back是尾插,pop\_back尾删。


使用:


下面的代码功能是依次在list尾部插入数据 1 2 3 4 5 6 7,插入完成之后打印;


打印之后再从尾部删除数据7 和 6:



#include
#include
using namespace std;
int main()
{
list l1;
for (int i = 1; i < 8; i++)
{
l1.push_back(i);
}
for (auto e : l1)
{
cout << e << " ";
}
cout << endl;
//1 2 3 4 5 6 7
l1.pop_back();
l1.pop_back();
for (auto e : l1)
{
cout << e << " ";
}
cout << endl;
//1 2 3 4 5
}


### push\_front和pop\_front


**头插和头删。**


使用:



#include
#include
using namespace std;
int main()
{
list l1;
for (int i = 1; i < 8; i++)
{
l1.push_front(i);
}
for (auto e : l1)
{
cout << e << " ";
}
cout << endl;
//7 6 5 4 3 2 1
l1.pop_front();
l1.pop_front();
for (auto e : l1)
{
cout << e << " ";
}
cout << endl;
// 5 4 3 2 1
}


### insert函数



//在指定的迭代器位置插入数据
iterator insert (iterator position, const value_type& val);
//在指定的迭代器位置插入n个val值
void insert (iterator position, size_type n, const value_type& val);
//在指定迭代器位置插入一段迭代器区间(左闭右开)
template
void insert (iterator position, InputIterator first, InputIterator last);


**在指定的迭代器位置插入数据**



iterator insert (iterator position, const value_type& val);


使用:



#include
#include
using namespace std;
int main()
{
list l1;
l1.push_back(0);
auto it = l1.begin();
l1.insert(it, 100);//在头部插入值100
for (auto e : l1)
{
cout << e << " ";
}
cout << endl;
//输出100 0
}


**在指定的迭代器位置插入n个val值**



void insert (iterator position, size_type n, const value_type& val);


使用:



#include
#include
using namespace std;
int main()
{
list l1;
l1.push_back(0);
auto it = l1.begin();
l1.insert(it,3, 100);//在头部插入3个值为100的数据
for (auto e : l1)
{
cout << e << " ";
}
cout << endl;
//输出100 100 100 0
}


**在指定迭代器位置插入一段迭代器区间**


凡是和迭代器相关的基本上都是左闭右开。



#include
#include
using namespace std;
int main()
{
list l1;
list l2(4, 5);
auto it = l1.begin();
l1.insert(it,l2.begin(),l2.end());//在头部插入l2的begin到end的数据,左闭右开
for (auto e : l1)
{
cout << e << " ";
}
cout << endl;
//输出5 5 5 5
}


### erase函数



//删除指定迭代器位置的值
iterator erase (iterator position);
//删除指定迭代器区间的值
iterator erase (iterator first, iterator last);


使用:



#include
#include
using namespace std;
int main()
{
list l1;
for (int i = 1; i < 8; i++)
{
l1.push_front(i);
}
for (auto e : l1)
{
cout << e << " ";
}
cout << endl;
//输出7 6 5 4 3 2 1
// 删除指定迭代器位置
//删除数据5
auto it = find(l1.begin(), l1.end(), 5);//使用find函数查找
l1.erase(it);
for (auto e : l1)
{
cout << e << " ";
}
cout << endl;
//输出7 6 4 3 2 1

//删除指定迭代器区间
//删除从6到2之间的数据,左闭右开,所以要找到指向数据1的迭代器
auto it1 = find(l1.begin(), l1.end(), 6);
auto it2 = find(l1.begin(), l1.end(), 1);
l1.erase(it1,it2);
for (auto e : l1)
{
	cout << e << " ";
}
cout << endl;
//输出7 1

}


前面说过,此处大家可将迭代器暂时理解成类似于指针,**迭代器失效即迭代器所指向的节点的无效,即该节点被删除了。因为list的底层结构为带头结点的双向循环链表,因此在list中进行插入时是不会导致list的迭代器失效的,只有在删除时才会失效,并且失效的只是指向被删除节点的迭代器,其他迭代器不会受到影响**。


**所以erase()函数执行后,所指向的节点已被删除,迭代器失效,所以在下一次使用时,必须先给其赋值。**


### swap函数


**交换两个list中的元素**



void swap (list& x);


使用:



#include
#include
using namespace std;
int main()
{
list l1(2,6);
list l2(4, 5);
//遍历l1
for (auto e : l1)
{
cout << e << " ";
}
//输出6 6
cout << endl;
//遍历l2
for (auto e : l2)
{
cout << e << " ";
}
//输出5 5 5 5
cout << endl;

l1.swap(l2);//交换l1和l2

//遍历l1
for (auto e : l1)
{
	cout << e << " ";
}
//输出5 5 5 5 
cout << endl;
//遍历l2
for (auto e : l2)
{
	cout << e << " ";
}
//输出6 6
cout << endl;

}


### clear函数


**清除list中的所有元素**



void clear();


使用:



#include
#include
using namespace std;
int main()
{
list l1(2,6);
//遍历l1
for (auto e : l1)
{
cout << e << " ";
}
//输出6 6
l1.clear();//清除l1中元素

for (auto e : l1)
{
	cout << e << " ";
}
//什么也不输出

}


## 迭代器


**我们可以将迭代器理解成指针,指向list中的某个节点。**




| 函数声明 | 接口说明 |
| --- | --- |
| begin + end | 返回第一个元素的迭代器+返回最后一个元素下一个位置的迭代器 |
| rbegin + rend | 返回第一个元素的reverse\_iterator,即end位置,返回最后一个元素下一个位置的 reverse\_iterator,即begin位置 |


**迭代器都是左闭右开**


### begin和end函数


使用:



#include
#include
#include
using namespace std;
int main()
{
list l1;
for (int i = 0; i < 5; i++)
{
l1.push_back(i);
}
//正向迭代器的使用
//正向遍历
list::iterator it = l1.begin();
while (it != l1.end())//遍历
{
cout << *it << " ";
it++;
}
//输出 0 1 2 3 4
cout << endl;
}


### rbegin和rend函数



#include
#include
#include
using namespace std;
int main()
{
list l1;
for (int i = 0; i < 5; i++)
{
l1.push_back(i);
}
//反向迭代器的使用
//反向遍历
list::reverse_iterator rit = l1.rbegin();
while (rit != l1.rend())
{
cout << *rit << " ";
rit++;
}
//输出 4 3 2 1 0
cout << endl;
}


## 元素获取




| 函数声明 | 接口说明 |
| --- | --- |
| front | 返回list的第一个节点中值的引用 |
| back | 返回list的最后一个节点中值的引用 |


### front函数


**front函数用于获取list容器当中的第一个元素的引用(能够修改元素)。**


使用:



#include
#include
using namespace std;
int main()
{
list l1(2,6);
//遍历l1
for (auto e : l1)
{
cout << e << " ";
}
//输出6 6
cout << l1.front() << endl;//获取第一个元素,输出6
l1.front() = 100; //获取第一个元素并将第一个元素改为100

for (auto e : l1)
{
	cout << e << " ";
}
//输出100 6

}


### back函数


**back函数用于获取list容器当中的最后一个元素(能够修改元素)。**


使用:



#include
#include
using namespace std;
int main()
{
list l1(2,6);
//遍历l1
for (auto e : l1)
{
cout << e << " ";
}
//输出6 6
cout << l1.back() << endl;//获取最后一个元素,输出6
l1.back() = 100; //获取最后一个元素并将其改为100

for (auto e : l1)
{
	cout << e << " ";
}
//输出 6 100

}


## 操作函数




| 函数声明 | 接口说明 |
| --- | --- |
| sort | 将容器当中的数据默认排为升序 |
| remove | 删除容器中指定值的元素 |
| remove\_if | 删除容器中满足条件的元素 |
| unique | 删除容器当中连续的重复元素 |
| reverse | 将容器当中元素的位置进行翻转逆置 |
| assign | 新内容分配给容器替换容器当前内容 |
| splice | 两个list容器之间的拼接 |


### sort函数


算法库中的sort函数代码如下:是通过指针相减算出来的,而list容器不是连续的地址所以这种算法对于list来说并不适用。


![image-20230701160438900](https://img-blog.csdnimg.cn/img_convert/a6158664bcc90c87f62252c91fd0990b.png)


list容器中的sort函数使用的是归并排序,算法库中的sort使用的是快排,快排是三个数取中间数同样不适用list。


从功能上来说迭代器要分三类:


1.单向迭代器 ++


2.双向迭代器(list) ++ –


3.随机迭代器(vector string) ++ – + -


在函数使用的时候如果模板中是双向不能使用单向,如果是单向可以传随机和双向。


算法库中的sort函数迭代器要传随机迭代器:


![image-20230701160750349](https://img-blog.csdnimg.cn/img_convert/252abe66294d835970dd9b3aa91aa468.png)


sort函数使用:



#include
#include
using namespace std;
int main()
{
list l1;
//遍历l1
for (int i = 13; i >= 3; i–)
{
l1.push_back(i);
}
//输出6 6

for (auto e : l1)
{
	cout << e << " ";
}
//输出13 12 11 10 9 8 7 6 5 4 3
l1.sort();
for (auto e : l1)
{
	cout << e << " ";
}
//输出 3 4 5 6 7 8 9 10 11 12 13

}


但是在实际中我们很少使用list的sort排序,因为性能不行。


比较vector和list容器的sort排序时间:



#include
#include
#include
#include
using namespace std;
int main()
{

//list和vector的sort函数性能测试
srand(time(nullptr));
list<int> l1;
vector<int> v1;
const int N = 1000000;

v1.reserve(N);
for (int i = 0; i < N; i++)
{
	auto e = rand();//随机数
	v1.push\_back(e);//插入
	l1.push\_back(e);//插入
}
int begin1 = clock();
sort(v1.begin(), v1.end());
int end1 = clock();
int begin2 = clock();
l1.sort();
int end2 = clock();
cout << "vector sort:" << (end1 - begin1) << endl;//vector排序时间
cout << "list sort:" <<  (end2 - begin2) << endl;//list排序时间

在release下进行测试:


![image-20230701162113993](https://img-blog.csdnimg.cn/img_convert/3eaab984e644475d2f5e975ae6bfea5d.png)


我们再尝试先将list容器中的数据放在vector中,然后再排序,排完序之后再放到list容器中:



#include
#include
#include
#include
using namespace std;
int main()
{

//list和vector的sort函数性能测试
srand(time(nullptr));
list<int> l1;
vector<int> v1;
const int N = 1000000;

v1.reserve(N);
for (int i = 0; i < N; i++)
{
	auto e = rand();//随机数
	v1.push\_back(e);//插入
	l1.push\_back(e);//插入
}
//vector排序时间
int begin1 = clock();
sort(v1.begin(), v1.end());
int end1 = clock();

img
img

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

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

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

include
#include
#include
#include
using namespace std;
int main()
{

//list和vector的sort函数性能测试
srand(time(nullptr));
list<int> l1;
vector<int> v1;
const int N = 1000000;

v1.reserve(N);
for (int i = 0; i < N; i++)
{
	auto e = rand();//随机数
	v1.push\_back(e);//插入
	l1.push\_back(e);//插入
}
//vector排序时间
int begin1 = clock();
sort(v1.begin(), v1.end());
int end1 = clock();

[外链图片转存中…(img-iXiOcccU-1715556045410)]
[外链图片转存中…(img-Rune09yp-1715556045411)]

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

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

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

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值