心得体会:
STL是一些常用数据结构和算法的模板的集合,有了STL,我们不必编写大多数常用的数据结构和算法,能够带来很大方便,效率很高,哪怕只写十几行程序,也可能用到STL中提供的数据和算法,例如对数组排序,sort算法往往只需要一条语句便可以完成
一、STL 概述
1. STL组件
容器:管理某类对象的集合
迭代器:在集合对象上进行遍历
算法:处理集合内的元素
容器适配器
函数对象
2. STL容器类别
序列式容器:排列次序取决于插入时机和位置
关联式容器:排列次序取决于特定准则
3. STL容器的共同能力
所有容器中存放的都是值而非引用。如果希望存放的不是副本,容器元素只能是指针。
所有元素都能形成一个次序,可以按相同的次序一次或多次遍历每个元素
4.STL容器元素的条件
对于基本数据类型(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) 与大小相关的操作操作 | 效果 |
* | 返回当前位置上的元素值。如果该元素有成员,可以通过迭代器以operator ->取用 |
++ | 将迭代器前进至下一元素 |
==和!= | 判断两个迭代器是否指向同一位置 |
= | 为迭代器赋值(将所指元素的位置赋值过去) |
操作 | 效果 |
begin() | 返回一个迭代器,指向第一个元素 |
end() | 返回一个迭代器,指向最后一个元素之后 |
半开区间[beg, end)的好处:
1.为遍历元素时循环的结束时机提供了简单的判断依据(只要未到达end(),循环就可以继续)
2.不必对空区间采取特殊处理(空区间的begin()就等于end())
list<int> l;
for(pos=l.begin();pos!=l.end();++pos{
…
}
vector<int> v;
for(pos=v.begin();pos<v.end();++pos{
…
}
构造、拷贝和析构
操作 | 效果 |
vector<T> c | 产生空的vector |
vector<T> c1(c2) | 产生同类型的c1,并将复制c2的所有元素 |
vector<T> c(n) | 利用类型T的默认构造函数和拷贝构造函数生成一个大小为n的vector |
vector<T> c(n,e) | 产生一个大小为n的vector,每个元素都是e |
vector<T>c(beg,end) | 产生一个vector,以区间[beg,end]为元素初值 |
~vector<T>() | 销毁所有元素并释放内存。 |
操作 | 效果 |
c.size() | 返回元素个数 |
c.empty() | 判断容器是否为空 |
c.max_size() | 返回元素最大可能数量(固定值) |
c.capacity() | 返回重新分配空间前可容纳的最大元素数量 |
c.reserve(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 | 将c2的全部元素赋值给c1 |
c.assign(n,e) | 将元素e的n个拷贝赋值给c |
c.assign(beg,end) | 将区间[beg,end]的元素赋值给c |
c1.swap(c2) | 将c1和c2元素互换 |
swap(c1,c2) | 同上,全局函数 |
所有的赋值操作都有可能调用元素类型的默认构造函数,拷贝构造函数,赋值操作符和析构函数
std::list<T> l;
std::vector<T> v;
…
v.assign(l.begin(),l.end());
操作 | 效果 | |
at(idx) | 返回索引idx所标识的元素的引用,进行越界检查 | |
operator [](idx) | 返回索引idx所标识的元素的引用,不进行越界检查 | |
front() | 返回第一个元素的引用,不检查元素是否存在 | |
back() | 返回最后一个元素的引用,不检查元素是否存在 |
std::vector<T> v;//empty
v[5]= t; //runtimeerror
std::cout << v.front(); //runtime error
操作 | 效果 |
begin() | 返回一个迭代器,指向第一个元素 |
end() | 返回一个迭代器,指向最后一个元素之后 |
rbegin() | 返回一个逆向迭代器,指向逆向遍历的第一个元素 |
rend() | 返回一个逆向迭代器,指向逆向遍历的最后一个元素 |
迭代器持续有效,除非发生以下两种情况:
(1)删除或插入元素
(2)容量变化而引起内存重新分配
操作 | 效果 |
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的副本 |
操作 | 效果 |
c.pop_back() | 移除最后一个元素但不返回最后一个元素 |
c.erase(pos) | 删除pos位置的元素,返回下一个元素的位置 |
c.erase(beg,end) | 删除区间[beg,end]内所有元素,返回下一个元素的位置 |
c.clear() | 移除所有元素,清空容器 |
c.resize(num) | 将元素数量改为num(增加的元素用defalut构造函数产生,多余的元素被删除) |
c.resize(num,e) | 将元素数量改为num(增加的元素是e的副本) |
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
int main()
{
vector<int>a;//建立容器
for(int i = 0; i <5; ++i)
{
a.push_back(5 -i);//存储数据
}
cout <<"Size: " << a.size() << endl;//输出实际大小
a.pop_back();//删除尾元素
a[0] = 1;//赋值
cout <<"Size: " << a.size() << endl;
for(int i = 0; i <(int)a.size(); ++i)
{
cout <<a[i] << ", ";
}
cout << endl;
sort(a.begin(),a.end());//排序
cout <<"Size: " << a.size() << endl;
for(int i = 0; i <(int)a.size(); ++i)
{
cout <<a[i] << ", ";
}
cout << endl;
a.clear();//清空
cout <<"Size: " << a.size() << endl;
return 0;
}
操作 | 效果 |
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<key,value> 一个以less(<)为排序准则的map,
map<key,value,op> 一个以op为排序准则的map
操作 | 效果 |
c.size() | 返回元素个数 |
c.empty() | 判断容器是否为空 |
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 | 将c2的全部元素赋值给c1 |
c1.swap(c2) | 将c1和c2的元素互换 |
swap(c1,c2) | 同上,全局函数 |
操作 | 效果 |
count(key) | 返回”键值等于key”的元素个数 |
find(key) | 返回”键值等于key”的第一个元素,找不到返回end |
lower_bound(key) | 返回”键值大于等于key”的第一个元素 |
upper_bound(key) | 返回”键值大于key”的第一个元素 |
equal_range(key) | 返回”键值等于key”的元素区间 |
操作 | 效果 |
begin() | 返回一个双向迭代器,指向第一个元素 |
end() | 返回一个双向迭代器,指向最后一个元素之后 |
rbegin() | 返回一个逆向迭代器,指向逆向遍历的第一个元素 |
rend() | 返回一个逆向迭代器,指向逆向遍历的最后一个元素 |
操作 | 效果 |
c.insert(pos,e) | 在pos位置为起点插入e的副本,并返回新元素位置(插入速度取决于pos) |
c.insert(e) | 插入e的副本,并返回新元素位置 |
c.insert(beg,end) | 将区间[beg,end]内所有元素的副本插入到c中 |
操作 | 效果 |
c.erase(pos) | 删除迭代器pos所指位置的元素,无返回值 |
c.erase(val) | 移除所有值为val的元素,返回移除元素个数 |
c.erase(beg,end) | 删除区间[beg,end]内所有元素,无返回值 |
c.clear() | 移除所有元素,清空容器 |
map应用实例
#include <iostream>
#include <map>
#include <algorithm>
using namespace std;
struct T1
{
int v;
bool operator <(const T1 &a)const
{
return (v <a.v);
}
};
struct T2
{
int v;
};
struct cmp
{
bool operator () (const T2 &a, const T2&b)const
{
return (a.v <b.v);
}
};
int main()
{
map<T1,int>mt1;
map<T2, int,cmp>mt2;
map<string,int> m2;
map<string,int>::iterator m2i, p1, p2;
//map<string, int,greater<string> >m2;//greater<string>默认小大排序
//map<string, int,greater<string> >::iterator m2i, p1, p2;//迭代器
m2["abd"] =2;
m2["abc"] =1;
m2["cba"] =2;
m2.insert(make_pair("aaa", 9));
//make_pair 属于算法的内容,将两盒数组合成整体
m2["abf"] =4;
m2["abe"] =2;
cout <<m2["abc"] << endl;
m2i=m2.find("cba");
if(m2i != m2.end())
{
cout <<m2i->first << ": " <<m2i->second << endl;
}
else
{
cout <<"find nothing" << endl;
}
cout <<"Iterate" << endl;
for(m2i = m2.begin();m2i != m2.end(); m2i++)
{
cout <<m2i->first << ": " <<m2i->second << endl;
}
return 0;
}
multimap应用实例
#include <iostream>
#include <map>
#include <algorithm>
using namespace std;
int main()
{
multimap<string,int> mm1;
multimap<string,int>::iterator mm1i, p1, p2;
mm1.insert(make_pair("b", 3));
mm1.insert(make_pair("a", 0));
mm1.insert(make_pair("b", 5));
mm1.insert(make_pair("c", 4));
mm1.insert(make_pair("b", 2));
cout <<"Size: " << mm1.size() << endl;
for(mm1i =mm1.begin(); mm1i != mm1.end(); mm1i++)
{
cout <<mm1i->first << ": " <<mm1i->second << endl;
}
cout <<"COUNT: " << mm1.count("b")<< endl;//b 的个数
cout <<"Bound: " << endl;
p1=mm1.lower_bound("b");
p2=mm1.upper_bound("b");
for(mm1i = p1; mm1i!= p2; mm1i++)
{
cout <<mm1i->first << ": " <<mm1i->second << endl;
}
return 0;
}
使用平衡二叉树管理元素
操作 | 效果 |
返回指向第一个元素的迭代器 | |
清除所有元素 | |
返回某个值元素的个数 | |
如果集合为空,返回true | |
返回指向最后一个元素的迭代器 | |
返回集合中与给定值相等的上下限的两个迭代器 | |
删除集合中的元素 | |
返回一个指向被查找到元素的迭代器 | |
返回集合的分配器 |
操作 | 效果 |
在集合中插入元素 | |
返回指向大于(或等于)某值的第一个元素的迭代器 | |
返回一个用于元素间值比较的函数 | |
返回集合能容纳的元素的最大限值 | |
返回指向集合中最后一个元素的反向迭代器 | |
返回指向集合中第一个元素的反向迭代器 | |
集合中元素的数目 | |
交换两个集合变量 | |
返回大于某个值元素的迭代器 | |
返回一个用于比较元素间的值的函数 |
#include<iostream>
#include <set>
#include<algorithm>
using namespace std;
struct T1
{
int key;
int value1, value2;
bool operator<(const T1 &b)const
{
return (key < b.key);
}
};
struct T2
{
int key;
int v1, v2;
};
struct T2cmp
{
bool operator()(const T2 &a, const T2&b)const
{
return (a.key < b.key);
}
};
int main()
{
multiset<T1> s2;
multiset<T2, T2cmp> s3;
multiset<string>s1;
multiset<string>::iterator iter1;
//multiset<string, greater<string>>s1;//默认的小大排序形式
//multiset<string, greater<string>>::iterator iter1;
s1.insert("abc");
s1.insert("abc");
s1.insert("abc");
s1.insert("bca");
s1.insert("aaa");
cout << "ITERATE:" <<endl;
for(iter1 = s1.begin(); iter1 != s1.end();iter1++)
{
cout << (*iter1) << endl;
}
cout << "FIND:" <<endl;
iter1 = s1.find("abc");
if(iter1 != s1.end())
{
cout << *iter1 << endl;
}
else
{
cout << "NOT FOUND"<< endl;
}
cout << "COUNT: " <<s1.count("abc")<< endl;//个数
cout << "BOUND: " <<endl;
multiset<string>::iterator s1i, p1,p2;
p1= s1.lower_bound("abc");
p2= s1.upper_bound("abc");
for(s1i = p1; s1i != p2; s1i++)
{
cout << (*s1i) << endl;
}
return 0;
}
Algorithm(算法)