温馨提示:本篇文章只给大家介绍初阶数据结构的一些常用接口
stl的简单介绍
什么是stl?
STL(standard template libaray-标准模板库):是C++标准库的重要组成部分,不仅是一个可复用的 组件库,而且是一个包罗数据结构与算法的软件框架
总结:一个可复用,同时又包含了数据结构和算法的软件框架。
STL的六大组件
vector篇(顺序表)
初始化部分
基本上的数据结构都离不开我们先前所讲的含参构造,无参构造,初始化列表
拷贝构造
迭代部分
begin
使用方式:对象名.begin();
作用:用于获取第一个元素的迭代器
end
使用方式:对象名.end();
作用:用于获取最后一个元素的迭代器
那么来看一下加了r后的变化
rbegin
使用方式:对象名.rbegin();
作用:用于获取最后一个元素
rend
使用方式:对象名.rend();
作用:用于获取第一个元素
从上面可以得知:加了r之后,我们可以发现rbegin与begin的作用完全相反,那么end和rend也是一样
容量部分
接口名 作用
size 获取数据个数
capacity 获取容量大小
empty 判断是否为空
resize 改变vector的size
reserve 改变vector的capacity
那么它们的使用方式也是对象名.接口名()
增删查改部分
接口名 作用
push_back 尾插
pop_back 尾删
find 查找
inser 在position之前插入val
erase 删除position位置的数据
swap 交换两个vector的数据空间
operator[ ] 像数组一样访问
小试牛刀
. - 力扣(LeetCode)
想必大家看到这题都会有思路,但是重点不在这里
从它的答题区我们可以看到不是和以前一样,那么这样就无从下手了吗?
其实它的核心逻辑我们依旧可以用,但是在使用核心逻辑之前我们需要给它来个初始化。
先前我们讲了resize是改变vector的长度,因此我们先定义一个二维数组,并且用for循环将二维数组内的每个元素进行初始化。最后就是再加上我们杨辉三角的核心逻辑,那么这样这道题就搞定了
源代码:
class Solution {
public:
vector<vector<int>> generate(int numRows) {
vector<vector<int>> ret(numRows);
for(int i = 0; i < numRows; i++)
{
ret[i].resize(i + 1, 0);
ret[i].front() = ret[i].back() = 1;
}
for(int i = 0; i < ret.size(); i++)
{
for(int j = 1; j < ret[i].size() - 1; j++)
{
ret[i][j] = ret[i - 1][j] + ret[i - 1][j - 1];
}
}
return ret;
}
};
那么这里给大家看个错误的代码
那么这个代码在哪里呢?它出错在ret[i].begin()和ret[i].end()。
其实这里有个易混淆的点
begin()&end() 与 front()&back()的区别
总结:begin()&end()返回的是迭代器,front()&back()返回的是变量的引用
拓展提升(了解)
list篇(链表)
这里的初始化部分都与vector的初始化相同,除此之外与vector相同的还有容量部分和增删查改部分。
常用的部分接口
函数声明 接口说明
(容量部分)
empty 检测list是否为空,是返回true,否则返回false
size 返回list中有效节点的个数
(迭代部分)
front 返回list的第一个节点中值的引用
back 返回list的最后一个节点中值的引用
(增删查改部分)
push_front 在list首元素前插入值为val的元素
pop_front 删除list中第一个元素
pop_back 删除list中最后一个元素
push_back 在list尾部插入值为val的元素
迭代器失效
概念:迭代器失效即迭代器所指向的节点的无效,即该节点被删除了。
稍微通俗一点地讲就是与野指针、空指针一样的道理。
“症状”:
错误的源代码:
当然在哪里出错上面的这张图片已经写出来了,那么具体是个什么情况我们来看下面这张图
从上面这张图中我们可以看到一个现象,在程序走完erase语句后it已经变成了一个随机数,那么此时再加加i自然也就会报错。
那么在写其他代码的时候如何发现这个错误,首先调试是第一,其次就是要有代码逻辑上的辅助,一步一步去推断。
正确源代码:
stack篇(栈)
接口名 作用
stack() 构造空的栈
empty() 检测stack是否为空
size() 返回stack中元素的个数
top() 返回栈顶元素的引用
push() 将元素val压入stack中
pop() 将stack中尾部的元素弹出
那么以上也是stack的基本接口,还有一些接口与vector的类似,具体的可以自行去官方文档查找
queue篇(队列)
函数声明 接口说明
queue() 构造空的队列
empty() 检测队列是否为空,是返回true,否则返回false
size() 返回队列中有效元素的个数
front() 返回队头元素的引用
back() 返回队尾元素的引用
push() 在队尾将元素val入队列
pop() 将队头元素出队列
那么以上也是queue的基本接口,还有一些接口与vector的类似,具体的可以自行去官方文档查找
priority_queue的介绍和使用
那么这里需要知道的是priority_queue是一个容器,并且是优先队列。
函数声明 接口说明
priority_queue()/priority_queue(first, last) 构造一个空的优先级队列
empty( ) 检测优先级队列是否为空,是返回true,否则返回false top( ) 返回优先级队列中最大(最小元素),即堆顶元素 push(x) 在优先级队列中插入元素x pop() 删除优先级队列中最大(最小)元素,即堆顶元素
deque的简单介绍(了解)
deque(双端队列):是一种双开口的"连续"空间的数据结构
dequeue的优缺点
优点
1. 头部插入和删除时,不需要搬移元素,效率特别高,而且在扩 容时,也不需要搬移大量的元素,因此其效率是比vector高的。
2. 与list比较,其底层是连续空间,空间利用率比较高
缺点
1. 不适合遍历
原因:dequeue的迭代器需要频繁检查其是否移动到了某段空间的边界
拓展介绍
什么是适配器
概念:适配器是一种设计模式,这个设计模式是一套被反复使用的、多数人知晓的、经过分类编目的、代码设 计经验的总结
作用:将一个类的接口转换成客户希望的另外一个接口。
那么基本上的容器也都讲完了,除了一个string和剩余没讲的几个接口外,不过string我也尽量从开一篇文章进行讲解,那么本篇文章就先到这里,我们下期再见!!!
都看到这里了,给个三连呗,谢谢啦!!!