长久以来,软件界一直希望建立一种可重复利用的东西
C++的面向对象和泛型编程思想,目的就是复用性的提升
大多情况下,数据结构和算法都未能有一套标准,导致被迫从事大量重复工作
为了建立数据结构和算法的一套标准,诞生了STL
STL(Standard Template Library,标准模板库)
STL从广义上分为:容器(container)算法(algorithm)迭代器(iterator)
容器和算法之间通过迭代器进行无缝连接
STL几乎所有的代码都采用了模板类或者模板函数
STL大体分为六大组件,分别是:容器、算法、迭代器、仿函数、适配器(配接器)、空间配置器
容器:各种数据结构,如vector、list、deque、set、map等,用来存放数据。
算法:各种常用的算法,如sort、find、copy、for_each等。
迭代器:扮演了容器与算法之间的胶合剂。
仿函数:行为类似函数。可作为算法的某种策略。(重载小括号)
适配器:一种用来修饰容器或者仿函数或迭代器接口的东西。
空间配置器:负责空间的配置与管理。
容器:置物之所也
STL容器就是将运用最广泛的一些数据结构实现出来
常用的数据结构:数组,链表,树,栈,队列,集合,映射表等
这些容器分为序列式容器和关联式容器两种:
序列式容器:强调值的排序,序列式容器中的每个元素均有固定的位置。
关联式容器:二叉树结构,各元素之间没有严格的物理上的顺序关系
算法:问题之解法也
有限的步骤,解决逻辑或数学上的问题,这一门学科我们叫做算法(Algorithms)
算法分为质变算法和非质变算法
质变算法:是指运算过程中会更改区间内的元素的内容。例如拷贝,替换,删除等等
非质变算法:是指运算过程中不会更改区间内的元素内客,例如查找、计数、遍历、寻找极值等等
迭代器:容器和算法之间粘合剂
提供一种方法,使之能够依序寻访某个容器所含的各个元素,而又无需暴露该容器的内部表示方式。
每个容器都有自己专属的迭代器
迭代器使用非常类似于指针,初学阶段我们]可以先理解迭代器为指针
迭代器种类:
种类 | 功能 | 支持运算 |
---|---|---|
输入迭代器 | 对数据的只读访问 | 只读,支持++、==、!= |
输出迭代器 | 对数据的只写访问 | 只写,支持++ |
前向迭代器 | 读写操作,并能向前推进迭代器 | 读写,支持++、==、!= |
双向迭代器 | 读写操作,并能向前和向后操作 | 读写,支持++、-- |
随机访问迭代器 | 读写操,可以以跳跃的方式访问任意数据,是功能最强的迭代器 | 读写,支持++、--、[n]、-n、<、<=、>、>= |
常用的容器中迭代器种类为双向迭代器,和随机访问迭代器
功能:
vector数据结构和数组非常相似,也称为单端数组
vector与普通数组区别:
不同之处在于数粗是静态空间,而vector可以动态扩展
动态扩展:
并不是在原空间之后接新空间,而是找更大的内存空间。然后将原款据拷贝新空间,释放原空间
vector容器的迭代器是支持随机访问的迭代器
功能描述:
创建vector客器
函数原型:
vector
采用模板实现类实现,默认构造函数
vector(v.begin(), v.end());
将v[begin().end()]区间中的元素拷贝给本身
vector(n, elem)
构造函数将n个elem拷贝给本身。
vector(const vector &vec);
作拷贝构造函数。
#include
#include
using namespace std;
void printVector(vector&v)
{
for(vector::iterator it = v.begin();it != v.end(); it++)
{
cout << *it << " ";
}
cout << endl;
}
//vector容器构造
void test01()
{
vectorv1;//默认构造 无参构造
for(int i = 0;i < 10; i++)
{
v1.push_back(i);
}
printVector(v1);
//通过区间的形式进行构造
vectorv2(v1.begin(), v1.end());
printVector(v2);
//n个elem方式构造
vectorv3(10, 100);
printVector(v3);
//拷贝构造
vectorv4(v3);
printVector(v4);
}
int main()
{
test01();
return 0;
}
功能描述:
给vector容器进行联值
函数原型:
vector operator=(const vector&vec);
重载等号操作符
assign(beg,end);
将[beg,end)区间中的数据拷贝赋值给本身。
assign(n,elem);
将n个elem拷贝赋值给本身。
#include
#include
using namespace std;
//打印函数
void printVextor(vector& v)
{
for(vrctor::iterator it = v.begin();it != v.end(); it++)
{
cout << *it << " ";
}
cout << endl;
}
//vector容器赋值操作
void test01()
{
vectorv1;
for(int i = 0;i < 10; i++)
{
v1.push_back(i);
}
printVector(v1);
//1.赋值 operator
vectorv2;
v2 = v1;
printVector(v2);
//2.assign
vectorv3;
v3.assign(v1.begin(),v2.end());
printVector(v3);
//3.n个elem方式
vectorv4;
v4.assign(10, 100);
printVector(v4);
}
int main()
{
test01();
return 0;
}
总结:vector赋值方式比较简单,使用operator=或者assign都可以
功能描述:
对vector容器的容量和大小操作
函数原型:
empty();
判断容器是否为空
capacity():
容器的容量
size();
返回容器中元素的个数
resize(int num);
重新指定容器的长度为num,若容器变长,则以默认值填充新位置。 如果容器变短,则末尾超出容器长度的元素被删除。
resize(int num, e1em):
更新指定容器的长度为num,若容器变长,则以elem值填充新位置。 如果容器变短,则末尾超出容器长度的元素被删除
示例:
#include
#include
using namespace std;
void printVector(vector& v)
{
for(vector::iterator it = v.begin();it != v.end(); it++)
{
cout << *it << " ";
}
cout << endl;
}
//vector容器的容量和大小操作
void test01()
{
vectorv1;
for(int i = 0;i < 10; i++)
{
v1.push_back(i);
}
printVector(v1);
//判断是否为空
if(v1.empty())//为真 则代表容器为空
{
cout << "v1为空" << endl;
}
else
{
cout << "v1不为空" << endl;
cout << "v1的容量为:" << v1.capacity() << endl;
cout << "v1的大小为:" << v1.size() << endl;
}
//重新指定大小
v1.resize(20);//利用重载版本,可以指定默认填充值
printVector(v1);//如果重新指定的比原来长,默认用0来填充新的位置,也可以自己定义,v1.resize(20,100);后面补充的就全为100
v1.resize(5);
printVector(v1);//若重新指定的比原来短了,超出部分会被删除
}
int main()
{
test01();
return 0;
}
总结:
判断是否为空一empty
返回元素个数一size
返回容器容量一capacity
新指定大小resize
功能描述:
对vector容器进行插入、删除操作
函数原型:
push_back(ele);
尾插入元素ele
pop_back();
删除最后一个元素
insert(const_iterator pos,ele);
迭代器指向位置pos插入元素ele
insert(const_iterator pos,int count,ele);
迭代器指向位置pos插入count个元素ele
erase(const_iterator pos);
由删除迭代器指向的元素
erase(const_iterator start,const_iterator end);
删除迭代器从start到end之间的元素
clear();
删除容器中所有元素
示例:
#include
#include
using namespace std;
void printVector(vectorv)
{
for(vector::iterator it = v.begin(); it != v.end(); it++)
{
cout << *it << " ";
}
cout << endl;
}
//vector容器的插入和删除
void test01()
{
vectorv1;
for(int i = 0;i < 10; i++)
{
v1.push_back(i);
}
printVector(v1);
//尾插元素ele
v1.push_back(10);
printVector(v1);
//删除最后一个元素
v1.pop_back();
printVector(v1);
//迭代器指定位置pos插入元素ele
v1.insert(v1.begin(),11);
printVector(v1);
//迭代器指向位置pos插入一系列元素
v1.insert(v1.begin(),2,12);
printVector(v1);
//删除 参数也是迭代器
v1.erase(v1.begin());
printVector(v1);
//清空
//v1.erase(v1.begin(), v1.end());相当于clear清空
v1.erase(v1.begin(), v1.end());
printVector(v1);
}
int main()
{
test01();
return 0;
}
功能描述:
对vector中的数据的存取操作
函数原型:
at(int idx);
返回索引idx所指的数据
operator[];
返回索引idx所指的数据
front();
返回容器中第一个数据元素
back();
返回容器中最后一个数据元素
示例:
#include
#include
using namespace std;
//vector容器 数据存取
void test01()
{
vectorv1;
for(int i = 0;i < 10; i++)
{
v1.push_back(i);//尾插法
}
//利用[]方式访问数组中的元素
for(int i = 0;i < v1.size(); i++)
{
cout << v1[i] << " ";
}
cout << endl;
//利用at方式访问元素
for(int i = 0;i < v1.size(); i++)
{
cout << v1.at(i) << " ";
}
cout << endl;
//输出第一个元素
cout << "第一个元素为:" << v1.front() << endl;
//输出最后一个元素
cout << "最后一个元素为:" << v1.back() << endl;
}
int main()
{
test01();
return 0;
}
总结:
除了用迭代器获取vector容器中元素,[]和at也可以
front返回容器第一个元素
back返回容器最后一个元素
功能描述:
实现两个容器内元素进行互换
函数原型:
swap(vec);
将vec与本身的元素互换
示例:
#include
#include
using namespace std;
void printVector(vector&v)
{
for(vector::iterator it = v.begin();it != v.end(); it++)
{
cout << *it << " ";
}
cout << endl;
}
//vector容器互换
//基本使用
void test01()
{
vectorv1;
for(int i = 0;i < 10; i++)
{
v1.push_back(i);
}
cout << "交换前,v1:";
printVector(v1);
vectorv2;
for(int i = 10;i > 0; i--)
{
v2.push_back(i);
}
cout << "交换前,v2:";
printVector(v2);
v1.swap(v2);
cout << "交换后,v1:";
printVector(v1);
cout << "交换后,v2:";
printVector(v2);
}
//实际用途
//巧用swap可以收缩内存空间
void test02()
{
vectorv;
for(int i = 0;i < 100000; i++)
{
v.push_back(i);
}
cout << "v的容量为:" << v.capacity() << endl;
cout << "v的大小为:" << v.size() << endl;
//重新指定大小
v.resize(3);
cout << "v的容量为:" << v.capacity() << endl;
cout << "v的大小为:" << v.size() << endl;
//巧用swap收缩内存
vector(v).swap(v);//vector(v)匿名对象
cout << "v的容量为:" << v.capacity() << endl;
cout << "v的大小为:" << v.size() << endl;
}
int main()
{
test01();
test02();
return 0;
}
交换前,v1:0 1 2 3 4 5 6 7 8 9 交换前,v2:2 2 2 2 2 2 2 2 2 2 交换后,v1:2 2 2 2 2 2 2 2 2 2 交换后,v2:0 1 2 3 4 5 6 7 8 9
总结:swap可以使两个容器互换,可以达到实用的收缩内存的效果。
功能描述:
减少vector在动态扩展容量时的扩展次数
函数原型:
reserve(int len);
容器预留len个元素长度,预留位置不初始化,元素不可访问。
示例:
//没有reserve,那么扩展容量次数就会很多次
#include
#include
using namespace std;
//vector容器 预留空间
void test01()
{
vectorv;
int num = 0;//统计开辟次数
int *p = NULL;
for(int i = 0;i < 10000; i++)
{
v.push_back(i);
if(p != &v[0])
{
p = &v[0];
num++;
}
}
cout << "num = " << num << endl;
}
int main()
{
test01();
return 0;
}
//reserve
#include
#include
using namespace std;
//vector容器 预留空间
void test01()
{
vectorv;
//利用reserve预留空间
v.reserve(10000);
int num = 0;//统计开辟次数
int *p = NULL;
for(int i = 0;i < 10000; i++)
{
v.push_back(i);
if(p != &v[0])
{
p = &v[0];
num++;
}
}
cout << "num = " << num << endl;//输出num = 1
}
int main()
{
test01();
return 0;
}
总结:如果数据比较大,可以一开始利用reserve预留空间
功能:
双端数组,可以对头端进行插入删除操作
deque与vector区别:
vectors对于头部的插入除效率低,数据量越大,效率越低
deque相对而言,对头部的插入删除速度可比vector快
vector访问元素时的速度会比deque快,这和两者内部实现有
deque内部工作原理:
deque内部有个中控器,维护每段缓冲区中的内容,缓冲区中存放真实数据
中控器维护的盛每个缓冲区的地址,使得使用deque时像一片连续的内存空间
deque容器的迭代器也是支持随机访问的
功能描述:
dequet容器构造
函数原型:
dequec
默认构造形式
deque(beg, end);
构造函数将[beg,end)区间中的元拷贝给本身。
deque(n,elem):
构造函数将n个elem拷贝给本身.
deque(const deque &deq);
拷贝构造函数
示例:
#include
#include
using namespace std;
//deque构造函数
void printDeque(deque&d)
{
for(deque::iterator it = d.begin();it != d.end(); it++)
{
*it = 100;//会对容器内的值产生影响
cout << *it << " ";
}
cout << endl;
}
//为了防止发生在这个函数中对it进行的修改操作,我们可以对代码进行改进
void printDeque1(const deque&d)
{
for(deque::const_iterator it = d.begin();it != d.end(); it++)
{
cout << *it << " ";
}
cout << endl;
}
void test01()
{
dequed1;
for(int i = 0;i < 10; i++)
{
d1.push_back(i);
}
printDeque1(d1);
//拷贝
dequed2(d1.begin(),d1.end());
printDeque1(d2);
dequed3(10, 100);
printDeque1(d3);
dequed4(d3);
printDeque1(d4);
}
int main()
{
test01();
return 0;
}
总结:deque容器和vector容器的构造方式几乎一致,灵活使用即可。
功能描述:
给deque容器进行赋值
函数原型:
deque&operator=(const deque &deq);
重载等号操作符
assign(beg, end);
将[beg,end)区间中的数据拷贝赋值给本身。
assign(n,elem);
将n个elem拷贝赋值给本身.
示例:
#include
#include
using namespace std;
//deque容器赋值
void printDeque(const deque&d)
{
for(deque::const_iterator it = d.begin();it != d.end(); it++)
{
cout << *it << " ";
}
cout << endl;
}
void test01()
{
dequed1;
for(int i = 0;i < 10; i++)
{
d1.push_front(i);
}
printDeque(d1);
//赋值操作
dequed2;
d2 = d1;
printDeque(d2);
//assign赋值
dequed3;
d3.assign(d1.begin(), d1.end());
printDeque(d3);
dequed4;
d4.assign(10, 100);
printDeque(d4);
}
int main()
{
test01();
return 0;
}
功能描述:
对deque容器的大小进行操作
函数原型:
deque.empty();
判断容器是否为空
deque.size();
返回容器中元素的个数
deque.resize(num);
重新指定容器的长度为num,若容器变长,则以默认值填充新位置。 如果容器变短,则末尾超出容器长度的元素被谢除
deque.resize(num,elem);
重新指定容器的长度为num,若容器变长,则以elem值填充新位置;如果容器变短,则末尼超出容台长度的元素被删除。
#include
#include
using namespace std;
void printDeque(const deque& d)
{
for(deque::const_iterator it = d.begin();it != d.end(); it++)
{
cout << *it << " ";
}
cout << endl;
}
void test01()
{
dequed1;
for(int i = 0;i < 10; i++)
{
d1.push_back(i);
}
printDeque(d1);
if(d1.empty())
{
cout << "d1为空" << endl;
}
else
{
cout << "d1不为空" << endl;
cout << "d1的大小" << d1.size() << endl;
//没有capacity容量的概念,因为deque容器可以无限地进行存放
}
//重新指定大小
d1.resize(15);
printDeque(d1);
d1.resize(17, 1);
printDeque(d1);
d1.resize(3);
printDeque(d1);
}
int main()
{
test01();
return 0;
}
总结:
deque没有容量的概念
判断是否为空——empty
返回元素个数——size
重新指定个数——resize
功能描述:
向deque容器中插入和删除数据
函数原型:
两端插入操作:
push_back(elem);
在容器尾部添加一个数据
push_front(elem);
在容器头部插入一个数据
pop_back();
删除容器最后一个数据
pop_front();
删除容器第一个数据
指定位置操作:
insert(pos,elem);
在pos位置插入一个elem元素的拷贝,返回新数据的位置
insert(pos,n,elem);
在pos位置插入n个elem数据,无返回值
insert(pos,beg,end);
在pos位置插入beg end区问的数据,无返回值
c1ear();
清空容器的所有数据
erase(beg,end);
删除[beg,end)区间的数据,返回下一个数据的位置
erase(pos);
除pos位置的数据,返回下一个数的位置
示例:
#include
#include
using namespace std;
void printDeque(const deque& d)
{
for(deque::const_iterator it = d.begin();it != d.end(); it++)
{
cout << *it << " ";
}
cout << endl;
}
void test01()
{
dequed1;
for(int i = 0;i < 5; i++)
{
//尾插
d1.push_back(i);
}
printDeque(d1);
for(int i = 10;i > 5; i--)
{
//头插
d1.push_front(i);
}
printDeque(d1);
//尾删
d1.pop_back();
printDeque(d1);
//头删
d1.pop_front();
printDeque(d1);
//insert插入
d1.insert(d1.begin(), 100);
printDeque(d1);
d1.insert(d1.end() - 1, 2, 200);
printDeque(d1);
//按照区间进行插入
dequed2;
d2.push_back(1);
d2.push_back(2);
d2.push_back(3);
d2.push_back(4);
d1.insert(d1.begin(), d2.begin(), d2.end());
printDeque(d1);
//删除
deque::iterator it = d1.begin();
it++;//删除了第二个元素
d1.erase(it);
printDeque(d1);
//按照区间的方式删除
d1.erase(d1.begin() + 3, d1.end() - 3);
printDeque(d1);
//清空
d1.clear();
printDeque(d1);
}
int main()
{
test01();
return 0;
}
总结:
插入和删除提供的位置是迭代器!
尾插——push_back
尾删——pop_back
头插——push_fron
头删——pop.front
功能描述:
对deque中的数据的存取操作
函数原型:
at(int idx);
返回索引idx所指的数据
operator[];
返回索引dx所指的数据
front();
返回容器中第一个数据元素
back();
返回容器中最后一个数据元素
#include
#include
using namespace std;
//deque数据存储操作
void test01()
{
dequed;
d.push_back(10);
d.push_back(20);
d.push_back(30);
d.push_back(40);
d.push_back(50);
d.push_front(9);
d.push_front(8);
d.push_front(7);
d.push_front(6);
//通过[]
for(int i = 0;i < d.size(); i++)
{
cout << d[i] << " ";
}
cout << endl;
//通过at的方式进行访问
for(int i = 0;i < d.size(); i++)
{
cout << d.at(i) << " ";
}
cout << endl;
cout << "第一个元素:" << d.front() << endl;
cout << "最后一个元素:" << d.back() << endl;
}
int main()
{
test01();
return 0;
}
总结:
除了用送代器获取deque容器中元素,[]和at也可以
front返回容器第一个元素
back返回容器最后一个元素
功能描述:
利用算法实现对deque容器进行排序
算法:
sort(iterator beg,iterator lend);
对beg和end区间内元素进行排序
#include
#include
#include//标准算法头文件
using namespace std;
void printDeque(const deque& d)
{
for(deque::const_iterator it = d.begin();it != d.end(); it++)
{
cout << *it << " ";
}
cout << endl;
}
//deque容器排序
void test01()
{
dequed;
d.push_back(10);
d.push_back(20);
d.push_back(30);
d.push_front(100);
d.push_front(200);
d.push_front(300);
//300 200 100 10 20 30
printDeque(d);
//排序 默认排序规则 是从小到大 升序
//支持随机访问的迭代器都可以利用sort算法直接对其进行排序
//vector容器也可以利用 sort进行排序
sort(d.begin(), d.end());
cout << "排序后:" << endl;
printDeque(d);
}
int main()
{
test01();
return 0;
}
#include
#include
#include
using namespace std;
void printVector(const vectorv)
{
for(vector::const_iterator it = v.begin();it != v.end(); it++)
{
cout << *it << " ";
}
cout << endl;
}
void test01()
{
vectorv;
v.push_back(1);
v.push_back(6);
v.push_back(7);
v.push_back(3);
v.push_back(5);
v.push_back(2);
v.push_back(4);
v.push_back(8);
printVector(v);
sort(v.begin(), v.end());
cout << "排序后:" << endl;
printVector(v);
}
int main()
{
test01();
return 0;
}
字符串,我们都比较熟悉,这里也给大家展示一下具体的用法。
本质:
string是C++风格的字符串,而string本质上是一个类
string和char *区别:
char* 是一个指针
string是一个类,类内部封装了char * ,管理这个字符串,是一个char*型的容器.
特点:
string类内部封装了很多成员方法
例如:查找find,拷贝copy,删除delete替换replace,插入insert
string管理char*所分配的内存,不用担心复制越界和取值越界等,由类内部进行负责
构造函数原型:
string();
创建一个空的字符串,例如:string str;
string(const char* s);
使用字符串s初始化
string(const string & str);
使用一个string对象初始化另一个string对象
string(int n, char c)
使用n个字符c初始化
示例:
#include
#include
using namespace std;
//string的构造函数
void test01()
{
string s1;//默认构造
const char* str = "hello world";
string s2(str);
cout << "s2 = " << s2 << endl;
string s3(s2);
cout << "s3 = " << s3 << endl;
string s4(10,'a');
cout << "s4 = " << s4 << endl;
}
int main()
{
test01();
return 0;
}
总结:string的多种构造方式没有可比性,灵活便用即可
功能描述:
给string字符串进行赋值
赋值的函数原型: string& operator=(const char*s);
char类型字符串赋值给当前的字符串
string& operator=(const string &s);
把字符串s赋给当前的字符串
string& operator=(char c);
字符赋值给当前的字符串
string& assign(const char s);
把字符串s赋给当前的字符串
string& ass1gm(const char s,int n);
把字符串s的前n个字符赋给当前的字符串
string& assign(const string &s);
把字符串s赋给当前字符串
string& assign(int n,char c);
用n个字符c赋给当前字符串
示例:
#include
#include
using namespace std;
//string赋值操作
/*
`string& operator=(const char*s);`char类型字符串赋值给当前的字符串
`string& operator=(const string &s);`把字符串s赋给当前的字符串
`string& operator=(char c);`字符赋值给当前的字符串
`string& assign(const char s);`把字符串s赋给当前的字符串
`str1ng& ass1gm(const char·s,intn);`把字符串s的前n个字符赋给当前的字符串
`string& assign(const string &s);`把字符串s赋给当前字符串
`string& assign(int n,char c);`用n个字符c给当前字符串
*/
void test01()
{
string str1;
str1 = "hello world";
cout << "str1 = " << str1 << endl;
string str2;
str2 = str1;
cout << "str2 = " << str2 << endl;
string str3;
str3 = 'a';
cout << "str3 = " << str3 << endl;
string str4;
str4.assign("hello C++");
cout << "str4 = " << str4 << endl;
string str5;
str5.assign("hello C++", 5);
cout << "str5 = " << str5 << endl;
string str6;
str6.assign(str5);
cout << "str6 = " << str6 << endl;
string str7;
str7.assign(10, 'w');
cout << "str7 = " << str7 << endl;
}
int main()
{
test01();
return 0;
}
功能描述:
实现在字符串末尾拼接字特串
函数原型: string& operator+=(canst char* str);
重载+=操作符
string& operator+=(const char c);
重戴+=操作符
string& operator+=(const string& str);
重载+=操作符
string& append(const char *s);
把字符串s连接到当前字符串结尾
string& append(const char *s, int n);
把字符串s的前n个字符连接到当前字符串结尾
string& append(const string &s);
同operator+=(const string& str)
string& append(const string &s,int pos,int n);
字符串s中从pos开始的n个字符连接到字符串结尾
示例:
#include
#include
using namespace std;
//string字符串拼接
/*
`string& operator+=(canst char* str);`重载+=操作符
`string& operator+=(const char c);`重戴+=操作符
`string& operator+=(const string& str);`重载+=操作符
`string& append(const char *s);`把字符串s连接到当前字符串结尾
`string& append(const char *s, int n);`把字符串s的前个字符连接到当前字符串结尾
`string& append(const string &s);`同operator+=(const string& str)
`string& append(const string &s,int pos,int n);`字符串s中从pos开始的n个字符连接到字符串结尾
*/
void test01()
{
string str1 = "我";
str1 += "爱玩游戏";
cout << "str1 = " << str1 << endl;
str1 += '!';
cout << "str1 = " << str1 << endl;
string str2 = "LOL DNF";
str1 += str2;
cout << "str1 = " << str1 << endl;
string str3 = "I";
str3.append(" love ");
cout << "str3 = " << str3 << endl;
str3.append("game abcde",4);
cout << "str3 = " << str3 << endl;
str3.append(str2, 3, 4);
cout << "str3 = " << str3 << endl;
}
int main()
{
test01();
return 0;
}
总结:字符串拼接的重载版本很多,初学阶段记住几种即可。
功能描述:
查找:查找指定字符串是否存在
替换:在指定的位置替换字符串
函数原型:
int find(const string& str,int pos = 0)const;
查找str第一次出现位置从D0s开始查找
int find(const char* s,int pos = 0) const;
查找s第一次出现位置从pos开始查找
int find(const char* s, int pos, int n)const;
从pos位置查找s的前n个字符第一次位置
int find(const char c,int pos = 0)const;
查找字符c第一次出现位置
int rfind(const string&str,int pos = npos)const;
查找str最后一次位置从pos开始查找
int rfind(const char* s,int pos = npos)const;
查找s最后一次出现位置从pos开始查找
int rfind(const char* s, int pos, int n)const;
从pos查找s的前n个字符最后一次位置
int rfind(const char c,int pos = 0)const;
查找字符c最后一次出现位置
string& replace(int pos,int n,const string& str);
替换从pos开始n个字符为字符串str
string& replace(int pos,int n,const chan*s);
替换从pos开始的个字符为字符串s
示例:
#include
#include
using namespace std;
//string查找和替换
//查找
void test01()
{
string str1 = "hello world";
//find
int pos = str1.find("ll");//从0开始索引,如果查的没有的话就会返回-1
if(pos == -1)
{
cout << "未查到所需字符串" << endl;
}
else
{
cout << "找到字符串,pos = " << pos << endl;
}
//rfind
pos = str1.rfind("ld");
if(pos == -1)
{
cout << "未查到所需字符串" << endl;
}
else
{
cout << "找到字符串,pos = " << pos << endl;
}
//rfind与find之间的区别
//rfind从右往左查找
//find从左往右查
string str2 = "abcdefjhem";
pos = str2.find("e");
if(pos == -1)
{
cout << "未查到所需字符串" << endl;
}
else
{
cout << "找到字符串,pos = " << pos << endl;
}
pos = str2.rfind("e");
if(pos == -1)
{
cout << "未查到所需字符串" << endl;
}
else
{
cout << "找到字符串,pos = " << pos << endl;
}
}
//替换
void test02()
{
string str1 = "abcdefg";
//从1号位置起 3个位置替换成1111
str1.replace(1,3,"1111");//a1111efg
cout << "str1 = " << str1 <
总结:rfind与find之间的区别,rfind从右往左查找,find从左往右查
功能描述:
字符串之间的比较
比较方式:
字符串比较是按字符的ASCLL码进行对比
= 返回 0 > 返回 1 < 返回 -1
函数原型:
int compare(const string &s)const;
与字符串s比较
int compare(const char* s)const;
与字符串比较
示例:
#include
#include
using namespace std;
//string比较
void test01()
{
string str1 = "xello";
string str2 = "hello";
int flag = str1.compare(str2);
if(flag == 0)
{
cout << "str1 等于 str2" << endl;
}
else if(flag > 0)
{
cout << "str1 大于 str2" << endl;
}
else cout << "str1 小于 str2" << endl;
}
int main()
{
test01();
test02();
return 0;
}
总计:字符串对比主要是用于比较两个字符串是否相等,判断谁大谁小意义不大
string中单个字符存取方式有两种
char& operator[(int n)];
通过[]方式取字符
char& at(int n);
通过at方式获取字符
示例:
#include
#include
using namespace std;
//string字符存取
void test01()
{
string str = "hello";
//cout << "str = " << hello << endl;
//1.通过[]访问单个字符
for(int i = 0;i < str.size(); i++)
{
cout << str[i] << " ";
}
cout << endl;
//2.通过at方式访问单个字符
for(int i = 0;i < str.size(); i++)
{
cout << str.at(i) << " ";
}
cout << endl;
//修改单个字符
str[0] = 'x';
cout << "str = " << endl;//xello
str.at(1) = 'x';
cout << "str = " << endl;//xxllo
}
int main()
{
test01();
return 0;
}
总结:string字符串单个字符存取有两种方式,利用[]或at
功能描述:
对string字符串进行插入和删除字符操作
函数原型:
string& insert(int pos,const char*s);
插入字符串
string& insert(int pos,const string& str);
插入字符串
string&insert(int pos,int n,char c);
在指定位置插入n个字符c
string& erase(int pos,int n = npos);
删除从pos开始的n个字符
示例:
#include
#include
using namespace std;
//插入和删除字符串
void test01()
{
string str = "hello";
//插入
str.insert(1,"1111");
cout << "str = " << str << endl;//h1111ello
string str2 = "wow";
str.insert(1,str2);
cout << "str = " << str << endl;//hwow1111ello
//删除
str.erase(1,3);
cout << "str = " << str << endl;//h1111ello
}
int main()
{
test01();
return 0;
}
总结:插入和删除的起点下标都从0开始
功能描述:
从字符串中获取想要的子串
函数原型:
string substr(int pos = 0,int n = npos)const;
返回由pos开始的n个字符组成的字符串
示例:
#include
#include
using namespace std;
//求子串
void test01()
{
string str = "abcdef";
string subStr = str.substr(1,3);
cout << "subStr = " << subStr << endl;
}
//使用操作
void test02()
{
string email = "[email protected]";
//从邮件地址中 获取 用户名的信息
int pos = email.find("@");
string userName = email.substr(0,pos-1);
cout << "userName = " << userName << endl;
}
int main()
{
test01();
test02();
return 0;
}
总结:灵活的运用求子串功能,可以在实际开发中获取有效的信息。
概念:stack是一种先进后出(First In Last Out,FILO)的数据结构,它只有一个出口。
能中只有顶端的元素才可以被外界使用,因此不允许有遍历行为。
栈不允许有遍历的行为,因为要遍历它的话,必须要把栈顶的元素全部取出才能读取到内部函数。
empty可以判断栈是否为空;
size可以返回栈内的元素个数;
栈中进入数据称为入栈——push 栈中弹出数据称为出栈——pop
功能描述:栈容器常用的时外接口
构造函数 stack
stack采用模板类实现,stack对象的默认构造形式
stack(const stack &stk);
拷贝构造函数
赋值探作:
stack& operator=(const stack &stk);
重载等号操作符
数据存取
push(elem)
向栈顶添加元素
pop();
从栈顶移除第一个元素
top();
返回栈顶元素
大小操作: empty();
判断堆栈是否为空
size();
返回栈的大小
示例
#include
#include
using namespace std;
//栈stack容器
void test01()
{
//特点:复合先进后出数据结构
stacks;
//入栈
s.push(10);
s.push(20);
s.push(30);
s.push(40);
//只要栈不为空,就查看栈顶,并且执行出栈
while(!s.empty())
{
//查看栈顶元素
cout << "栈顶元素为:" << s.top() << endl;
//出栈
s.pop();
}
//全部出栈完了,检验一下
cout << "出完栈的大小:" << s.size() << endl;
}
int main()
{
test01();
return 0;
}
概念:Queue是一种先进先出(First In First Out, FIFO)的数据结构,它有两个出口。
队列Queue符合先进先出,只能从队头和队尾被外界访问,因此不允许有遍历行为。
队列容器允许从一端新增元素,从另一端移除元素
队列中只有队头和队尾才可以被外界便用。因此队列不允许有遍历行为。
队列中进数据称为入队——push 队列中出数据称为出队——pop
功能描述:队列容器常用的时外接口
构造函数:
queue
queue采用模板类实现,queue对象的默认构造形式
queue(const queue &que);
拷贝构造函数
赋值操作:
queue& operator=(const queue &que);
重载等号操作符
数据存取:
push(elem);
往队尾添加元素
pop():
从队头移除第一个元素
back();
返回最后一个元素
front();
返回第一个元素
大小操作:
empty();
判断队列是否为空
size();
返回队列的大小
示例:
#include
#include
#include
using namespace std;
class Person
{
public:
Person(string name, int age)
{
this->m_Name = name;
this->m_Age = age;
}
string m_Name;
int m_Age;
};
//队列 Queue
void test01()
{
//创建队列
queueq;
//准备数据
Person p1("zhangsan",18);
Person p2("Lisi",19);
Person p3("wangwu",20);
Person p4("zhaoliu",21);
Person p5("tangqi",22);
//入队
q.push(p1);
q.push(p2);
q.push(p3);
q.push(p4);
q.push(p5);
cout << "队列大小为:" << q.size() << endl;
//判断只要队列不为空,查看队头和队尾,出队
while(!q.empty())
{
//查看队头
cout << "队头元素————姓名:" << q.front().m_Name << "年龄:" << q.front().m_Age << endl;
//查看队尾
cout << "队尾元素————姓名:" << q.back().m_Name << "年龄:" << q.back().m_Age << endl;
//出队
q.pop();
}
cout << "检测出队后队列大小为:" << q.size() << endl;
}
int main()
{
test01();
return 0;
}
总结:
入队——push
出队——pop
返回队头元素——front
返回队尾元素——back
判断队是否为空——empy
返回队列大小——size
功能:将数据进行范式存储
链表(s)是一种物理存储单元上非连续的存储结构,数据元素的逐辑顷序是通过整表中的指针连接实现的
链表的组成:链表由一系列结点组成
结点的组成:一个是存储数据元素的数据域,另一个是存储下一个结点地址的指针域
STL中的链表是一个双向循环链表
链表的优点:链表很灵活,可以对任意位置进行快速的添加、插入、删除元素;采用的是动态存储分配,不会造成内存浪费和溢出;链表执行插入删除等操作十分方便,修改指针即可,无需移动大量元素。
链表的缺点:容器遍历速度没有数组快;占用时间、速度和空间比数组更长、更慢和更多
由于链表的存储方式并不是连续的内存空间,因此链表引list中的迭代器只支持前移和后移,属于双向迭代器。
总结:STL中List和vector是两个最常被使用的容器,各有优缺点
功能描述:
创建List容器
函数原型:
list
list采用采用模板类实现,对象的默认构造形式;
list(beg,end);
构造函数将[beg,end)区间中的元素拷贝给本身;
list(n,elem);
构造函数将n个elem拷贝给本身;
list(const list &lst);
拷贝构造函数。
示例:
#include
#include
using namespace std;
//list容器构造函数
void printList(const list&L)
{
for(list::const_iterator it = L.begin();it != L.end(); it++)
{
cout << *it << " ";
}
cout << endl;
}
void test01()
{
//创建list容器
listL1;//默认构造
//创建数据
L1.push_back(10);
L1.push_back(20);
L1.push_back(30);
L1.push_back(40);
printList(L1);
//区间方式构造
listL2(L1.begin(), L1.end());
printList(L2);
//拷贝构造
listL3(L2);
printList(L3);
//n个elem
listL4(10, 100);
printList(L4);
}
int main()
{
test01();
return 0;
}
功能描述:
给list容器进行赋值,以及交换list容器
函数原型:
assign(beg, end);
将[beg,end)区间中的数据拷贝赋值给本身。
assign(n,elem);
将n个elem拷贝赋值给本身。
list& operator=(const list &list);
重载等号操作符
swap(lst);
将lst与本身的元素互换.
示例:
#include
#include
using namespace std;
//list容器赋值和交换
void printList(const list& L)
{
for(list::const_iterator it = L.begin();it != L.end(); it++)
{
cout << *it << " ";
}
cout << endl;
}
//赋值
void test01()
{
//创建容器
listL1;
//添加元素
L1.push_back(10);
L1.push_back(20);
L1.push_back(30);
L1.push_back(40);
printList(L1);
//区间赋值
listL2;
L2.assign(L1.begin(), L1.end());
printList(L2);
//elem拷贝
listL3;
L3.assign(10,100);
printList(L3);
//重载等号
listL4;
L4 = L3;
printList(L4);
}
//交换操作
void test02()
{
listL1;
L1.push_back(10);
L1.push_back(20);
L1.push_back(30);
L1.push_back(40);
cout << "交换前L1:" << endl;
printList(L1);
listL2;
L2.push_back(1);
L2.push_back(2);
L2.push_back(3);
cout << "交换前L2:" << endl;
printList(L2);
swap(L1, L2);
cout << "交换前L1:" << endl;
printList(L1);
cout << "交换前L2:" << endl;
printList(L2);
}
int main()
{
test01();
test02();
return 0;
}
功能描述:
对is容器的大小进行操作
函数原型:
size();
返回容器中元素的个数
empty();
判断容器是否为空
resize(num);
重新指定容器的长度为num,若容器变长,则以默认值填充新位置。如果容器变短,则末尾超出容器长度的元素删除。
resize(num,elen);
重新指定容器的长度为num,若容器变长,则以elem值填充新位置,如果容器变短,则末尾超出容器长度的元素被删除。
示例:
#include
#include
using namespace std;
//list大小操作
void printList(const list& L)
{
for(list::const_iterator it = L.begin();it != L.end(); it++)
{
cout << *it << " ";
}
cout << endl;
}
void test01()
{
listL1;
L1.push_back(10);
L1.push_back(20);
L1.push_back(30);
L1.push_back(40);
printList(L1);
//判断是否为空
if(L1.empty())
{
cout << "L1为空!" << endl;
}
else
{
cout << "L1不为空!" << endl;
cout << "L1的元素个数为:" << L1.size() << endl;
}
//重新指定大小
L1.resize(10);//L1.resize(10,1000);
printList(L1);
L1.resize(3);
printList(L1);
}
int main()
{
test01();
return 0;
}
总结:
判断是否为空——empty
返回元素个数——size
重新指定个数——resize
功能描述:
对list容器进行数据的插入和删除
函数原型:
push_back(elem);
/∥在容器尾部加入一个元素
pop_back();
删除容器中最后一个元素
push_front(elem);
在容器开头插入一个元素
pop.front
从容器开头移除第一个元素
insert(pos,elem);
在pos位置插elem元素的拷贝,返回新数据的位置
insert(pos,n,elem)
在pos位置插入n个elem数据,无返回值
insert(pos,beg,end);
在pos位置插入[beg,end)区间的数据,无返回值
clear();
移除容器的所有数据
erase(beg,end);
移除[beg end)区间的数据,返回下一个数据的位置
erase(pos)
删除pos位置的数据,返回下一个数据的位置
remove(elem)
删除容器中所有与elem值匹配的元素
示例:
#include
#include
using namespace std;
void printList(const list& L)
{
for(list::const_iterator it = L.begin();it != L.end(); it++)
{
cout << *it << " ";
}
cout << endl;
}
void test01()
{
listL;
//尾插
L.push_back(10);
L.push_back(20);
L.push_back(30);
L.push_back(40);
//头插
L.push_front(4);
L.push_front(3);
L.push_front(2);
L.push_front(1);
//输出1 2 3 4 10 20 30 40
printList(L);
//删除
L.erase(L.begin());
printList(L);
L.erase(++L.begin());
printList(L);
//移除
L.push_back(1000);
printList(L);
L.remove(1000);
printList(L);
//清空
L.clear();
printList(L);
}
int main()
{
test01();
return 0;
}
总结:
头插——push_back
尾删——pop_back
头插——push_front
头删——pop_front
插入——insert
删除——erase
移除——remove
清空——clear
功能描述:
对list容器中数据进行存取
函数原型: front();
返回第一个元豪。
back();
返回最后一个元素。
示例:
#include
#include
using namespace std;
//list容器 数据存取
void test01()
{
listL;
L.push_back(10);
L.push_back(20);
L.push_back(30);
L.push_back(40);
cout << "第一个元素:" << L.front() << endl;
cout << "最后一个元素:" << L.back() << endl;
}
int main()
{
test01();
return 0;
}
功能描述:
将容器中的元素反转,以及将容器中的数据进行排序
函数原型:
reverse();
反转链表
sort();
链表排序
示例:
#include
#include
#include
using namespace std;
//list容器反转和排序
void printList(const list& L)
{
for(list::const_iterator it = L.begin();it != L.end(); it++)
{
cout << *it << " ";
}
cout << endl;
}
bool myCompare(int v1, int v2)
{
//降序 就让第一个数 > 第二个数
return v1 > v2;
}
void test01()
{
//反转
listL1;
L1.push_back(20);
L1.push_back(10);
L1.push_back(50);
L1.push_back(40);
L1.push_back(30);
cout << "反转前:" << endl;
printList(L1);
//不是一个全局函数,而是一个成员函数
L1.reverse();
cout << "反转后:" << endl;
printList(L1);
//排序
//所以不支持随机访问迭代器的容器,不可以用标准算法
//不支持随机访问迭代器的容器,内部会提供一些对应的算法
//sort(L1.begin(), L1.end());是不允许使用的
L1.sort();//默认排序规则 从小到大 升序
cout << "排序后:" << endl;
printList(L1);
L1.sort(myCompare);
printList(L1);
}
int main()
{
test01();
return 0;
}
案例描述:
将Person自定义数据类型进行排序,Person中属性有姓名、年龄、身高 排序规则:
按照年龄进行升序,如果年龄相同按照身高进行降序,如果身高年龄都一样,那么按照体重降序。
#include
#include
#include
using namespace std;
//list容器 排序案例 对自定义数据类型 做排序
//按照年龄进行升序 如果年龄相同那么就按照身高进行降序
class Person
{
public:
Person(string name, int age, double height, double weight)
{
this->m_Name = name;
this->m_Age = age;
this->m_Height = height;
this->m_Weight = weight;
}
string m_Name;//姓名
int m_Age;//年龄
double m_Height;//身高
double m_Weight;//体重
};
//指定排序规则
bool comparePerson(Person p1, Person p2)
{
//按照年龄 升序
if(p1.m_Age == p2.m_Age && p1.m_Height == p2.m_Height)
{
return p1.m_Weight > p2.m_Weight;
}
else if(p1.m_Age == p2.m_Age)
{
return p1.m_Height > p2.m_Height;
}
else
{
return p1.m_Age < p2.m_Age;
}
}
//测试
void test01()
{
//创建容器
listL;
//准备数据
Person p1("zhangsan", 18, 160, 70);
Person p2("lisi", 19, 162, 80);
Person p3("wangwu", 20, 164, 50);
Person p4("zhaoliu", 19, 162, 60);
Person p5("tangqi", 21, 170, 65);
Person p6("jiangba", 18, 170, 75);
//插入数据
L.push_back(p1);
L.push_back(p2);
L.push_back(p3);
L.push_back(p4);
L.push_back(p5);
L.push_back(p6);
for(list::iterator it = L.begin();it != L.end(); it++)
{
cout << "姓名:" << (*it).m_Name << " " << "年龄:" << " " << it->m_Age << " " << "身高" << it->m_Height << " " << "体重:" << it->m_Weight << endl;
}
//排序
cout << "--------------------------------------" << endl;
cout << "排序后:" << endl;
L.sort(comparePerson);
for(list::iterator it = L.begin();it != L.end(); it++)
{
cout << "姓名:" << (*it).m_Name << " " << "年龄:" << " " << it->m_Age << " " << "身高" << it->m_Height << " " << "体重:" << it->m_Weight << endl;
}
}
int main()
{
test01();
return 0;
}
总结:
对于自定义数据类型,必须要指定排序规则,否则编译器不知道如何进行排序
高级排序只是在排序规则上再进行一次逻辑规则制定,并不复杂
简介:
所有元素都会在插入时自动被排序
本质:
set / multiset属于关联式容器,底层结构是用二叉树实现。
set和multiset区别:
set不允许容器中有重复的元素
multiset允许容器中有重复的元素
头文件都是#include
功能描述:创理set容器以及赋值
构造:
set
默认构造函数;
set(const set &st);
作拷贝构造函数
赋值:
set&operator=(const set &st);
重载等号操作符
示例:
#include
#include
using namespace std;
//set容器构造和赋值
void printSet(set&s)
{
for(set::iterator it = s.begin();it != s.end(); it++)
{
cout << *it << " ";
}
cout << endl;
}
void test01()
{
sets1;
//插入数据 只有insert方式
s1.insert(10);
s1.insert(40);
s1.insert(20);
s1.insert(40);
s1.insert(30);
s1.insert(50);
s1.insert(30);
//遍历容器
//set容器的特点 所有元素插入的时候会自动被排序
//set容器不允许插入重复值
printSet(s1);
//拷贝构造
sets2;
printSet(s2);
//赋值
sets3;
s3 = s2;
printSet(s3);
}
int main()
{
test01();
return 0;
}
功能描述:
统计set容器大小以及交换set容器
函数原型:
size();
返回容器中元素的数目
empty();
判断容器是否为空
swap(st);
交换两个集合容器
示例:
#include
#include
using namespace std;
//set容器 大小和交换
//遍历
void printSet(set& s)
{
for(set::iterator it = s.begin();it != s.end(); it++)
{
cout << *it << " ";
}
cout << endl;
}
//大小
void test01()
{
sets1;
//插入数据
s1.insert(10);
s1.insert(20);
s1.insert(30);
s1.insert(40);
s1.insert(50);
printSet(s1);
//判断是否为空
if(s1.empty())
{
cout << "s1为空" << endl;
}
else
{
cout << "s1不为空" << endl;
cout << "s1的大小为:" << s1.size() << endl;
}
}
//交换
void test02()
{
sets1;
//插入数据
s1.insert(10);
s1.insert(20);
s1.insert(30);
s1.insert(40);
s1.insert(50);
sets2;
//插入数据
s2.insert(100);
s2.insert(200);
s2.insert(300);
s2.insert(400);
s2.insert(500);
cout << "交换前:" << endl;
printSet(s1);
printSet(s2);
cout << "交换后:" << endl;
s1.swap(s2);
printSet(s1);
printSet(s2);
}
int main()
{
test01();
test02();
return 0;
}
功能描述:
set容器进行搭入数据和除数据
函数原型:
insert(elem);
在容器中插入元素
clear();
清除所有元素
erase(pos);
删除pos迭代器所指的元素,返回下一个元素的迭代器
erase(beg, end);
删除区间[beg,end)的所有元素,返回下一个元素的迭代器
erase(elem);
删除容器中值为elem的元素。
示例:
#include
#include
using namespace std;
//set容器 插入和删除
void printSet(sets)
{
for(set::iterator it = s.begin();it != s.end(); it++)
{
cout << *it << " ";
}
cout << endl;
}
void test01()
{
sets;
//插入
s.insert(10);
s.insert(20);
s.insert(30);
s.insert(40);
printSet(s);
s.erase(s.begin());
printSet(s);
s.erase(++s.begin());
printSet(s);
s.erase(40);
printSet(s);
s.clear();
printSet(s);
}
int main()
{
test01();
return 0;
}
功能描述:
对set容器进行直找数据以及统计数据
函数原型:
find(key):
查找key是否存在,若存在,返回该键的元素的迭代器:若不存在,返回set.end()
count(key)
统计key的元素个数
示例:
#include
#include
using namespace std;
//查找和统计
void test01()
{
sets;
s.insert(10);
s.insert(20);
s.insert(30);
s.insert(30);
s.insert(30);
s.insert(30);
s.insert(40);
//查找
//查找
//set::iterator pos = s1.find(30);
cout << *s.find(30) << endl;
cout << *s.find(40) << endl;
//统计
cout << "值30的个数:" << s.count(30) << endl;
cout << "值50的个数:" << s.count(50) << endl;
}
int main()
{
test01();
return 0;
}
学习目标:
掌握set和multiset的区别
区别:
set不可以插入重复数据,而multiset可以
set插入数据的同时会返回插入结果,表示插入是否成功
multiset不会检测数据,因此可以插入重复数据
示例:
#include
#include
using namespace std;
//set容器 和 multiset容器的区别
void printSet(multisets)
{
for(multiset::iterator it = s.begin();it != s.end(); it++)
{
cout << *it << " ";
}
cout << endl;
}
void test01()
{
multisets;
s.insert(10);
s.insert(20);
s.insert(30);
s.insert(30);
s.insert(40);
s.insert(10);
printSet(s);
}
int main()
{
test01();
return 0;
}
造成两者不同的结果的原因是,在源码部分存在有_Pairib
_Pairib:所以在insert()过后,如果插入成功,_Pairib的iterator会指向元素插入的位置,bool被置为true;否则,iterator指向重复的元素的位置,且bool为false.所以,“[]”重载函数可以通过insert()间接实现的。但在MS STL中,它没有采用这种方法,其内部虽也通过insert()间接实现,但其采用以map
详细解法利用对组:
#include
#include
using namespace std;
void test()
{
sets;
//对组
pair::iterator, bool> ret = s.insert(10);
if(ret.second)
{
cout << "第一次插入成功!" << endl;
}
else
{
cout << "第一次插入失败!" << endl;
}
ret = s.insert(10);
if(ret.second)
{
cout << "第二次插入成功!" << endl;
}
else
{
cout << "第二次插入失败!" << endl;
}
}
int main()
{
test();
return 0;
}
总结:
如果不允许插入重复数据可以利用set
如果需要插入重复改据利用multiset
功能描述:
成对出现的数据,利用对组可以返回两个数据
两种创建方式:
pair
pair
示例:
#include
#include
using namespace std;
//对组的建立
void test01()
{
//第一种方式
pairp("Tom",12);
cout << "姓名:" << p.first << " " << "年龄:" << p.second << endl;
//第二种方式
pairp2 = make_pair("Jerry",10);
cout << "姓名:" << p2.first << " " << "年龄:" << p2.second << endl;
}
int main()
{
test01();
return 0;
}
学习目标:
set容器默认排序规则为从小到大,掌握如何改变排序规则
主要技术点:
利用仿函数,可以改变排序规则
#include
#include
using namespace std;
//set容器排序
//仿函数改变排序规则
class MyCompare
{
public:
bool operator()(int v1,int v2)
{
return v1 > v2;
}
};
void test01()
{
sets1;
s1.insert(10);
s1.insert(20);
s1.insert(30);
s1.insert(40);
s1.insert(50);
for(set::iterator it = v.begin();it != v.end(); it++)
{
cout << *it << " ";
}
cout << endl;
//指定排序规则从大到小
sets2;
s2.insert(40);
s2.insert(20);
s2.insert(30);
s2.insert(10);
s2.insert(50);
for(set::iterator it = v.begin();it != v.end(); it++)
{
cout << *it << " ";
}
cout << endl;
}
int main()
{
test01();
system("pause");
return 0;
}
总结:利用仿函数可以指定set容器
#include
#include
#include
using namespace std;
//set容器排序 存放自定义数据类型
class Person
{
public:
Person(string name, int age)
{
this->m_Name = name;
this->m_Age = age;
}
string m_Name;
int m_Age;
};
class comparePerson
{
public:
bool operator()(const Person&p1, const Person&p2)
{
//按照年龄 降序
return p1.m_Age > p2.m_Age;
}
};
void test01()
{
sets;
//创建Person对象
Person p1("zhangsan",18);
Person p2("lisi",19);
Person p3("wangwu",20);
Person p4("zhaoliu",21);
s.insert(p1);
s.insert(p2);
s.insert(p3);
s.insert(p4);
//排序
for(set::iterator it = s.begin();it != s.end(); it++)
{
cout << "姓名:" << it->m_Name << " " << "年龄:" << it->m_Age << endl;
}
cout << endl;
}
int main()
{
test01();
return 0;
}
简介:
map中所有元素都是pair
pair中第一个元素为key(键值),起到索引作用,第二个元素为value(实值)
所有元素都会根据元素的键值自动排序
本质:
map/multimap属于关联式容器。底层结构是用二叉树实现.
优点:
可以根据key值快速找到value值
map和multimapl区别:
map不允许容器中有重复key值元素
multimap允许容器中有重复key值元素
功能描述:
对map容器进行构造和赋值操作
函数原型:
构造: map
map默认构造函数:
map(const map &mp);
拷贝构造函数
赋值:
map&operator=(const map &mp);
重载等号操作符
示例:
#include
#include
功能描述:
统计map客品大小以及交换map容器
函数原型:
size();
返回容器中元素的数目
empty();
条件判新容器是否为空
swap(st);
交换两个集合容器
#include
#include
功能描述:
map容进行插入数据和别除数据
函数原型:
insert(elem);
在容器中插入元素。
clear();
清除所有元素
erase(pos);
删除pos迭代器所指的元素,返回下一个元素的迭代器
erase(beg, end);
删除区间[beg.end的所有元素,返回下一个元素的迭代器
erase(key);
删除容器中值为key的元素
示例:
#include
#include
功能描述:
对map容器进行查找数据以及统计数据
函数原型:
find(key);
查找key是否存在,若存在,返回该键的元素的迭代器:若不存在,返回set.end();
count(key);
统计key的元素个数
示例:
#include
#include
学习目标
map容器默认排序规则为按照key值进行从小到大排序,掌握如何改变排序规则
主要技术点:
利用仿函数,可以改变排序规则
示例:
#include
#include
有5名选手:选手ABCDE,10个评委分别对每一名选手打分,去除最高分,去除评委中最低分,取平均分。
创建五名选手,放到vector中
遍历vector容器,取出来每一个选手,执行for循环,可以把10个评分打分存到deque容器中
sort算法对deques容器中分数排序,去除最高和最低分
deque容器遍历一遍,累加总分
获取平均分
#include
#include
#include
#include
#include
using namespace std;
//评委打分案例
/*
有5名选手:选手ABCDE,10个评委分别对每一名选手打分,去除最高分,去除评委中最低分,取平均分。
*/
class Person
{
public:
Person(string name, double score)
{
this->m_Name = name;
this->m_Score = score;
}
string m_Name;//姓名
double m_Score;//平均分
};
void createPerson(vector&v)
{
string nameSeed = "ABCDE";
for(int i = 0;i < 5; i++)
{
string name = "选手";
name += nameSeed[i];
double score = 0;
Person p(name, score);
//将创建的person对象 放入到容器中
v.push_back(p);
}
}
//打分
void serSore(vector&v)
{
for(vector::iterator it = v.begin();it != v.end(); it++)
{
//将评委的分数 放入deque容器中
dequed;
for(int i = 0;i < 10; i++)
{
double score = rand() % 41 + 60;//60 ~ 100
d.push_back(score);
}
cout << "选手:" << it->m_Name << " " << "打分:" << endl;
for(deque::iterator dit = d.begin();dit != d.end(); dit++)
{
cout << *dit << " ";
}
cout << endl;
//排序
sort(d.begin(), d.end());
//去掉最高分和最低分
d.pop_back();
d.pop_front();
//取平均分
double sum = 0;
for(deque::iterator dit = d.begin();dit != d.end(); dit++)
{
sum += *dit;//累加每个评委的分数
}
double avg = sum / d.size();
//将平均分 赋值给选手
it->m_Score = avg;
}
}
//打印结果
void showScore(vector&v)
{
for(vector::iterator it = v.begin();it != v.end(); it++)
{
cout << "姓名:" << it->m_Name << " " << "平均分:" << it->m_Score << endl;
}
}
int main()
{
//创建5名选手
vectorv;//存放选手容器
createPerson(v);
//测试
//for(vector::iterator it = v.begin();it != v.end(); it++)
//{
//cout << (*it).m_Name << " " << (*it).m_Score << endl;
//}
//给5名选手打分
serSore(v);
cout << endl;
//显示最后得分
showScore(v);
return 0;
}
今天的分享到这里就结束啦,STL标准库还是得靠练习才能巩固、掌握和灵活使用。种类很多,但是具体的调用方法则是大同小异,很多情况下就是属于掌握了一个,就能推出其他的使用情况,区别的地方记牢、会用即可!!!
兄弟萌,加油啊!!!!!