XuQi's Blog

  • 首页

  • 归档

STL从0开始

发表于 2019-05-21 更新于 2019-10-20

容器(Containers)

顺序容器

array [c++11]

vector

单开口,预留空间

emplace_back[c++11] 在最后构造并插入

list

容器适配器

stack

后进先出 使用deque/list,不用vector的原因应该是容量大小有限制,扩容耗时

queue

先进先出 使用deque/list,不用vector的原因应该是容量大小有限制,扩容耗时

deque

关联容器

set

map

multiset

multimap

无序关联容器

unordered_set [c++11]

unordered_map [c++11]

unordered_multiset [c++11]

unordered_multimap [c++11]

容器分类

数据结构
数组 array/vector

​ 特点: 随机访问,vector删除数据时,空间不释放

双向链表 list

​ 特点:快速增删

双端队列 deque

​ 特点: 随机访问,头尾快速增删

红黑树 set/multiset map/multimap

​ 特点:插入删除性能相同O(log2n)

哈希表 unordered_set/unordered_multiset unordered_map/unordered_multimap

​ 特点: 最优O(1),最差O(n)

有序

​ 红黑树

不可重复

​ 哈希+红黑树

红黑树 R-B Tree,全称是Red-Black Tree 一种特殊的二叉查找树

红黑树的特性:

(1)每个节点或者是黑色,或者是红色。
(2)根节点是黑色。
(3)每个叶子节点(NIL)是黑色。 [注意:这里叶子节点,是指为空(NIL或NULL)的叶子节点!]
(4)如果一个节点是红色的,则它的子节点必须是黑色的。
(5)从一个节点到该节点的子孙节点的所有路径上包含相同数目的黑节点。

操作时间是:log n

AVL树-自平衡二叉查找树

特性:

(1)它的左子树和右子树都是AVL树

(2)左子树和右子树的高度差不能超过1

顺序容器常用操作

iterators const iterators capacity element access modifiers observers
begin cbegin size at push_front data
end cend empty [] pop_front
rbegin front push_back
rend end pop_back
erase
swap
clean
insert

关联容器 常用操作

operations observers
count key_comp
find value_comp

算法(Algorithms)

头文件

只读算法

查找算法
函数 描述
find(beg, end, v) 在[beg, end)之间查找等于v的元素,找到返回迭代器,找不到返回end
find_first_of(beg, end, beg2, end2) 在[beg, end)之间查找[beg2, end2)内任意匹配元素,找到返回的第一个容器中第一个匹配的元素
find_end(beg, end, beg2, end2) 找到最后匹配的元素
find_if(beg,end,func) 函数find的带一个函数参数的_if版本,与find功能相同,条件:使函数func返回true
搜索与统计算法
函数 描述
search(beg, end, beg2, end2) 在区间1内搜索子序列2
search_n(beg, end, n, v) 在区间[beg, end)内查找连续n个元素v
count(v) 统计v的个数
lower_bound(beg, end, v) 查找非递减序列,第一个大于v的元素
upper_bound(beg, end, v) 查找非递减序列,第一个小于v的元素
count_if(beg, end, v) 函数count的_if版本

可变序列算法

函数 描述
copy(beg, end, beg2) 将[beg, end)复制到beg2
transform(beg, end, beg2, func) 将每个元素经过func
replace(beg, end, v1, v2) 将[beg, end)中的v1替换v2
fill(beg, end, v) 将[beg, end)写入v
fill_n(beg, n, v) 从beg写入n个v
generate(beg, n, rand) 从beg,填入n个随机数
remove(beg, end) 移除区间[beg, end)内元素,不是真正删除,只是移到最后
unique(beg, end) 删除相邻重复元素,不是真正删除,只是移到最后
remove_if(beg, end, func) remove的_if版本
replace_if(beg,end,func,v2) replace的_if版本
remove_copy(beg,end,dest) remove的_copy版本,将反转后的序列输出到从dest开始的区间。

排序算法

函数 描述
sort(beg,end) 字典排序
stable_sort(beg,end) 字典排序。保存相等元素关系
parital_sort(beg,mid,end) 取mid - beg最小元素,放入[beg,mid)内
random_shuffle(beg,end) 随机排序
reverse(beg,end) 翻转
rotate(beg,mid,end) [beg,mid)和[mid,end)元素旋转,并使用mid作为起点
merge(beg,end,beg2,end2,nbeg) 合并为一个,同时排序
reverse_cpoy(beg,end,dest) reverse的copy
rotate_cpoy(beg,mid,end,dest) rotate的copy

关系算法

函数 描述
equal(beg,end,beg1,end1) 判断两区间是否相同
include(beg1,end1,beg2,end2) 判断[beg2,end2)是否包含[beg1,end1)
max_element(beg,end) 返回最大元素
min_eleament(beg,end) 返回最小元素
mismatch(beg,end,beg1,end1) 查找两序列,第一个不匹配的的元素,返回一对it

堆算法

“堆”是个很有趣的数据结构,是个完全二叉树。

“堆”的特性:每个节点的键值一定总是大于(或小于)它的父节点(大于:称为“最大堆”,小于:称为“最小堆”),或者说每个节点总是大于或小于它的子节点。

对于最大堆而言,根节点为最大值;对于最小堆而言,根节点为最小值。

通常“堆”是通过数组来实现的,这样可以利用数组的特点快速定位指定索引的元素。

完全二叉树:对于一个树高为h的二叉树,如果其第0层至第h-1层的节点都满。如果最下面一层节点不满,则所有的节点在左边的连续排列,空位都在右边。这样的二叉树就是一棵完全二叉树。

函数 描述
make_heap(beg,end) 以区间[beg,end)建立堆
pop_heap(beg,end) 重新排序堆,第一个和最后一个交换,并不弹出正在最大值
push_heap(beg,end) 插入元素,重新排序堆
sort_heap(beg,end) 对序列重新排序

容器特有的算法

因为list容器上的迭代器是双向的,所以不能使用随机访问的迭代器算法。

参考链接:

https://blog.csdn.net/xyqqwer/article/details/81263060

常见问题

STL有哪些组件?

容器,迭代器,算法,容器适配器

STL常用的容器有哪些以及各自的特点是什么?
说说std::vector的底层(存储)机制。
什么情况下用vector,什么情况下用list。
vector中begin和end函数返回的是什么?
为什么vector的插入操作可能会导致迭代器失效?

vector动态增加大小时,并不是在原空间后增加新的空间,而是以原大小的两倍在另外配置一片较大的新空间,然后将内容拷贝过来,并释放原来的空间。由于操作改变了空间,所以迭代器失效。

deque与vector的区别。

1)vector是单向开口的连续线性空间,deque是双向开口的连续线性空间。(双向开口是指可以在头尾两端分别做元素的插入和删除操作)。

2)deque没有提供空间保留功能,而vector则要提供空间保留功能。

3)deque也提供随机访问迭代器,但是其迭代器比vector迭代器复杂很多。

不允许有遍历行为的容器有哪些(不提供迭代器)

queue,stack,heap

说说std::map底层机制。
vector、list、map、deque用erase(it)后,迭代器的变化。

vector和deque是序列式容器,其内存分别是连续空间和分段连续空间,删除迭代器it后,其后面的迭代器都失效了,此时it及其后面的迭代器会自动加1,使it指向被删除元素的下一个元素。

list删除迭代器it时,其后面的迭代器都不会失效,将前面和后面连接起来即可。

map也是只能使当前删除的迭代器失效,其后面的迭代器依然有效。

map和set的3个问题。

1)为何map和set的插入删除效率比其他序列容器高。

因为不需要内存拷贝和内存移动

2)为何map和set每次Insert之后,以前保存的iterator不会失效?

因为插入操作只是结点指针换来换去,结点内存没有改变。而iterator就像指向结点的指针,内存没变,指向内存的指针也不会变。

3)当数据元素增多时(从10000到20000),map的set的查找速度会怎样变化?

RB-TREE用二分查找法,时间复杂度为log2n,所以从10000增到20000时,查找次数从log210000=14次到log220000=15次,多了1次而已。

# STL
shadowsocks
以太网芯片MAC和PHY的关系
  • 文章目录
  • 站点概览

XuQi

44 日志
30 标签
  1. 1. 容器(Containers)
    1. 1.1. 顺序容器
      1. 1.1.1. array [c++11]
      2. 1.1.2. vector
      3. 1.1.3. list
    2. 1.2. 容器适配器
      1. 1.2.1. stack
      2. 1.2.2. queue
      3. 1.2.3. deque
    3. 1.3. 关联容器
      1. 1.3.1. set
      2. 1.3.2. map
      3. 1.3.3. multiset
      4. 1.3.4. multimap
    4. 1.4. 无序关联容器
      1. 1.4.1. unordered_set [c++11]
      2. 1.4.2. unordered_map [c++11]
      3. 1.4.3. unordered_multiset [c++11]
      4. 1.4.4. unordered_multimap [c++11]
      5. 1.4.5. 容器分类
        1. 1.4.5.1. 数据结构
          1. 1.4.5.1.1. 数组 array/vector
          2. 1.4.5.1.2. 双向链表 list
          3. 1.4.5.1.3. 双端队列 deque
          4. 1.4.5.1.4. 红黑树 set/multiset map/multimap
          5. 1.4.5.1.5. 哈希表 unordered_set/unordered_multiset unordered_map/unordered_multimap
        2. 1.4.5.2. 有序
        3. 1.4.5.3. 不可重复
      6. 1.4.6. 顺序容器常用操作
      7. 1.4.7. 关联容器 常用操作
    5. 1.5. 算法(Algorithms)
      1. 1.5.0.1. 头文件
    6. 1.5.1. 只读算法
      1. 1.5.1.1. 查找算法
      2. 1.5.1.2. 搜索与统计算法
    7. 1.5.2. 可变序列算法
    8. 1.5.3. 排序算法
    9. 1.5.4. 关系算法
    10. 1.5.5. 堆算法
    11. 1.5.6. 容器特有的算法
  2. 1.6. 常见问题
    1. 1.6.0.1. STL有哪些组件?
    2. 1.6.0.2. STL常用的容器有哪些以及各自的特点是什么?
    3. 1.6.0.3. 说说std::vector的底层(存储)机制。
    4. 1.6.0.4. 什么情况下用vector,什么情况下用list。
    5. 1.6.0.5. vector中begin和end函数返回的是什么?
    6. 1.6.0.6. 为什么vector的插入操作可能会导致迭代器失效?
    7. 1.6.0.7. deque与vector的区别。
    8. 1.6.0.8. 不允许有遍历行为的容器有哪些(不提供迭代器)
    9. 1.6.0.9. 说说std::map底层机制。
    10. 1.6.0.10. vector、list、map、deque用erase(it)后,迭代器的变化。
    11. 1.6.0.11. map和set的3个问题。
© 2019 XuQi
由 Hexo 强力驱动 v3.9.0
|
主题 – NexT.Muse v7.3.0