前言
上一章节主要是详细介绍了C++泛型编程基础,不清楚的可以回顾一下哦。本章节主要针对于C++STL(标准模板类库)做个详细介绍。标准模板类库也就是别人写的模板类,主要内容是各种数据结构的封装,以及常用算法。暂时分三个章节介绍,本章节主要介绍容器篇。
容器总括
序列式容器(sequence containers)
array(
: 定长数组。c++11以上版本
)vector
vector
: vector的bool特化。forward_list(
c++11以上版本
)
: 单链表。list
:双向链表。
deque
:双端动态数组。
关联式容器(associative containers)
set(multiset)
: 有序集合,键和值相同。map(multimap)
: 有序集合,键对应值。
哈希表(hash table) (c++11以上版本
)
unordered_set(unordered_multiset)(
: 无序集合,key == value, 特性与unordered_map类似c++11以上版本
)unordered_map(unordered_multimap)(
: 无序集合,单独访问某个元素较快,从头到尾遍历效率会低于mapc++11以上版本
)
容器适配器(container adapters)
stack
: 栈queue
: 队列priority_queue
: 优先队列bitset
: 位组
本章节主要介绍以下几种容器的基本用法:
适配器容器
因为这些容器都是基于其他标准容器实现的所以叫做容器的适配器,具体的有stack,queue,priority_queue,默认的情况下,stack和queue基于deque而实现的,priority_queue在vector上实现的,可以根据第二个实参指定容器的类型,但一定要符合标准,queue要求要有push_front操作因此不能建立在vector上面,priority_front要求有随机访问的功能,因此建立在vector上面。优先级队列默认情况下是大顶堆,也就是大者优先级高,后面可以自定义优先级比较规则,当然这些东西大家了解一下即可,更多是掌握这些适配器容器的使用。
1stack容器stack是栈结构,栈是一种FILO(先进后出)结构,从容器中拿数据必须按照FILO的方式。stack主要成员函数有以下几个:
empty()
:栈为空则返回真pop()
: 移除栈顶元素push()
: 在栈顶增加元素size()
: 返回栈中元素数目top()
: 返回栈顶元素
使用实例代码如下:求解一个数字的二进制
2queue容器queue是队列结构,队列是一种FIFO(先进先出)结构,从容器中拿数据必须按照FIFO的方式。queue主要成员函数有以下几个:
empty()
:队列为空则返回真pop()
: 移除队头元素push()
: 在队尾增加元素size()
: 返回队中元素数目front()
: 返回队头元素
使用实例代码如下:描述点赞,转发,评论 三连操作
3priority_queue容器priority_queue是优先队列,一般我们都需要自己重写比较准则,相对于上面两种容器来说稍微麻烦一点。优先队列具有队列的所有特性,包括队列的基本操作,只是在这基础上添加了内部的一个排序,它本质是一个堆实现的。主要成员函数和queue基本差不多,主要有以下几个:
top()
:访问队头元素empty()
:队列是否为空size()
: 返回队列内元素个数push()
: 插入元素到队尾 (并排序)emplace()
: 原地构造一个元素并插入队列pop()
: 弹出队头元素swap()
:交换内容
优先队列主要用来做大顶堆和小顶堆使用,因为出队是根据优先权去出队的。案例代码如下:
priority_queue , greater >
int: 操作的数据类型
vector: 操作的容器
greater: 比较准则 大于
在优先队列操作自定义类型的时候通常是重写比较准则来实现排序效果。这个一定要注意。
序列式容器
所谓序列容器,即以线性排列(类似普通数组的存储方式)来存储某一指定类型(例如 int、double 等)的数据,需要特殊说明的是,该类容器并不会自动对存储的元素按照值的大小进行排序。需要注意的是,序列容器只是一类容器的统称,并不指具体的某个容器,本文序列式容器只介绍array,vector,以及list。
1array容器array是定长数组,此类容器一旦建立,其长度就是固定不变的,这意味着不能增加或删除元素,只能改变某个元素的值,案例代码如下:
2vector容器vector是动态数组,在没有确定数组长度的时候,不能采用下标法进行插入元素,只能采用push_back的成员函数进行插入元素,vector常用成员函数如下:
assign(beg,end)
:赋值区间[beg,end]元素到容器assign(n,elem)
:n个elem复制到容器at(index): 访问index序号的元素
clear()
: 清除容器中的元素erase(index): 删除index序号的元素
empty(): 判断容器是否为空
push_back(elem):尾部插入元素elem
size():容器元素个数
back():容器最后一个元素
动态数组vector和数组类似,并不是很复杂,案例代码如下:
3list容器
list容器是双向链表,类似于C语言中写的双向链表,操作很简单,常用成员函数如下:
front()
:链表头部元素back()
:链表尾部元素size()
: 链表中元素个数empty()
: 链表是否为空push_back(elem)
: 尾插法push_front(elem)
: 头插法pop_back:尾删法
pop_front()
: 头插法insert(iter): 指定位置插入
erase(iter):指定位置删除
merage(list): 合并
sort():排序
assign(beg,end):区间 [beg,end]元素复制到链表
list的使用基本和自己的些的链表使用差不多,只是函数已被封装。如下案例:
关联式容器
关联式容器存储的元素,都是一个一个的“键值对”( ),这是和序列式容器最大的不同。除此之外,序列式容器中存储的元素默认都是未经过排序的,而使用关联式容器存储的元素,默认会根据各元素的键值的大小做升序排序。关联式容器所具备的这些特性,归咎于 STL 标准库在实现该类型容器时,底层选用了 红黑树这种数据结构来组织和存储各个键值对。
1set容器set容器可以理解为集合,对于set集合一般是key和value是相等的,所以存储的数据没有对应的关系,存储的数据一般是有序的,对于set来说还有相对应的多重集合 multiset,set集合不允许重复的数据,multiset允许重复的数据,它们使用的成员函数基本是差不多的。主要成员函数如下:
insert(elem)
:插入elembegin()
:容器开始位置end()
: 容器结束位置size()
: 容器中元素个数erase(iter)
: 删除容器中iter指向的元素
对于set集合插入元素后会自带排序功能,默认排序方式是从小到大, 可以通过修改排序准则调整排序方式。set> object,构造集合对象的时候加入排序准则即可,或者重写也可以。集合测试案例代码如下:
2map容器map容器可以理解为单映射,操作的数据类型是数对类型,即pair类型,pair数据有两个成员 first(键)和second(值),而map的排序是根据键排序的。同样也存在多重映射,区别在于多重映射允许相同的键的数据存在。而单映射不允许。数组其实可以理解为下标与值的对应关系,而映射是是拓展版的下标对应值的关系,因为它不局限于整数的键。对于映射常用成员函数如下:
insert(pairelem)
:插入数对elembegin()
:容器开始位置end()
: 容器结束位置size()
: 容器中元素个数erase(iter)
: 删除元素
在单映射中可以采用数组形态方式进行插入元素,但是多重映射不允许的,案例代码如下:
尾言
本栏目到这里结束了,关于迭代器内容我们单独一章节讲解,作业:采用STL去操作自定义类型数据。难度不大,重在重载。