C++ STL容器

参考oi wiki

C++ STL容器_第1张图片

STL的产生是为了简化数据结构和算法的内部实现

并对任一数据类型都可实现对应操作

功能封装起来,用时即拿

类型
序列式容器

向量 vector  顺序表  可当作动态数组使用

数组 array C++11特性 定长顺序表(静态数组

双端队列 deque 两端均可对数据元素进行高效操作的队列

列表 list 可沿双向遍历的链表 (双向链表)

单向列表(forward_list)只能单向遍历

关系式容器

集合 set 有序性 互异性 红黑树实现

多重集合 multiset 有序性 可重性

映射 map 键值对的集合 按键值有序排列

多重映射 multimap 键值对组成的多重集合 允许一个键有多个映射

无序(关联式)容器

无序集合 unordered_set 无序 哈希实现 关心元素是否存在

无序映射unordered_map 键无序 哈希实现 关心映射关系

容器适配器

适配器是对STL容器的包装,使其拥有和数据结构一样的作用

栈 stack LIFO容器 默认是对双端队列的包装

队列 queue FIFO容器 默认是对双端队列的包装

优先队列 priorty_queue 默认对向量包装

迭代器

类似于数组的指针,迭代器可以访问容器中的元素

主要支持自增++,自减-- 来移动迭代器

以及*用来解引用

迭代器的声明

container::iterator it;
auto it;

迭代器在很多STL函数里作为参数

共有函数
=                                            //赋值  赋值构造
container_name.begin()                       //返回容器首个元素的迭代器
container_name.end()                         //返回末尾迭代器
container_name.size()                        //返回容器大小
container_name.empty()                       //判空
swap(container1,container2) <==> container1.swap(container2)    //交换容器内容
container_name.clear()                       //清除
== != < > <= >=                              //字典序比大小 无序容器不支持

向量

顺序表,内存连续,可变长度

随机访问,插删时间复杂度线性

向量容器内部重写了赋值与比较运算符,可以使用简单的双目运算符直接比较容器

实现细节

vector底层依旧是定长数组,但分开存储了当前长度n与最大容量N,当检测到n>N,容器将分配2N数组,将旧数据拷贝到新数组,并释放原数组内存

vector对bool的特化,在vector中使用[]访问元素无法返回bool&,而是vector::reference。节省空间可用bitset代替

数组

是对原生数组的直接封装

双端队列

提供线性复杂度删插,随机访问

deque的底层是多个不连续的缓冲区buffer,但缓冲区内部内存连续,并记录首尾指针,用以标记有效数据区间,一个buffer满就会分配新的buffer

双向链表

双向链表增删查改的操作与deque相同

不过链表不提供随机访问的接口,只能迭代器访问

集合

含有键值对象的已排序集,支持对数复杂度的搜删插

内部实现是红黑树。拥有平衡二叉树的特性

映射

有序键值对容器,键唯一,支持对数复杂度搜删插

通过红黑树实现

无序集合与无序映射

普通的关联容器大多通过红黑树实现,而无序关联式容器使用哈希方法

使得该类容器大部分操作都可以在常数复杂度进行

哈希冲突

STL里,每个元素的散列值都是对这个列表里的质数取模得到

G++7后一般是107897

可通过向容器中插入该质数的倍数制造哈希冲突

自定义哈希函数

为避免哈希冲突

需要先定义结构体,重载()运算符

struct my_hash {
  size_t operator()(int x) const { return x; }
};

为确保哈希函数不被轻易破解,可在哈希函数中加入许多随机化函数

struct my_hash {
  static uint64_t splitmix64(uint64_t x) {
    x += 0x9e3779b97f4a7c15;
    x = (x ^ (x >> 30)) * 0xbf58476d1ce4e5b9;
    x = (x ^ (x >> 27)) * 0x94d049bb133111eb;
    return x ^ (x >> 31);
  }

  size_t operator()(uint64_t x) const {
    static const uint64_t FIXED_RANDOM =
        chrono::steady_clock::now().time_since_epoch().count();
    return splitmix64(x + FIXED_RANDOM);
  }

  // 针对 std::pair 作为主键类型的哈希函数
  size_t operator()(pair x) const {
    static const uint64_t FIXED_RANDOM =
        chrono::steady_clock::now().time_since_epoch().count();
    return splitmix64(x.first + FIXED_RANDOM) ^
           (splitmix64(x.second + FIXED_RANDOM) >> 1);
  }
};

自定义完后,就可以在声明容器时传入哈希函数了

容器适配器

栈和队列都是对双端队列的包装,但都对其进行了限制性操作

栈和队列均不支持随机访问与迭代器

其成员函数均为线性复杂度

对于优先队列,一般称作堆或者二叉堆

除了删插是对数复杂度外,其余常用成员函数皆是常数级别

你可能感兴趣的:(c++,开发语言)