1.容器
1.1 stack
stack是一种先进后出的数据结构,stack 模板类的定义在头文件中。
stack 模板类需要两个模板参数,一个是元素类型,一个容器类型,但只有元素类型是必要
的,在不指定容器类型时,默认的容器类型为deque。
定义stack 对象的示例代码如下:
stack s1;
stack s2;
stack 的基本操作有:
入栈,如例:s.push(x);
出栈,如例:s.pop();注意,出栈操作只是删除栈顶元素,并不返回该元素。
访问栈顶,如例:s.top()
判断栈空,如例:s.empty(),当栈空时,返回true。
访问栈中的元素个数,如例:s.size()。
补充:stack的三种含义
含义一:数据结构
stack的第一种含义是一组数据的存放方式,特点为LIFO,即后进先出(Last in, first out)。
既上述stl中所描述的stack
含义二:代码运行方式
stack的第二种含义是"调用栈"(call stack),表示函数或子例程像堆积木一样存放,以实现层层调用。
含义三:内存区域
stack的第三种含义是存放数据的一种内存区域。程序运行的时候,需要内存空间存放数据。一般来说,系统会划分出两种不同的内存空间:一种叫做stack(栈),另一种叫做heap(堆)。
它们的主要区别是:stack是有结构的,每个区块按照一定次序存放,可以明确知道每个区块的大小;heap是没有结构的,数据可以任意存放。因此,stack的寻址速度要快于heap。
1.2 queue
queue 队列也是一个线性存储表,与后进先出的堆栈不同,元素数据的插入在表的一端进行,在另一端删除,从而构成了一个先进先出(First In First Out) 表。插入一端称为队尾,删除一端称为队首。
由于C++ STL 的队列泛化,默认使用双端队列 deque 来实现,因此,queue 也可看成一个容器的适配器,将 deque 容器转换为 queue 容器。当然,也可以利用其它合适的序列容器作为底层实现 queue 容器。
queue队列容器的C++标准头文件为 queue ,需要用宏语句 "#include " 包含进来才可应用 queue 容器进行开发。
1.3 map
map是一种关联容器,存储的对象是一组key/value
不允许有重复的key
map存储的对象必须是可排序性的
template,class_Alloc = allocator>>classmap{...}
默认采用less定义排序行为,如果map中存储的是自己定义的类,则需要重载operator <
或者可以通过仿函数自定义排序行为
1.3 set
set是一种关联容器,存储的对象既是key又是value
这是 set与map的最大区别
MAP的节点是一对数据.
SET的节点是一个数据.
Map使用关键值Key来唯一标识每一个成员 ,map可以重复。
set是集合 ,不能重复
在作业中遇到的问题:set的iterator类型自动就是const的引用类型,因此当set保存的是类类型时,对iterator解引用无法调用类的非const成员。
解决办法:
1.set中不存储对象本身,改为存储对象指针
2.利用const_cast 进行转型
2.仿函数
仿函数又称函数对象,从名字上可以得出,它本质上是**一种具有函数特质的对象**, 也即可以像使用函
数一样使用该对象。怎么样做?重载operator()运算符即可,有了这个运算符,我们就可以在仿函数对象后
面加上一对小括号,以此调用仿函数所定义的operator()。STL仿函数可以分为一元和二元,或者算术运
算、关系运算和逻辑运算。
为什么要有仿函数?在算法的设计过程中,我们会发现其本质往往是不变的(例如排序算法的思想),变
化的除了数据之外还有操作(例如排序中不一定是比较大小,也可以是两两之间满足某种关系),仿函数就
是为了这种情况产生的,它替代原来需要函数指针的地方,把这种操作或者策略传给算法,使得算法抽象性
更高,也就更通用。
为什么不用函数指针?很简单的解释是抽象性不够,更进一步说是它无法配接,也就是可以将操作配接在
一起变换为更复杂的操作(例如compose和bind1st等等方法),仿函数则可以轻松实现这些配接,使得其功
能异常强大。
仿函数在实现上是一个结构体,并且如上所述重载了operator()运算符,所有的仿函数如果是一元的都继
承自unary_function,二元则继承自binary_function,因为继承自这两个函数的仿函数均定义了相应型别供
配接时使用,也就具有了配接能力。
2.仿函数适配器
由于在for_each的定义中只接受f(obj)这种类型的调用,mem_fun和mem_fun_ref的存在可以让obj的成员函数f可以以f(obj)这种形式被调用
for_each(set1.begin(), set1.end(), mem_fun(&Programmer::print));
需要注意的是如果set中存储的是对象本身,则需要使用mem_fun_ref,如果存储的是对象指针则使用mem_fun