C++语言:STL

1、STL容器

1.1 介绍

容器分为顺序容器和关联容器,这种划分是基于容器中元素的组织方式。

容器名 中文名 头文件 所属概念
vector 向量 <vector> 随机访问容器,顺序容器
deque 双端队列 <deque> 随机访问容器,顺序容器
list 列表 <list> 可逆容器,顺序容器
set 集合 <set> 可逆容器,关联容器
multiset 多重集合 <set> 可逆容器,关联容器
map 映射 <map> 可逆容器,关联容器
multimap 多重映射 <map> 可逆容器,关联容器

1.2 STL容器的共性

设S表示一种容器类型(例如vector),s1和s2都是S类型的实例,容器支持的基本功能如下
操作 功能

S s1	
容器都有一个默认构造函数,用于构造一个没有任何元素的空容器

s1 op s2	
这里的op是各种比较运算符,它会对两个容器之间的元素按字典顺序进行比较

s1.begin()	
返回指向s1第一个元素的迭代器

s1.end()	
返回指向s1最后一个元素的下一个位置的迭代器

s1.clear()	
将容器s1的内容清空

s1.empty()	
返回一个布尔值,容器为空返回true,否则返回false

s1.size()	
返回s1的元素个数

s1.swap(s2)	
将s1容器和s2容器的内容交换

2、顺序容器

2.1 介绍

STL中的顺序容器包括向量(vector)、双端队列(deque)和列表(list),它们在逻辑上可看作一个长度可扩展的数组,容器中的元素都是线性排列。可人为决定每个元素在容器中的位置,可以随时向指定的位置插入新的元素和删除已有的元素。

2.2 顺序容器的共性

假设S表示容器的类型,s表示S类型的实例,用T表示S容器的元素类型,用t表示T类型的一个实例,用n表示一个整型数据,用p1和p2表示指向s中的元素的迭代器,用q1,q2表示任何一个指向T类型元素的输入迭代器(未必指向S中的元素,也未必具有S::iterator类型),顺序容器的基本功能如下所示:

  • 1、构造函数
S s	
使用默认构造函数,构造一个空容器

S s(n,t)
构造一个由n个t元素构成的容器实例s

S s(n)	
构造一个有n个元素的容器实例s,每个元素都是T()

S s(q1,q2)	
使用 [q1,q2) 区间内的数据作为s的元素构造s
  • 2、赋值函数
 说明;
 可以使用赋值函数assign将指定的元素赋给顺序容器,
 顺序容器中原先的元素会被清除,赋值函数的3种形式是与构造函数一一对应的

s.assign(n,t)	
赋值后的容器由n个t元素构成

s.assign(n)	
赋值后的容器由n个值都为T()的元素构成

s.assign(q1,q2)	
赋值后的容器的元素为 [q1,q2) 区间内的数据
  • 3、元素的插入
说明:
向顺序容器中可以一次插入一个或多个指定元素,
也可以将一个迭代器区间所表示的序列插入,
插入时需要通过一个指向当前容器元素的迭代器来指示插入位置。

s.insert(p1,t)	
在s容器中p1所指向的位置插入一个新的元素t,
插入后的元素夹在原p1和p1-1所指向的元素之间,
该函数会返回一个迭代器指向新插入的元素

s.insert(p1,n,t)	
在s容器中p1所指向的位置插入n个新的元素t,
插入后的元素夹在原p1和p1-1所指向的元素之间,没有返回值

s.insert(p1,q1,q2)[q1,q2) 区间内的元素顺序插入到s容器中p1位置处,
新的元素夹在原p1和p1-1所指向的元素之间

  • 4、元素的删除
s1.erase(p1)	
删除s1容器中p1所指向的元素,返回被删除元素的下一个元素的迭代器

s1.erase(p1,p2)	
删除s1容器中 [p1,p2) 区间内的元素,返回最后一个被删除元素的下一个元素的
迭代器(即在删除前p2所指向元素的迭代器)
 
  • 5、改变容器的大小
s1.resize(n)	
将容器的大小变为n,如果原来的元素大于n,则容器末尾多余的元素
会被删除,如果原来的元素小于n,则在容器末尾会用T()填充
  • 6、首尾元素的相关操作(高效)
s.front()	获得容器首元素的引用
s.back()	获得容器尾元素的引用
s.push_back(t)	向容器尾部插入元素t
s.pop_back()	将容器尾部的元素删除
s.push_front(t)	向容器头部插入元素t    (向量除外)
s.pop_front()	将容器头部的元素删除  (向量除外)

3、关联容器

3.1 介绍

对于关联容器,它的每个元素都有一个键(key),容器中的元素的顺序并不能人为随意决定,而是按照键的取值升序排列的。也就是说,对于一个关联容器s,使用迭代器在 [s.begin(),s.end() )区间内遍历,访问到的序列总是升序的。

3.2 分类

按照容器中是否允许出现重复键值,关联容器可分为单重关联容器和多重关联容器:

  • 单重关联容器中的键值是唯一的,不允许重复,集合和映射属于这一类;
  • 多重关联容器中,相同的键值允许重复出现,多重集合和多重映射属于这一类。

按照键与元素的关系可以分为简单关联容器和二元关联容器:

  • 简单关联容器以元素本身作为键,集合和多重集合属于这一类
  • 二元关联容器的元素是由键和某种类型的附加数据共同构成,键只是元素的一部分,映射和多重映射属于这一类

3.3 二元组pair

二元关联容器的元素类型是键类型和附加数据类型的组合,这种组合类型可以用一个二元组(pair)来表示,pair是头文件中定义的结构体模板:

template<class T1,class T2>
struct pair{
     T1 first;  //二元组的第一元
     T2 second;  //二元组的第二元
     pari();   //默认构造函数
     pair(const T1 &x,const T2 &y);     //构造first=x,second=y的二元组
     template<class U,class V>pair(const pair<U,V>&p);  //复制构造函数
};

3.4 关联容器的共性

假设S表示容器的类型,s表示S类型的实例,用T表示S容器的元素类型,用t表示T类型的一个实例,用K表示S容器的键的类型,用k表示K的一个实例,用n表示一个整型数据,用p1和p2表示指向s中的元素的迭代器,用q1,q2表示任何一个指向T类型元素的输入迭代器,关联容器的基本功能如下所示:

  • 1、构造函数
操作 功能 单重关联容器 多重关联容器
S s 构造一个空容器 构造一个空容器 构造一个空容器
S s(q1,q2) 将[q1,q2)区间的数据作为s的元素构造s 当[q1,q2)范围内出现具有相同键的元素时,只有一个元素会被加入s中 [q1,q2)范围内的所有元素均被无条件加入s中
  • 2、元素的插入
操作 功能 单重关联容器 多重关联容器
s.insert(t) 将元素t插入s容器中 只有当不存在相同键的元素时才能成功插入,该函数返回类型为pair<S::iterator,bool>。插入成功时,返回被插入元素的迭代器,否则返回与t的键相同的元素的迭代器和false 插入总会成功,返回已插入元素的迭代器
s.insert(p1,t) 将元素t插入s容器中,p1是一个提示的插入位置,如果提示位置准确(即t的键的大小刚好在p1-1和p1之间)则可以提高插入效率。即使提示位置不准确也可以正确完成插入操作,该函数总是返回一个迭代器 只有当不存在相同键的元素时才能成功插入,插入成功时,返回被插入元素的迭代器,否则返回与t的键相同的元素的迭代器 插入总会成功,返回已插入元素的迭代器
s.insert(q1,q2) 相当于按顺序对 [q1,q2) 区间内的每个元素x分别执行s.insert(x)
  • 3、元素的删除
s.erase(p1)	删除p1所指向的元素
s.erase(p1,p2)	删除 [p1,p2) 区间内的元素
s.erase(k)	删除所有键为k的元素,返回被删除元素的个数
  • 4、键的查找和计数
s.find(k)	
找到任意一个键为k的元素,返回该元素的迭代器,如果s中没有键为k的元素,则返回s.end()

s.lower_bound(k)	
得到s中第一个键值不小于k的元素的迭代器(第一个>=k的元素)

s.upper_bound(k)	
得到s中第一个键值大于k的元素的迭代器(第一个>k的元素)

s.equal_range(k)	
得到一个用pair<S::iterator,S::iterator>表示的区间,记为 [p1,p2) 。
该区间刚好包含所有键值为k的元素,p1==s.lower_bound(k)和p2==s.upper_bound(k)一定成立

s.count(k)
得到s容器中键为k的元素个数

注:关联容器的插入和删除操作不会使任何已有的迭代器、指针或引用失效。

4、使用

1、stack

函数 原型 功能
empty bool empty() const 判断栈是否为空,空返回true,否则返回false
size size_type size() const 返回栈中元素的个数
top T& top() ; const T& top() const 返回栈顶元素
pop void pop() 出栈
push void push(const T &x) 入栈

2、queue

函数 原型 功能
empty bool empty() const 判断队列是否为空,空返回true,否则返回false
size size_type size() const 返回队列中元素的个数
front T& front() ; const T& front() const 返回队头元素
back T& back ( ) ; const T& back ( ) const 返回队尾元素
pop void pop() 队头元素出队
push void push(const T &x) 从队尾入队

3、priority_queue

函数 原型 功能
empty bool empty() const 判断优先队列是否为空,空返回true,否则返回false
size size_type size() const 返回优先队列中元素的个数
top const T& top ( ) const 返回优先级最高的元素
push void push(const T &x) 向优先队列中添加元素
pop void pop() 优先级最高的元素出队

由于优先队列还涉及到优先级的设置,因此本文除了给出优先队列的操作外,还对优先级的设置进行说明。

priority_queue类模板

template < class T, class Container = vector<T>,
           class Compare = less<typename Container::value_type> > class priority_queue;

参数说明:

  • T 说明优先队列中元素的类型,可以是基本数据类型,也可以是用户自定义数据类型
  • Container 说明实现优先队列的底层容器,默认是vector
  • Compare 说明优先队列的优先原则,即值大优先还是值小优先,特别注意此处实际表示的是!Compare。默认是less,less是一个表示值小优先的结构体的类模板,由!Compare可知优先队列默认值大优先

设置优先原则的方法
情况一:元素为用户自定义数据类型
值小优先:重载<运算符为大于含义
值大优先:重载<运算符为小于含义
注:这样重载是由于优先队列的第三个参数实际表示的是!Compare的缘故

重载好后即可按如下方式定义:

priority_queue<T> que;  

T为自定义数据类型

情况二:元素为基本数据类型

值小优先:使用与less相反的greater

示例:priority_queue<int,vector<int>,greater<int> >que

值大优先:优先队列默认值大优先

示例:priority_queue<int> que

只有第一个参数,后面两个参数使用默认值

4、vector

函数 功能
rbegin() 传回一个逆向队列的第一个数据。
rend() 传回一个逆向队列的最后一个数据的下一个位置。
at(idx) 传回索引idx所指的数据,如果idx越界,抛出out_of_range。
capacity() 返回容器中数据的个数。
max_size() 返回容器能存放数据的最大数量。
operator[] 返回容器中指定位置的一个引用。

5、list

函数 功能
listl1(l2) 复制 l2
it l.rbegin() 返回“反向链表”的第1个元素的地址。即返回链表的最后一个元素的地址。
it l.rend() 返回“反向链表”的最后一个元素的下一个位置,这么说可能不正确,这个函数主要用于反向链表的操>作。返回的是地址,该地址没有元素。
void l.remove (const value_type& val) 删除值等于val的元素,得一模一样才能删除,估计比对的是整块内存的二进制。与erase不同。
void l.remove_if (Predicate pred) 删除元素。将链表中每个元素单独传入pred函数,只要返回的结果为true,就删除。pred不用加括>号,它类似于sort里的comp
void l.merge (list& x) 将链表x接在l之后,合并为一个链表l,合并完后链表x中的元素为0了,但x仍存在。(不排序)
void l.merge (list& x, Compare comp) 将两链表合并在一起,按照comp函数的排序规则来排序。
void l.sort() 排序,按照默认的方法排序,一般为增序,比如整数、字符串比较
void l.sort(comp) 排序,按照comp函数所返回的那样,若true则不改变位置,若false则交换位置。
void l.splice (it pos, list& x) 将链表x中所有的元素“剪切”到pos处,其实只是指针操作,不用赋值
void l.splice (it pos, list& x, it i) 将链表x中的元素i“剪切”到pos处,只是单个元素。
void l.splice (it pos, list& x, it first, it last) 将链表x中first到last这段元素都迁移到l中的pos处。
void l.unique() 删除重复的多余元素,使每个元素唯一。相同元素的第一个都不会删。
void l.unique (Predicate pred) 以pred函数为依据,删除重复的元素,当pred返回true时则删除其中一个。
void l.reverse() 将所有元素的顺序置为相反,比如升序变为降序。

6、bitset

头文件:<bitset>
1、构造函数:

bitset<4> b1;  
无参构造,长度为4,默认每一位为00000

bitset<8> b2(12);  
长度为8,二进制保存,前面用0补充  :00001100

string s = "100101";
bitset<10> b3(s);  
长度为10,前面用0补充  :0000100101

char s2[] = "10101";
bitset<13> b4(s2);  
长度为13,前面用0补充  :0000000010101
若参数的二进制表示比bitsize大,参数为整数时取后面部分,参数为字符串或字符数组时取前面部分

2、成员函数:
bs.any()
是否存在值为1的二进制位

bs.none()
是否全部位为0

bs.size()
位长

bs.count()
值为1的个数

bs.test(pos)
测试pos处的二进制位是否为1

bs.set()
全部位置1

bs.set(pos)
将pos位处的二进制位设置为1

bs.reset()
全部位置0

bs.reset(pos)
pos位处的二进制位设置为0

bs.flip()
全部位逐位取反

bs.flip(pos)
pos处的二进制位取反

bs.to_ulong()
将二进制转换为unsigned long输出

bs.to_string()
将二进制转换为字符串输出

~bs
按位取反
效果等效为bs.flip()

os << b
将二进制位输出到os流,小值在右,大值在左

3、位运算的使用:
>位运算符&|~<<>>可用于两个bitset类型的实例。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章