概述
C++标准模板库
一、知识点总结
一、STL概述
STL内的所有组件都由模板(template)构成,其元素可以是任意类型
STL是所有C++编译器和所有操作系统都支持的一种库
1、STL组件
(1)容器(Container)-管理某类对象的集合
(2)迭代器(Iterator)-在对象集合上进行遍历
(3)算法(Algorithm)-处理集合内的元素
(4)容器适配器(container adaptor)
(5)函数对象(functor)
2、STL容器类别
(1)序列式容器-排列次序取决于插入时机和位置
(2)关联式容器-排列顺序取决于特定准则
3、STL容器的共同能力
(1)所有容器中存放的都是值而非引用,如果希望存放的不是副本,容器元素只能是指针。
(2)所有元素都形成一个次序(order),可以按相同的次序一次或多次遍历每个元素。
4、STL容器元素的条件
(1)必须能够通过拷贝构造函数进行复制
(2)必须可以通过赋值运算符完成赋值操作
(3)必须可以通过析构函数完成销毁动作
(4)序列式容器元素的默认构造函数必须可用
(5)某些动作必须定义operator=,例如搜寻操作
(6)关联式容器必须定义出排序准则,默认情况是重载operator<
对于基本数据类型(int,long,char,double,...)而言,以上条件总是满足。
5、STL容器的共同操作
(1)初始化
产生一个空容器
std::list<int>l;
以另一个容器元素为初值完成初始化
std::list<int>l;
...
std::vector<float>c(l.begin(),l.end());
以数组元素为初值完成初始化
int array[]={2,4,6,1345};
...
std::set<int>c(array,array+sizeof(array)/sizeof(array[0]));
(2)与大小相关的操作
empty()-判断容器是否为空
size ()-返回 当前容器的元素数量。
max_size()-返回容器能容纳的最大元素数量
(3)比较
==,!=,<,<=,>,>=
比较操作两端的容器必须属于同一类型
如果两个容器内的所有元素按序相等,那么这两个容器相等。
采用字典式顺序判断某个容器是否小于另一个容器
(4)赋值和交换
swap用于提高赋值操作效率
(5)与迭代器(iterator)相关的操作
begin()-返回一个迭代器,指向第一个元素
end()-返回一个迭代器,指向最后一个元素之后
rbegin()-返回一个逆向迭代器,指向逆向遍历的第一个元素
rend()-返回一个逆向迭代器,指向逆向遍历的最后一个元素之后
(6)元素操作
insert(pos,e)-将元素e的拷贝安插于迭代器pos所指的位置
erase(beg,end)-移除[begin,end]区间的所有元素
clear()-移除所有元素
insert(pos,e)-将元素e的拷贝安插于迭代器pos所指的位置
erase(beg,end)-移除[begin,end]区间的所有元素
clear()-移除所有元素
6、迭代器(iterator)
(1)可遍历STL容器内全部或部分元素的对象
(2)指出容器中的一个特定的位置
(3)迭代器的基本操作
* 返回当前位置上的元素值,如果该元素有成员,可以通过迭代器以operator->取用
++ 将迭代器前进至下一元素
==和!= 判断两个迭代器是否指向同一位置
= 为迭代器赋值(将所指元素的位置赋值过去)
(4)所有容器都提供获得迭代器的函数
begin()-返回一个迭代器,指向第一个元素
end()-返回一个迭代器,指向最后一个元素之后
半开区间[beg,end]的好处:
为遍历元素时循环的结束时机提供了简单的判断依据(只要未到达end(),循环就可以继续)
不必对空区间采取特殊处理(空区间的begin()就等于end())
(5)所有容器都提供两种迭代器
container::iterator以"读/写"模式遍历
container::const_iterator以"只读"模式遍历元素
(6)迭代器分类
双向迭代器
可以双向进行,以递增运算前进或以递减运算后退,可以用==和!=比较
list,map,和set提供双向迭代器
随机存取迭代器
除了具备双向迭代器的所有属性,还具备随机访问能力
可以对迭代器增加或减少一个偏移量,处理迭代器之间的距离,或者使用<和>之类的关系运算符比较两个迭代器
vector ,deque和string提供随机存取迭代器
迭代器持续有效,除非发生以下两种情况:
删除或插入元素
容量变化而引起内存重新配置
7、vector
(1)vector模拟动态数组//任意增大缩小
(2)vector的元素可以是任意类型T,但必须具备赋值和拷贝能力(具有public拷贝函数和重载的赋值操作符)
(3)必须包含的头文件#include<vector>
(4)vector支持随机存取
(5)vector的大小(size)和容量(capacity)
size 返回实际元素个数
capacity返回vector能容纳的元素的最大数量,如果插入元素时,元素个数超过capacity,需要重新配置内部存储器
//如果只有100个,当使用第101个时,自动增加10个
(6)构造、拷贝和析构
vector<T>c
vector保存类型为T的对象。默认构造函数v1为空,产生空的vector。
vector<T>c1(c2);
c1是c2的一个副本。产生同类型的c1,并将复制c2的所有元素
vector<T>c(n,e);
c包含n个值为i的元素。产生一个大小为n的vector,每个元素都是e
vector<T>c(n);
含有值初始化的元素的n个副本。利用类型T的默认构造函数和拷贝构造函数生成一个大小为n的vector
vector<T>c(beg,end)
产生一个vector,以区间[beg,end]为元素初值
~vector<T>()
销毁所有元素并释放内存
(7)非变动性操作
c.key_comp() //返回比较准则
c.value_comp() //返回对值比较的标准 (与key_comp()相同)
c.empty() //判断容器是否为空,与size()==0相同,但可能更快
c.size() //返回当前元素
c.max_size() //返回可容纳的元素最大数量(固定值)
c.capacity()//返回重新分配空间前可容纳的最大元素数量
c.reverse(n)//扩大容量为n
c1 == c2 //判断c1与c2是否相等
c1 != c2 //判断c1与c2是否不相等,等同于!(c1==c2)
c1 < c2 //判断c1是否小于c2
c1 > c2 //判断c1是否大于c2
c1 <= c2 //判断c1是否小于等于c2
c1 >= c2 //判断c1是否大于等于c2
(8)赋值操作
c 1= c2 //将c2所有元素赋值给c 1
c.assign(n,e) //将e的n个拷贝赋值给c
c.assign(beg,end)//将区间[beg,end]的元素赋值给c
c = rv //将右值对象rv的所有元素移动赋值给c
c = initlist //使用初始化列表进行赋值
c1.swap(c2) //交换c1和c2的数
swap(c1,c2) //交换c1和c2的数 ,全局函数(所有的赋值操作都有可能调用元素类型的默认构造函数,拷贝构造函数,赋值操作符和析构函数)
(9)元素存取
at(idx)//返回索引idx所标识得元素的引用,进行跨界检查
operator[](idx)//返回索引idx所标识的元素的引用,不进行越界检查
front()//返回第一个元素的引用,不检查元素是否存在
back()//返回最后一个元素的引用,不检查元素是否存在
(10)迭代器相关函数
begin()-返回一个迭代器,指向第一个元素
end()-返回一个迭代器,指向最后一个元素之后
rbegin()-返回一个逆向迭代器,指向逆向遍历的第一个元素
rend()-返回一个逆向迭代器,指向逆向遍历的最后一个元素之后
(11)安插(insert)元素
c.insert(pos,e)在pos位置插入元素e的副本,并返回新元素位置
c.insert(pos,n,e)在pos位置插入n个元素e的副本
c.insert(pos,beg,end)在pos位置插入区间[beg,end]内所有元素的副本
c.push_back(e)在尾部添加一个元素e的副本
(12)移除(remove)元素
c.pop_back()移除最后一个元素但不返回最后一个元素
c.erase(pos) 删除pos位置的元素,返回下一个元素的位置
c.erase(beg,end) 删除区间[beg,end]内所有的元素,返回下一个元素的位置
c.clear() 移除所有元素,清空容器
c.resize(num)将元素数量改为num(增加的元素用default构造函数产生,多余的元素被删除)
c.resize(num,e)将元素数量改为num(增加的元素是e的副本)
8、map/multimap
(1)使用平衡二叉树管理元素
(2)元素包含两部分(key,value),key和value可以是任意类型
(3)必须包含的头文件#include<map>
(4)根据元素的key自动对元素排序,因此根据元素的key进行定位很快,但根据元素的value定位很慢
(5)不能直接改变元素的key,可以通过operator[]直接存取元素值
(6)map中不允许key相同的元素,multimap允许key相同的元素
(7)构造、拷贝和析构函数
map c //默认构造函数;创建一个空map/multimap
map c(op) //创建一个空map/multimap,并以op原则作为排序准则
map c(c2) //复制构造函数;创建一个新的map/multimap作为c2的副本(所有元素都被复制)
map c = c2 //复制构造函数;创建一个新的map作为c2的副本(所有元素都被复制)
map c(beg,end) //创建一个map/multimap,并使用beg到end范围内的值进行初始化
map c(beg,end,op) //创建一个map/multimap,并使用beg到end范围内以op原则排序后的值进行初始化
map c(initlist) //创建一个map/multimap,并使用初始化列表进行初始化
map c = initlist //创建一个map/multimap,并使用初始化列表进行初始化
~map() //销毁所有元素并释放内存
其中map可以是下列形式
map<Key,Val> //以less<为排序准则的map
map<Key,Val,Op> //以op为排序准则的map
multimap<Key,Val> //以less<为排序准则的multimap
multimap<Key,Val,Op> //以op为排序准则的multimap
(8)非变动性操作
c.empty() //判断容器是否为空,与size()==0相同,但可能更快
c.size() //返回当前元素数量
c.max_size() //返回可容纳的元素最大数量
c1 == c2 //判断c1与c2是否相等
c1 != c2 //判断c1与c2是否不相等,等同于!(c1==c2)
c1 < c2 //判断c1是否小于c2
c1 > c2 //判断c1是否大于c2
c1 <= c2 //判断c1是否小于等于c2
c1 >= c2 //判断c1是否大于等于c2
c.key_comp() //返回比较准则
c.value_comp() //返回对值比较的标准 (与key_comp()相同)
(9)赋值
c1= c2 //将c2所有元素赋值给c1
c = initlist //使用初始化列表进行赋值
c1.swap(c2) //交换c1和c2的元素
swap(c1,c2) //交换c1和c2的元素,全局函数
(10)特殊查询操作
c.count(key) //返回键值为key的元素个数
c.find(key) //返回第一个键值为key的位置,若没找到返回end()
c.lower_bound(key) //返回键值为key的第一个可插入的位置,也就是键值 >= key的第一个元素位置
c.upper_bound(key) //返回键值为key的最后一个可插入的位置,也就是键值 > key的第一个元素位置
c.equal_range(key) //返回键值为key的可插入的第一个位置和最后一个位置的区间,也就是键值 == key的元素区间
(11)迭代器相关函数
begin()-返回一个双向迭代器,指向第一个元素
end()-返回一个双向迭代器,指向最后一个元素之后
rbegin()-返回一个逆向迭代器,指向逆向遍历的第一个元素
rend()-返回一个逆向迭代器,指向逆向遍历的最后一个元素之后
(12)安插元素
c.insert(val) //插入一个val的副本,返回新元素位置(对map来说不论成功与否)
c.insert(pos,val) //在pos位置为起点插入一个val副本,返回新元素位置(插入速度取决于pos)
c.insert(beg,end) //将范围beg到end的所有元素的副本插入到c(无返回值)
c.insert(initlist) //插入初始化列表的所有元素的副本(无返回值)
(13)移除元素
c.erase(val) //移除所有与val值相等的元素,并返移除的元素个数
c.erase(pos) //移除迭代器pos所指位置的元素
c.erase(beg,end) //移除beg到end范围内的所有元素,无返回值
c.clear() //移除所有元素,清空容器
9、set/multiset
(1)使用平衡二叉树管理元素
(2)集合(Set)是一种包含已排序对象的关联容器
(3)必须包含的头文件#include<set>
(4)map容器是键-值对的集合,好比以人名为键的地址和电话号码。相反的,set容器只是单纯的键的集合。当我们想知道某位用户是否存在时,使用set容器是最合适的
(5)set中不允许key相同的元素,multiset允许key相同的元素
(6)操作
begin()-返回指向第一个元素的迭代器
end()-返回指向最后一个元素的迭代器
clear()移除所有元素
erase()移除集合中的的元素
count() //返回某个值元素个数
equal_range() //返回集合中与给定值相等的上下限的两个迭代器
empty()如果集合为空,返回true
find()返回一个指向被查找到元素的迭代器
get_allocator()返回集合的分配器
insert() //在集合中插入元素
lower_bound() //返回指向大于(或等于)某值的第一个元素的迭代器
upper_bound() //返回大于某个值元素的迭代器
rbegin()-返回指向集合中最后一个元素的反向迭代器
rend()-返回指向集合中第一个元素的反向迭代器
size() //返回当前元素数量
max_size() //返回可容纳的元素最大数量
key_comp() //返回比较准则,返回一个用于元素间值比较的函数
swap()交换两个集合变量
value_comp() //返回对值比较的标准 (与key_comp()相同) ,返回一个用于比较元素间的值的函数
10、pair模板:
pair模板可以用于生成key-value对
11、算法
1、泛型算法通则
(1)所有算法的前两个参数都是一对iterators:[first,last),用来指出容器内一个范围内的元素。
(2)每个算法的声明中,都表现出它所需要的最低层次的iterator类型。
(3)大部分算法都可以用function object来更换准则,function object又称functor.
2、算法列表
accumulate() 元素累加
adjacent_difference() 相邻元素的差额
adjacent_find() 搜寻相邻的重复元素
binary_search() 二元搜寻
copy() 复制
copy_backward() 逆向复制
count() 计数
count_if() 在特定条件下计数
equal() 判断相等与否
equal_range() 判断相等与否(传回一个上下限区间范围)
fill() 改填元素值
fill_n() 改填元素值,n 次
find() 搜寻
find_if() 在特定条件下搜寻
find_end() 搜寻某个子序列的最后一次出现地点
find_first_of() 搜寻某些元素的首次出现地点
for_each() 对范围内的每一个元素施行某动作
generate() 以指定动作的运算结果充填特定范围内的元素
generate_n() 以指定动作的运算结果充填 n 个元素内容
includes() 涵盖於
inner_product() 内积
inplace_merge() 合并并取代(覆写)
iter_swap() 元素互换
lexicographical_compare() 以字典排列方式做比较
lower_bound() 下限
max() 最大值
max_element() 最大值所在位置
min() 最小值
min_element() 最小值所在位置
merge() 合并两个序列
mismatch() 找出不吻合点
next_permutation() 获得下一个排列组合
nth_element() 重新安排序列中第n个元素的左右两端
partial_sort() 局部排序
partial_sort_copy() 局部排序并复制到它处
partial_sum() 局部总和
partition() 切割
prev_permutation() 获得前一个排列组合
random_shuffle() 随机重排
remove() 移除某种元素(但不删除)
remove_copy() 移除某种元素并将结果复制到另一个 container
remove_if() 有条件地移除某种元素
remove_copy_if() 有条件地移除某种元素并将结果复制到另一个 container
replace() 取代某种元素
replace_copy() 取代某种元素,并将结果复制到另一个 container
replace_if() 有条件地取代
replace_copy_if() 有条件地取代,并将结果复制到另一个 container
reverse() 颠倒元素次序
reverse_copy() 颠倒元素次序并将结果复制到另一个 container
rotate() 旋转
rotate_copy() 旋转,并将结果复制到另一个 container
search() 搜寻某个子序列
search_n() 搜寻「连续发生 n 次」的子序列
set_difference() 差集
set_intersection() 交集
set_symmetric_difference() 对称差集
set_union() 联集
sort() 排序
stable_partition() 切割并保持元素相对次序
stable_sort() 排序并保持等值元素的相对次序
swap() 置换(对调)
swap_range() 置换(指定范围)
transform() 以两个序列为基础,交互作用产生第三个序列
unique() 将重复的元素摺叠缩编,使成唯一
unique_copy() 将重复的元素摺叠缩编,使成唯一,并复制到他处
upper_bound() 上限
以下是heap相同演算法
make_heap()制造一个heap
pop_heap()在heap中取出一个元素
push_heap()将一个元素推进heap内
sort_heap()对heap排序
3、算法使用示例
(1)count:
template<class InIt, class T>
size_t count(InIt first, InIt last, const T& val);
计算[first,last) 中等于val的元素个数
(2)count_if :
template<class InIt, class Pred, class Dist>
size_t count_if(InIt first, InIt last, Pred pr);
计算[first,last) 中符合pr(e) == true 的元素 e的个数
(3)min_element:
template<class FwdIt>
FwdIt min_element(FwdIt first, FwdIt last);
返回[first,last) 中最小元素的迭代器,以 “< ”作比较器
max_element:
template<class FwdIt>
FwdIt max_element(FwdIt first, FwdIt last);
返回[first,last) 中最大(不小)元素的迭代器,以 “< ”作比较器
(4)for_each:
template<class InIt, class Fun>
Fun for_each(InIt first, InIt last, Fun f);
对[first,last)中的每个元素 e ,执行 f(e) , 要求 f(e)不能改变e
(5)find
template<class InIt, class T>
InIt find(InIt first, InIt last, const T& val);
返回区间 [first,last) 中的迭代器 i ,使得 * i == val
(6) find_if
template<class InIt, class Pred>
InIt find_if(InIt first, InIt last, Pred pr);
返回区间 [first,last) 中的迭代器 i, 使得 pr(*i) == true
(7)binary_search
折半查找,要求容器已经有序且支持随机访问迭代器,返回是否找到
template<class FwdIt, class T>
bool binary_search(FwdIt first, FwdIt last, const T& val);
上面这个版本,比较两个元素x,y 大小时, 看 x < y
template<class FwdIt, class T, class Pred>
bool binary_search(FwdIt first, FwdIt last, const T& val, Pred pr);
上面这个版本,比较两个元素x,y 大小时, 看 pr(x,y)
(8) lower_bound,uper_bound,equal_range
lower_bound:
template<class FwdIt, class T>
FwdIt lower_bound(FwdIt first, FwdIt last, const T& val);
要求[first,last)是有序的,
查找大于等于val的最小的位置
upper_bound:
template<class FwdIt, class T>
FwdIt upper_bound(FwdIt first, FwdIt last, const T& val);
要求[first,last)是有序的,
查找大于val的最小位置
equal_range:
template<class FwdIt, class T>
pair<FwdIt, FwdIt> equal_range(FwdIt first, FwdIt last, const T& val);
要求[first,last)是有序的,
返回值是一个pair, 假设为 p, 则
[first,p.first) 中的元素都比 val 小
[p.second,last)中的所有元素都比 val 大
(9)sort快速排序
template<class RanIt>
void sort(RanIt first, RanIt last);
按升序排序。判断x是否应比y靠前,就看 x < y 是否为true
template<class RanIt, class Pred>
void sort(RanIt first, RanIt last, Pred pr);
按升序排序。判断x是否应比y靠前,就看 pr(x,y) 是否为true
(10)改变序列的算法
template<class FwdIt>
FwdIt unique(FwdIt first, FwdIt last);
用 == 比较是否相等
template<class FwdIt, class Pred>
FwdIt unique(FwdIt first, FwdIt last, Pred pr);
用 pr 比较是否等
去除[first,last) 这个升序序列中的重复元素
返回值是迭代器,指向元素删除后的区间的最后一个元素的后面
reverse
template<class BidIt>
void reverse(BidIt first, BidIt last);
颠倒区间[first,last)顺序
二、感悟
1、vector模拟动态数组,可以任意增大缩小
2、vector向量存储的元素可以是任意类型,默认可以容纳100个元素,不够自动每次加10
个
3、以后写程序要用vector取代数组
4、map查找速度很快
5、迭代器对象是对象的数据成员
6、键值可以作为map的下标使用
7、make_pair是pair的一个函数,是人为的将两个内容凑成整体
8、要想有序就要重载"<"
9、常函数只读不写
10、所有容器的使用都要定义迭代器
11、greater:按从大到小排序,less按升序排列
12、set和map都是二分查找
13、pair把两个不用的元素组合在一起
14、
(1)map:建立索引,查找方便
(2)set:一组复杂数据按序排列
15、copy(doubleSet.begin(),doubleSet.end(),output)//把set中指定范围的元素复制过来到输出流中在屏幕显示
16、迭代器对象是指针
17、binary_search会使原始数据破坏,尽量不要使用,可以选择map排序
18、unique:去重,把相同元素去掉,留下不相同的元素
19、reverse可以指定区间颠倒顺序
20、map等价于目录,位置在第二个位置,关键字为条件,重点使用multimap
21、每种查找方式要对应一个map
22、如果vector中的内容改变了,map中的内容也应随之改变
23、map只能用一个关键字查找
三、经典样例
#include<iostream>
#include<fstream>
#include<string>
#include<map>
#include<vector>
#include<algorithm>
using namespace std;
class DemoStatic{
public:
static int getNum(){return num;}
static void setNum(int n){num=n;}
private:
static int num;
};
int DemoStatic::num=0;//给静态数据成员赋初值
class Date{
public:
Date(){}//无参构造函数
Date(int y,int m,int d):year(y),month(m),day(d){}//有参构造函数
//get&set函数
int getYear(){return year;}
int getMonth(){return month;}
int getDay(){return day;}
void setYear(int y){year=y;}
void setMonth(int m){month=m;}
void setDay(int d){day=d;}
void display();//显示函数
//重载"<"比较日期大小
bool operator<(const Date&d)const{
return year!=d.year?year<d.year:month!=d.month?month<d.month:day<d.day;}
//重载输入输出流
friend ostream&operator<<(ostream&out,const Date&d);//整体输出Date对象数据
friend istream&operator>>(istream&in,Date&d);//整体输入Date对象数据
//重载赋值运算符
Date&operator=(const Date&d){
year=d.year;month=d.month;day=d.day;}
private:
int year;
int month;
int day;
};
void Date::display()
{
cout<<year<<" "<<month<<" "<<day<<endl;
}
ostream&operator<<(ostream&out,const Date&d)
{
out<<d.year<<" "<<d.month<<" "<<d.day<<endl;
return out;
}
istream&operator>>(istream&in,Date&d)
{
in>>d.year>>d.month>>d.day;
return in;
}
class Record{
public:
Record(){}//无参构造函数
Record(string s,Date b,Date e):str(s),begin(b),end(e){}//有参构造函数
//get&set函数
Date getDateB(){return begin;}//得到开始时间
Date getDateE(){return end;}//得到结束时间
string getStr(){return str;}
void setStr(int s){str=s;}
void display();//显示函数
//重载输入输出流
friend istream&operator>>(istream&in,Record&r);//整体输入Record对象数据
friend ostream&operator<<(ostream&out,Record&r);//整体输出Record对象数据
//重载赋值运算符
Record&operator=(const Record&r){
begin=r.begin;end=r.end;}
private:
string str;
Date begin;//开始时间
Date end;// 结束时间
};
void Record::display()
{
cout<<str<<endl;
begin.display();
end.display();
}
istream&operator>>(istream&in,Record&r)
{
in>>r.str;
if(r.str=="end")return in;//结束输入
in>>r.begin>>r.end;
return in;
}
ostream&operator<<(ostream&out,Record&r)
{
out<<r.str<<" "<<r.begin<<" "<<r.end<<endl;
return out;
}
struct cmp1
{
string str;
cmp1(string s){str=s;}
bool operator()(Record&r)
{return (r.getStr().find(str)!=string::npos);}
};
struct cmp2
{
int m;
cmp2(int mm){m=mm;}
bool operator()(Record&r)
{
return(r.getDateB().getMonth()<m);
}
};
/*struct cmp3
{Date d;
cmp3(Date dd){d=dd;}
bool operator()(Record&r)
{if(d==r.getDateB())
return r.getDateB();}
};*/
class Demo{
public:
Demo(){}
//Demo(){load();}//构造函数从文件读数据
//~Demo(){save();}//析构函数写数据到文件
void add();//增加多条记录
void add(Record r);//增加一条记录
void display();
int search1(string s);//按字符串查找
int search2(Date d);//按日期查找
void search3(string s);//按子串查找
void search4(int m);//查找小于m的月份的记录
void deleteByStr(string s);//按字符串删除
void deleteByDate(Date d);//按日期删除
private:
vector<Record>v;
vector<Record>::iterator it;
multimap<string,int>m1;//按字符串查找
multimap<string,int>::iterator mit1;
multimap<Date,int>m2;//按日期查找
multimap<Date,int>::iterator mit2;
};
void Demo::add()
{
Record r;
int i;
while(1){
cin>>r;
if(r.getStr()=="end")break;
v.push_back(r);
i=v.size();
m1.insert(make_pair(r.getStr(),i-1));
m2.insert(make_pair(r.getDateB(),i-1));
}}
void Demo::add(Record r)
{int i;
v.push_back(r);
i=v.size();
m1.insert(make_pair(r.getStr(),i-1));
m2.insert(make_pair(r.getDateB(),i-1));
}
void Demo::display()
{
cout<<"Static Date"<<" "<<DemoStatic::getNum()<<" "<<"Demo"<<endl;
for(it=v.begin();it!=v.end();it++)
cout<<*it;
}
int Demo::search1(string s)
{it=find_if(v.begin(),v.end(),cmp1(s));
mit1=m1.find(s);
if(mit1!=m1.end())
{cout<<"found"<<endl;
cout<<*it<<endl;
return mit1->second;
}
else cout<<"not found"<<endl;
return -1;
}
int Demo::search2(Date d)
{
mit2=m2.find(d);
if(mit2!=m2.end())
{cout<<"found"<<endl;
return mit2->second;
}
else
cout<<"not found"<<endl;
return -1;
}
void Demo::search3(string s)
{
it=find_if(v.begin(),v.end(),cmp1(s));
if(it!=v.end())
{cout<<"found"<<endl;
cout<<*it<<endl;
it=find_if(it+1,v.end(),cmp1(s));
}
else cout<<"not found"<<endl;
}
void Demo::search4(int m)
{
it=find_if(v.begin(),v.end(),cmp2(m));
if(it!=v.end())
{
cout<<"found"<<" ";
cout<<*it<<endl;
it=find_if(it+1,v.begin(),cmp2(m));
}
else cout<<"not found"<<endl;
}
void Demo::deleteByStr(string s)
{
int i;
//cout<<"i="<<i<<endl;
i=search1(s);
if(i!=-1){
it=v.begin()+i;
m2.erase(m2.find(it->getDateB()));
m1.erase(m1.find(s));
v.erase(it);
}
}
void Demo::deleteByDate(Date d)
{
int i;
i=search2(d);
if(i!=-1){
it=v.begin()+i;
m2.erase(m2.find(d));
m1.erase(m1.find(it->getStr()));
v.erase(it);
}
}
int main()
{
Date d1(2016,4,28),d2(2016,6,28);
/*d1.display();
d2.display();*/
Demo d;
Record r("sss",d1,d2);
r.display();
d.add(r);
d.display();
/*d.save();
d.load();
d.display();*/
d.search4(4);
cout<<endl;
d.search3("sss");
cout<<endl;
d.search3("ss");
cout<<endl;
d.search3("fff");
cout<<endl;
d.search2(d1);
cout<<endl;
d.search1("ss");
cout<<endl;
d.search1("sss");
cout<<endl;
d.deleteByDate(d2);
d.deleteByDate(d1);
//d.deleteByStr("sss");
//cout<<endl;
d.display();
d.search3("ff");
d.search4(7);
return 0;
}
#include<fstream>
#include<string>
#include<map>
#include<vector>
#include<algorithm>
using namespace std;
class DemoStatic{
public:
static int getNum(){return num;}
static void setNum(int n){num=n;}
private:
static int num;
};
int DemoStatic::num=0;//给静态数据成员赋初值
class Date{
public:
Date(){}//无参构造函数
Date(int y,int m,int d):year(y),month(m),day(d){}//有参构造函数
//get&set函数
int getYear(){return year;}
int getMonth(){return month;}
int getDay(){return day;}
void setYear(int y){year=y;}
void setMonth(int m){month=m;}
void setDay(int d){day=d;}
void display();//显示函数
//重载"<"比较日期大小
bool operator<(const Date&d)const{
return year!=d.year?year<d.year:month!=d.month?month<d.month:day<d.day;}
//重载输入输出流
friend ostream&operator<<(ostream&out,const Date&d);//整体输出Date对象数据
friend istream&operator>>(istream&in,Date&d);//整体输入Date对象数据
//重载赋值运算符
Date&operator=(const Date&d){
year=d.year;month=d.month;day=d.day;}
private:
int year;
int month;
int day;
};
void Date::display()
{
cout<<year<<" "<<month<<" "<<day<<endl;
}
ostream&operator<<(ostream&out,const Date&d)
{
out<<d.year<<" "<<d.month<<" "<<d.day<<endl;
return out;
}
istream&operator>>(istream&in,Date&d)
{
in>>d.year>>d.month>>d.day;
return in;
}
class Record{
public:
Record(){}//无参构造函数
Record(string s,Date b,Date e):str(s),begin(b),end(e){}//有参构造函数
//get&set函数
Date getDateB(){return begin;}//得到开始时间
Date getDateE(){return end;}//得到结束时间
string getStr(){return str;}
void setStr(int s){str=s;}
void display();//显示函数
//重载输入输出流
friend istream&operator>>(istream&in,Record&r);//整体输入Record对象数据
friend ostream&operator<<(ostream&out,Record&r);//整体输出Record对象数据
//重载赋值运算符
Record&operator=(const Record&r){
begin=r.begin;end=r.end;}
private:
string str;
Date begin;//开始时间
Date end;// 结束时间
};
void Record::display()
{
cout<<str<<endl;
begin.display();
end.display();
}
istream&operator>>(istream&in,Record&r)
{
in>>r.str;
if(r.str=="end")return in;//结束输入
in>>r.begin>>r.end;
return in;
}
ostream&operator<<(ostream&out,Record&r)
{
out<<r.str<<" "<<r.begin<<" "<<r.end<<endl;
return out;
}
struct cmp1
{
string str;
cmp1(string s){str=s;}
bool operator()(Record&r)
{return (r.getStr().find(str)!=string::npos);}
};
struct cmp2
{
int m;
cmp2(int mm){m=mm;}
bool operator()(Record&r)
{
return(r.getDateB().getMonth()<m);
}
};
/*struct cmp3
{Date d;
cmp3(Date dd){d=dd;}
bool operator()(Record&r)
{if(d==r.getDateB())
return r.getDateB();}
};*/
class Demo{
public:
Demo(){}
//Demo(){load();}//构造函数从文件读数据
//~Demo(){save();}//析构函数写数据到文件
void add();//增加多条记录
void add(Record r);//增加一条记录
void display();
int search1(string s);//按字符串查找
int search2(Date d);//按日期查找
void search3(string s);//按子串查找
void search4(int m);//查找小于m的月份的记录
void deleteByStr(string s);//按字符串删除
void deleteByDate(Date d);//按日期删除
private:
vector<Record>v;
vector<Record>::iterator it;
multimap<string,int>m1;//按字符串查找
multimap<string,int>::iterator mit1;
multimap<Date,int>m2;//按日期查找
multimap<Date,int>::iterator mit2;
};
void Demo::add()
{
Record r;
int i;
while(1){
cin>>r;
if(r.getStr()=="end")break;
v.push_back(r);
i=v.size();
m1.insert(make_pair(r.getStr(),i-1));
m2.insert(make_pair(r.getDateB(),i-1));
}}
void Demo::add(Record r)
{int i;
v.push_back(r);
i=v.size();
m1.insert(make_pair(r.getStr(),i-1));
m2.insert(make_pair(r.getDateB(),i-1));
}
void Demo::display()
{
cout<<"Static Date"<<" "<<DemoStatic::getNum()<<" "<<"Demo"<<endl;
for(it=v.begin();it!=v.end();it++)
cout<<*it;
}
int Demo::search1(string s)
{it=find_if(v.begin(),v.end(),cmp1(s));
mit1=m1.find(s);
if(mit1!=m1.end())
{cout<<"found"<<endl;
cout<<*it<<endl;
return mit1->second;
}
else cout<<"not found"<<endl;
return -1;
}
int Demo::search2(Date d)
{
mit2=m2.find(d);
if(mit2!=m2.end())
{cout<<"found"<<endl;
return mit2->second;
}
else
cout<<"not found"<<endl;
return -1;
}
void Demo::search3(string s)
{
it=find_if(v.begin(),v.end(),cmp1(s));
if(it!=v.end())
{cout<<"found"<<endl;
cout<<*it<<endl;
it=find_if(it+1,v.end(),cmp1(s));
}
else cout<<"not found"<<endl;
}
void Demo::search4(int m)
{
it=find_if(v.begin(),v.end(),cmp2(m));
if(it!=v.end())
{
cout<<"found"<<" ";
cout<<*it<<endl;
it=find_if(it+1,v.begin(),cmp2(m));
}
else cout<<"not found"<<endl;
}
void Demo::deleteByStr(string s)
{
int i;
//cout<<"i="<<i<<endl;
i=search1(s);
if(i!=-1){
it=v.begin()+i;
m2.erase(m2.find(it->getDateB()));
m1.erase(m1.find(s));
v.erase(it);
}
}
void Demo::deleteByDate(Date d)
{
int i;
i=search2(d);
if(i!=-1){
it=v.begin()+i;
m2.erase(m2.find(d));
m1.erase(m1.find(it->getStr()));
v.erase(it);
}
}
int main()
{
Date d1(2016,4,28),d2(2016,6,28);
/*d1.display();
d2.display();*/
Demo d;
Record r("sss",d1,d2);
r.display();
d.add(r);
d.display();
/*d.save();
d.load();
d.display();*/
d.search4(4);
cout<<endl;
d.search3("sss");
cout<<endl;
d.search3("ss");
cout<<endl;
d.search3("fff");
cout<<endl;
d.search2(d1);
cout<<endl;
d.search1("ss");
cout<<endl;
d.search1("sss");
cout<<endl;
d.deleteByDate(d2);
d.deleteByDate(d1);
//d.deleteByStr("sss");
//cout<<endl;
d.display();
d.search3("ff");
d.search4(7);
return 0;
}
最后
以上就是笨笨月亮为你收集整理的STL学习总结的全部内容,希望文章能够帮你解决STL学习总结所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复