STL为了提高代码复用性,提供一套标准的数据结构和算法。
STL六大组件:
1、容器 :各种数据结构,vector\list\map,用来存放数据
2、算法 : 各种常见算法,sort\find\copy、for_each等
3、迭代器 :连接容器和算法
4、仿函数 :行为类似函数 本质上是一个类
5、适配器 :修饰容器接口
6、空间配置器 :空间的配置和管理
1、vector容器
(deque 容器 双读数组,可以对头进行插入删除操作)
相比vector 数组的缺点有以下几个方面:
1. 数组的维度必须是常量表达式,即在初始化是必须给出。整个程序的运行过程中也不会改变。
2. 数组不允许拷贝和赋值,即不能将数组的内容拷贝到其他数组作为其初始值,但是vector可以。
3. vector容器可以动态扩展(寻找更大的内存空间,然后将元数据拷贝到新空间,释放原空间),数组是静态空间。
#include <algorithm> //标准算法头文件
#incldue <vector>
vector<int> v;
//迭代器可以看作是一个指针
vector<int>::iterator itBegin = v.begin(); //起始迭代器 指向容器第一位
vector<int>::iterator itEnd = v.end(); //结束迭代器 指向容器最后一位的下一位
//v.push_back(a); 向容器插入数据
//遍历方式1
while(itBegin != itBegin) {
cout<<*itBegin<<endl;
itBegin++;
}
//遍历方式2 (常用)
for(vector<int>::iterator it = v.begin;it != v.end(); it++){
cout<<*it<<endl;
}
//遍历方式3 STL提供
myPrint(int val){
cout<<val<<endl;
}
for_each(v.begin(),v.end(),myPrint);
//vector容器访问某个位置
for(int i = 0; i < v.size();i++) {
cout<<v[i]<<" "; //v.at[i]
}
cout<<endl;
//存放自定义数据类型
class person {
public:
person(string name,int age) {
this->m_name = name;
this->m_age = age;
}
private:
string m_name;
int m_age;
};
for(vector<person>::iterator it = v.begin;it != v.end(); it++){
cout<<(*it).m_name<<endl;
}
1、vector容器赋值
v2 = v1;
v3.assgin(v1.begin(),v1.end()); //左闭右开
v4.assgin(10,100); //10个100
2、容量和大小
empty() //容器是否为空
capacity() //容器的容量
size() //返回容器元素个数
resize(int num) //重新指定容器长度,变长补充,变短删除
resize(int num,elem) //变长则补充elem
3、插入和删除
push_back(ele) // 尾部插入元素
pop_back() // 尾部删除元素
insert(const_iterator pos ,ele) //迭代器指向位置pos插入元素
//insert(v.begin,100)
insert(const_iterator pos,int count,ele) //插入count个元素。
erase(const_iterator pos) //删除pos位置上的数据
//erase(v.begin())
erase(const_iterator start,const_iterator end) //删除区间的数据
clear() //删除容器全部元素
4、数据存取
v.front() //获取第一个元素
v.back() //获取最后一个元素
5、元素互换 //收缩内存空间 当定义10个元素的时候,内存空间自己开辟大于10的空间
v1.swap(v2) //指针互换
vector<int> (v).swap(v) //(v) 匿名对象 拷贝函数创建新的对象。 系统自己回收
6、预留空间
reserve(int len) //预留len个元素长度,预留位置不初始化,不可访问
vector容器优缺点:
优点:
1、有一段连续的内存空间,方便地进行随机存取,即 [] 操作符,
缺点:
1、内存区域是连续的,它中间插入或删除某个元素,需要复制并移动现有的元素。
2、当被插入的内存空间不够时,需要重新申请一块足够大的内存并进行内存拷贝。值得注意的是,vector每次扩容为原来的两倍,对小对象来说执行效率高,但如果遇到大对象,执行效率就低了。
2、map容器
功能:
1、map中的所有元素都是pair
2、pair中的第一个元素为key(键值),第二个元素为value(实值)
3、所有元素都会根据键值自动排序
map和multimap 始于关联式容器,底层由二叉树实现。
优点:可以根据键值快速找到value
map和multimap的区别:
1、map不允许容器中有重复key值元素
2、multimap允许有重复的key值元素
map功能实现:
1、构造和赋值
map<T1,T2> mp; //map<int,int> m;
map(const map &mp); //map<int,int> m2(m);
//、、、、、、、、、、、、、、、、
map<int,int> m;
m.insert(pair<int,int> (1,10)); //插入
//、、、、、输出、、、、、、、、、
void printmap(map<int ,int > &ma) {
for(map<int,int>::iterator it = ma.begin(); it != ma.end(); it++) {
cout<<"key"<<(*it).first<<"value"<<(*it).second<<endl;
}
}
//、、、、、赋值、、、、、、、、、
map& operator=<const map &mp>; // m3 = m2
2、大小和交换
size(); //返回容器元素个数
empty();//判断容器是否为空
swap(st); //交换两个容器
3、插入和删除
clear() //清除所有元素
erase(pos) //删除pos迭代器指向的元素,返回下一个元素的迭代器
erase(m.begin(),m.end());
erase(key); //删除key的元素 erase(3) 按照key删除
m.insert(pair<int,int> (1,10)); //插入
m.insert(make_pair(2,10));
4、查找和统计
5、排序,改变排序规则
class compare {
public:
bool operator()(int v1,int v2) {
return v1 >v2;
}
};
map<int,int,compare> m;
m.insert(make_pair(1,10));
for(map<int,int>::iterator it = m.begin(); it != m.end();it ++) {
cout<<"key = "<<(*it).first <<(*it).second<<endl;
}
3、list容器
list本质是链表,非连续线性空间存储数据,迭代器不支持随机访问
功能:将数据进行链式存储
优点:对任意位置进行插入或者删除元素,不需要移动大量元素。
采用动态分配不会造成内存的浪费或者溢出。
缺点:遍历速度慢,占用空间比数组大。
//插入和删除的时候,不会造成原有迭代器的失效,vector容器不成立
链表:一种物理储存单元非连续,数据元素通过链表中的指针链接实现的。
链表的组成:链表由一系列节点组成。
节点的组成:包括存储数据元素的数据域和存储下一个节点地址的指针域。
STL中的链表是双向循环链表。有指向前端和后端的指针。
list容器功能:
list<int> L1;
void myprint(const list<int> &L){
for(list<int> ::const_itreator it = l.begin(); it != l.end(); it++) {
cout<<*it<<endl;
}
//第一种构造
L1.push_back(ele);
//第二种构造
list<int> L2(L1.begin(),L1.end());
2、赋值和交换
L1 = L;
list<int> L2(L);
L2.assgin(l.begin(),l.end()); //赋值操作
L3.assgin(10,100);
l1.swap(l2);//交换
3、大小操作
l.size(); //元素个数
l.resize(int num,ele);//变长则补充elem
l.empty(); //是否为空
4、插入和删除
push_back(ele) //尾部插入
pop_back() //尾部删除
push_front(ele) //首部插入
pop_front() //首部删除
insert(pos,ele) //在pos位置,插入ele 迭代器
//l.insert(l.begin(),100);
//list<int> ::iterator it = l.begin();
//l.insert(++it,100);
insert(pos,n,ele) //插入n个ele
//insert(pos,beg(),end());
clear() //移除全部数据
erase(begin(),end()) //删除区间 迭代器
erase(pos) //删除位置
remove(ele) /删除所有ele
5、数据存取
l1[10] at(10) // 不可以用中括号和at方式访问容器中的元素
l.front() //获取第一个元素
l.back() //获取最后一个元素
6、反转和排序
//反转
l.reverse();
//排序
//不支持随机访问的容器,不能用标准算法.
//不支持的会内部会提供一些算法。
l.sort(); //从小到大
//从大到小
bool myCompare(int v1,int v2) {
return v1>v2;
}
l.sort(myCompare);
//排序案例
//按照年纪升序,年龄相同身高降序。
bool myCompare(Person &p1,Person &P2) {
if(p1.m_age = p2.m_age){
return p1.m_height > p2.m_height;
}
return p1.m_age < p2.m_age;
}
l.sort(myCompare);
4、set容器
功能: 所有的元素插入的时候自动排序
set/multiset 属于关联式容器,底层结构用二叉树实现。
set: 不允许容器有重复的元素 不可以插入重复数据,插入同时返回插入结果,表示插入是否成功
multiset: 允许有重复的元素 可以插入重复数据
//判断是否插入成功
set<int> s;
//pair<set<int>::iterator,bool> ret = s.insert(10);
if(ret.second) {
cout<<"插入成功"<<endl;
}
else {
cout<<"插入失败"<<endl;
}
//pair对组的创建
pair<string,int> p("TOM",20);
pair<string,int> p2 = make_pair("TOny".30);
cout<<" name "<<p.first<<" age "<<p.second<<endl;
set容器功能:
1、构造和赋值
set<int> s1;
set<int> s2(s1); //set(const set&st);
s3 = s1; //set& operator<const set &st>
2、插入数据(只有insert())
set<int> st;
st.insert(10);
3、大小和交换
set<int> s;
s.empty();
s.swap();
4、查找和统计 //对set容器进行查找数据以及统计数据
s.find(key); //查找key是否存在,返回元素的迭代器,若不存在,返回set.end();
set<int>::iterator pos=s.find(key);
if(pos != s1.end()){
cout<<"找到元素:"<<endl;
}
else {
cout<<"没找到元素"<<endl;
}
s.count(key); //统计key的个数 0、1
set容器排序:
//利用仿函数,可以改变排序规则
class myconpare {
public:
bool operator()(int v1,int v2) { //重载小括号
return v1 > v2;
}
};
set<int,mycompare> s;
自定义数据结构怎么排序
//存放自定义的数据类型进行排序
class person {
public:
person(string name ,int age) {
this->m_name = name;
this->m_age = age;
}
string m_name;
int m_age;
};
class mycompare {
public:
bool operator()(const person &p1,const person &p2) { //重载小括号
return p1.m_age > p2.m_age;
}
};
//创建对象
set<person,mycompare> s;
person p1("tony",10);
//自定义数据类型,指定排序规则,利用仿函数进行
s.insert(p1);
//输出
for(set<person,mycompare>::iterator it = s.begin(); it != s.end();it++){
cout<<"姓名:"<<it.m_name<<"年龄: "<<it.m_age<<endl;
}