STL(Standard Template Library),即标准模板库,该库包含了诸多在计算机科学领域里所常用的基本数据结构和基本算法,C++标准模板库的核心包括以下组件:
组件 描述
容器(Container) —— 用来管理某一类对象的集合。c++提供了各种不同类型的容器
如:deque、list、vector、map等。
迭代器(Iterator) —— 用于遍历对象集合的元素。
算法(Algorithm) —— 处理集合内的元素。它们提供了执行各种操作的方式,
如:对容器的内容执行初始化、排序、搜索和转换等。
一.容器概述:
(1)顺序容器
将单一类型元素聚集起来成为容器,然后根据位置
来储存和访问这些元素。(vector)
vector: 后部插入\删除,直接接访问。
deque: 前\后部插入\删除,直接访问。
list: 双向链表,任意位置插入\删除。
(2)关联容器
支持通过键来高效的查找和读取元素(map和set)
set: 快速查找,无重复元素。
multiset: 快速查找,可有重复元素。
map: 一对一映射,无重复元素,基于关键字查找。
multimap:一对一映射,可有重复元素,基于关键字查找。
(3)容器适配器(关联容器)
stack: LIFO(后进先出)
queue: FIFO(先进先出)
2.STL容器的共同操作
(1)初始化(initialization)
产生一个空容器
std::list
以另一个容器元素为初值完成初始化
Std::list
…
std::vector
以数组元素为初值完成初始化
int array[]={2,4,6,1345};
…
std::set
(2)与大小相关的操作(size operator)
size()-返回当前容器的元素数量
empty()-判断容器是否为空
max_size()-返回容器能容纳的最大元素数量
(3)比较(comparison)
==,!=,<,<=,>,>=
比较操作两端的容器必须属于同一类型
如果两个容器内的所有元素按序相等,那么这两个容器相等
采用字典式顺序判断某个容器是否小于另一个容器
(4)赋值和交换
swap用于提高赋值操作效率
(5)与迭代器相关的操作
begin()-返回一个迭代器,指向第一个元素
end()-返回一个迭代器,指向最后一个元素之后
rbegin()-返回一个逆向迭代器,指向逆向遍历的第一个元素
rend()-返回一个逆向迭代器,指向逆向遍历的最后一个元素之后
(6)元素操作
insert(pos,e)-将元素e的拷贝安插于迭代器pos所指的位置
erase(beg,end)-移除[beg,end]区间内的所有元素
clear()-移除所有元素
二.迭代器:
可遍历STL容器内全部或部分元素的对象。
指出容器中的一个特定位置。
迭代器的分类:
(1)双向迭代器
可以双向行进,以递增运算前进或以递减运算后退、可以用==和!=比较。
list、set和map提供双向迭代器
(2)随机存取迭代器
除了具备双向迭代器的所有属性,还具备随机访问能力。可以对迭代器增加或减少一个偏移量、处理迭代器之间的距离或者使用<和>之类的关系运算符比较两个迭代器。
vector、deque和string提供随机存取迭代器。
3.vector
vector模拟动态数组
vector的元素可以是任意类型T,但必须具备赋值和拷贝能力(具有public拷贝构造函数和重载的赋值操作符)。
注:必须包含的头文件#include
vector支持随机存取
vector的大小(size)和容量(capacity)。
size返回实际元素个数,
capacity返回vector能容纳的元素最大数量。如果插入元素时,元素个数超过capacity,需要重新配置内部存储器。
注:
@使用平衡二叉树管理元素
@元素包含两部分(key,value),key和value可以是任意类型
@必须包含的头文件#include
@根据元素的key自动对元素排序,因此根据元素的key进行定位很快,但根据元素的value定位很慢
@不能直接改变元素的key,可以通过operator []直接存取元素值
@map中不允许key相同的元素,multimap允许key相同的元素
(1)构造、拷贝和析构
map c ——产生空的map
map c1(c2) ——产生同类型的c1,并复制c2的所有元素
map c(op) ——以op为排序准则产生一个空的map
map c(beg,end) ——以区间[beg,end]内的元素产生一个map
map c(beg,end,op) ——以op为排序准则,以区间[beg,end]内的元素产生一个map~ map() ——销毁所有元素并释放内存。
注:其中map可以是下列形式
map
map
(2)安插(insert)元素
c.insert(pos,e) ——在pos位置为起点插入e的副本,并返回新元素位置(插入速度取决于pos)
c.insert(e) ——插入e的副本,并返回新元素位置
c.insert(beg,end)——将区间[beg,end]内所有元素的副本插入到c中。
(3)移除(remove)元素
c.erase(pos) ——删除迭代器pos所指位置的元素无返回值
c.erase(val) ——移除所有值为val的元素,返回移除元素个数
c.erase(beg,end) ——删除区间[beg,end]内所有元素,无返回值
c.clear() ——移除所有元素,清空容器
5. set/multiset
注:
@使用平衡二叉树管理元素
@集合(Set)是一种包含已排序对象的关联容器。
@必须包含的头文件#include
@map容器是键-值对的集合,好比以人名为键的地址和电话号码。相反地,set容器只是单纯的键的集合。当我们想知道某位用户是否存在时,使用set容器是最合适的。
@set中不允许key相同的元素,multiset允许key相同的元素。
三.算法 ( algorithm ):
头文件:#inlcude
在STL 的泛型算法中有4 类基本的算法:
变序型队列算法 :可以改变容器内的数据;
非变序型队列算法 :处理容器内的数据而不改变他们;
排序值算法: 包涵对容器中的值进行排序和合并的算法,还有二叉搜索算法、通用数值算法。(注:STL 的算法并不只是针对STL 容器,对一般容器也是适用的。)
变序型队列算法: 又叫可修改的序列算法。这类算法有复制( copy )算法、交换( swap )算法、替代( replace )算法、删除(clear )算法,移动( remove )算法、翻转( reverse )算法等等。这些算法可以改变容器中的数据(数据值和值在容器中的位置)。
begin() ——返回指向第一个元素的迭代器;
clear() ——清除所有元素;
count() ——返回某个值元素的个数;
empty() ——如果集合为空,返回true;
end() ——返回指向最后一个元素的迭代器;
equal_range() ——返回集合中与给定值相等的上下限的两个迭代器;
erase() ——删除集合中的元素;
find() ——返回一个指向被查找到元素的迭代器;
get_allocator() ——返回集合的分配器;
insert() ——在集合中插入元素;
lower_bound() ——返回指向大于(或等于)某值的第一个元素的迭代器;
key_comp() ——返回一个用于元素间值比较的函数;
max_size() ——返回集合能容纳的元素的最大限值;
rbegin() ——返回指向集合中最后一个元素的反向迭代器;rend() ——返回指向集合中第一个元素的反向迭代器;
size() ——集合中元素的数目;
swap() ——集合中元素的数目;
upper_bound() ——返回大于某个值元素的迭代器;
value_comp()——返回一个用于比较元素间的值的函数;
对学习STL的心得体会:
STL的意义就在于它为我们提供了很多很好的“零件”,我们可以用它开发自己的“车”!
而且STL制造的“零件”是那么的优良。 自我感觉STL的伟大不仅在于它提供了大量常用的数据结构和许多经典算法,而且因为他提供迭代器:你可以利用迭代器概念,写出自己的迭代器,也能很好的使用;而且,它可以让你自己去扩充库,并且与现有的库可以很好的配合使用。
【运算符重载】
1.引入:运算符重载使得用户自定义的数据以一种更简洁的方式工作。
2.运算符重载规则
(1)限制:
<不能重载的运算符>: . :: .* ?: sizeof
<可以重载的运算符>: + - * / % ^ & | ~
! = < > += -= *= /= %
^= &= |= << >> >>= <<= == !=
<= >= && || ++ -- -> * ‘ ->
[] () new delete new[] delete[]
重载运算符函数可以对运算符作出新的解释,但原有基本语义不变:
a, 不改变运算符的优先级。
b, 不改变运算符的结合性。
c, 不改变运算符所需要的操作数。
d, 不能创建新的运算符。
3.用成员函数或友元函数重载运算符
(1)一元运算符
Object op或op Object
重载为成员函数,解释为:Object .operator op ()操作数由对象Object通过this指针隐含传递;
重载为友元函数,解释为:operatorop (Object)操作数由参数表的参数Object提供
(2)二元运算符
ObjectL op ObjectR
重载为成员函数,解释为:ObjectL . operator op (ObjectR ),左操作数由ObjectL通过this指针传递,右操作数由参数ObjectR传递;
重载为友元函数,解释为:operatorop ( ObjectL, ObjectR )左右操作数都由参数传递。
(3)用成员函数重载运算符
成员运算符函数的原型在类的内部声明格式如下:
class X
{
//…
返回类型 operator运算符(形参表);
//…
}
在类外定义成员运算符函数的格式如下:
返回类型 X::operator运算符(形参表)
{
函数体
}
双目运算符重载为成员函数:
对双目运算符而言,成员运算符函数的形参表中仅有一个参数,它作为运算符的右操作数,此时当前对象作为运算符的左操作数,它是通过this指针隐含地传递给函数的。
(4)用友元函数重载
a, 友元函数重载运算符常用于运算符的左右操作数类型不同的情况:在第一个参数需要隐式转换的情形下,使用友元函数重载运算符是正确的选择。
b, 友元函数没有 this 指针,所需操作数都必须在参数表显式声明,很容易实现类型的隐式转换。
c, C++中不能用友元函数重载的运算符有
= () [] ->
(5)成员运算符函数与友元运算符函数的比较
①成员运算符函数比友元运算符函数少带一个参数(后置的++、--需要增加一个形参)。
②双目运算符一般可以被重载为友元运算符函数或成员运算符函数,但当操作数类型不相同时,必须使用友元函数。
4.几个典型运算符重载
数学类中常用的几个运算符重载的特点和应用
设 A Aobject ;
运算符 ++和 - - 有两种方式:
前置方式: ++Aobject --Aobject
成员函数 重载 A :: Aoperator++ () ;
解释为: Aobject. operator ++( ) ;
友元函数 重载 friend A operator++ (A &) ;
解释为: operator++( Aobject ) ;
后置方式: Aobject ++ Aobject --
成员函数 重载 A ::A operator++ (int) ;
解释为: Aobject. operator ++( 0 ) ;
友元函数 重载: friend A operator++ (A &, int) ;
解释为: operator++(Aobject,0)
5.重载运算符[]和()
a, 运算符 [] 和 () 是二元运算符
b, [] 和 () 只能用成员函数重载,不能用友元函数重载
(1)重载下标运算符[]
[] 运算符用于访问数据对象的元素
重载格式 类型 类 ::operator[] ( 类型 ) ;
例:
设 x 是类 X 的一个对象,则表达式: x[ y ],可被解释为 :x. operator [ ] ( y )
(2)重载函数调用符 ()
() 运算符用于函数调用
重载格式 类型 类 ::operator() ( 参数表 ) ;
例
设 x 是类 X 的一个对象,则表达式:x( arg1, arg2, … ),可被解释为: x. operator () (arg1, arg2, … )
6.重载流插入和流提取运算符
a, istream 和 ostream 是 C++ 的预定义流类。
b, cin 是 istream 的对象,cout 是 ostream 的对象。
c, 运算符 << 由ostream 重载为插入操作,用于输出基本类型数据。
d, 运算符 >> 由 istream 重载为提取操作,用于输入基本类型数据。
e, 用友元函数重载 << 和 >> ,输出和输入用户自定义的数据类型。
重载输出运算符“<<”(只能被重载成友元函数,不能重载成成员函数)
定义输出运算符“<<”重载函数的一般格式如下:
ostream& operator<<(ostream&out,class_name&obj)
{
out<
out<
.. .
out<
return out;
}
重载输入运算符“>>” (只能被重载成友元函数)
定义输入运算符函数“>>”重载函数的一般格式如下:
istream& operator>>(istream&in,class_name&obj)
{
in>>obj.item1;
in>>obj.item2;
. . .
in>>obj.itemn;
return in;
}
对学习运算符重载的心得体会:
我们可以自己重定义或重载大部分 C++ 内置的运算符。这样,我们就能使用自定义类型的运算符。
重载的运算符是带有特殊名称的函数,函数名是由关键字 operator 和其后要重载的运算符符号构成的。与其他函数一样,重载运算符有一个返回类型和一个参数列表。运算符重载给我们提供了一种更简便、更行之有效的途径去实现各种功能,但是琐碎的知识点往往给我们在实践时带来困难。所以我们还要多花时间去记忆去了解。