日常记录(二)

1.STL六大组件:容器、算法、迭代器、放寒暑、适配器(配接器)和空间配置器

STL优点:高可重用性、高性能、高移植性

六大组件关系:

        1.容器通过空间配置器取得数据存储空间

        2.算法通过迭代器存储容器中的内容

        3仿函数可以协助算法完成不同的策略变化

        4.适配器可以修饰仿函数。

适配器
⼀种⽤来修饰容器或者仿函数或迭代器接⼝的东西。

注意:queue和stack属于一种容器配接器,因为他们的底部完全借助deque,所有的操作也由底层的deque供应。

空间配置器
        负责空间的配置与管理。从实现􁥯度看,配置器是⼀个实现了动态空间配置、空间管理、空间释放的class tempalte.
        ⼀般的分配器的std:alloctor都含有两个函数allocate与deallocte,这两个函数分别调⽤
operator new()与delete(),这两个函数的底层⼜分别是malloc()and free();但是每次malloc会带
来格外开销(因为每次malloc⼀个元素都要带有􁴫加信息)。

2.容器之间的实现关系以及分类:

序列式容器:array、vector(array)、heap、list(双端数组)、slist、deque

关联式容器:rb_tree、set、map、multiset、muitimap

3.C++容器中的begin() 、cbegin()、rbegin()、crbegin()

  • begin();end()正序迭代器
  • cbegin();cend() 返回 constbegin();end()
  • rbegin();rend() 逆序迭代器
  • crbegin();crend() 返回 constrbegin();rend()

rbegin()指向最后的一个元素;rend()指向第一个元素前面的位置.

std::vector<int>::iterator iter=vec.begin();
std::vector<int>::const_iterator iter=vec.cbegin();

如果容器是const的其返回类型要加上const_前缀,也就是const_iterator和const_reversr_iterator类型(比如遍历map,其key值为const不可修改的)

map的元素为pair,  pair<const key_type, mapped_type>

map<string, int>p;
auto map1 = p.cbegin();
while(map1 != p.cend()){
    cout<<map1->first<<map1->second<<endl;
}

4.vector底层实现:

①三个迭代器:

(1)first : 指向的是vector中对象的起始字节位置
(2)last : 指向当前最后⼀个元素的末尾字节
(3)end : 指向整个vector容器所占⽤内存空间的末尾字节

因此有:

        (1)last - first : 表示 vector 容器中⽬前已被使⽤的内存空间
        (2)end - last : 表示 vector 容器⽬前空闲的内存空间
        (3)end - first : 表示 vector 容器的容量

                size():返回当前已经存储元素个数

                capacity():不分配新内存情况下最多可以保存的元素个数

②扩容过程

如果集合已满,在新增数据的时候,就要分配⼀块更⼤的内存,将原来的数据复制过来,释放
之前的内存,在插⼊新增的元素
所以对vector的任何操作,⼀旦引起空间重新配置,指向原vector的所有迭代器就都失效了

5.Vector和list区别:

1. vector底层实现是数组;list是双向链表
2. vector是顺序内存,⽀持随机访问,list不⾏
3. vector在中间节点进⾏插⼊删除会导致内存拷⻉,list不会
4. vector⼀次性分配好内存,不够时才进⾏翻倍扩容;list每次插⼊新节点都会进⾏内存申请
5. vector随机访问性能好,插⼊删除性能差;list随机访问性能差,插⼊删除性能好

6.deque

        deque是⼀个双端开⼝的连续线性空间,其内部为分段连续的空间组成,随时可以增加⼀段新
的空间并链接。

        由于deque的迭代器⽐vector要复咱,这影响了各个运算层⾯,所以除⾮必要尽量使⽤
vector;为了提⾼效率,在对deque进⾏排序操作的时候,我们可以先把deque复制到vector
中再进⾏排序最后在复制回deque。

deque中控器:deque是由⼀段⼀段的定量连续空间构成。⼀旦有必要在其头端或者尾端增加新的空间,便配置⼀段定量连续空间,串接在整个deque的头端或者尾端

好处:避免“vector的重新配置,复制,释放”的轮回,维护连整体连续的假象,并提供随机访问的接⼝。

坏处:使得迭代器很复杂。

deque两个数据成员:start与finish迭代器,分别由deque:begin()与deque:end()传回

7.heap && priority_queue

heap(堆):建立在完全二叉树上,分为大根堆和小根堆

priority_queue(优先队列):也是配接器,其内的元素不是按照被推⼊的顺序排列,⽽是⾃动取元素的权值排列,确省情况下利⽤⼀个max-heap完成,后者是以vector—表现的完全⼆叉树。

8.map && set

都是C++的关联容器,底层都是红黑树实现。

不同点:

        set:⽤来判断某⼀个元素是不是在⼀个组⾥⾯。

        map:映射,相当于字典,把⼀个值映射成另⼀个值,可以创建字典。

①为什么要成倍的扩容而不是⼀次增加⼀个固定⼤⼩的容量呢?
        采⽤成倍⽅式扩容,可以保证常数的时间复杂度,⽽增加指定⼤⼩的容量只能达到O(n)的时间复杂度。

②为什么是以两倍的⽅式扩容而不是三倍四倍,或者其他⽅式呢
        考虑可能产⽣的堆空间浪费,所以增⻓倍数不能太⼤,⼀般是1.5或2;GCC是2;VS是1.5,k=2 每次扩展的新尺寸必然刚好⼤于之前分配的总和,之前分配的内存空间不可能被使⽤,这样对于缓存并不友好,采⽤1.5倍的增⻓⽅式可以更好的实现对内存的重复利⽤。

③map为什么insert之后,以前保存的iterator不会失效?
因为 map 和 set 存储的是结点,不需要内存拷⻉和内存移动。但是像 vector 在插⼊数据时如
果内存不够会重新开辟⼀块内存。map 和 set 的 iterator 指向的是节点的指针,vector 指向的
是内存的某个位置


④为何map和set的插⼊删除效率⽐其他序列容器⾼?
因为 map 和 set 底部使⽤红黑树实现,插⼊和删除的时间复杂度是 O(logn),⽽向 vector 这
样的序列容器插⼊和删除的时间复杂度是 O(N)

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值