目录
6. 应用: 输入一个字符串,用map统计每个字符出现的次数并输出字符及对应的次数
1. STL的基础知识
1.1 STL的基本概念
STL(标准模板库),广义上分为容器、算法和迭代器。容器和算法之间通过迭代器进行无缝连接。
SLT几乎所有代码都采用了模板类或者模板函数。
1.2 STL六大组件
STL六大组件:容器、算法、迭代器、仿函数、适配器(配接器)、空间配置器。
1、容器:各种数据结构,如vector、list、deque、set、map等,用来存放数据。
2、算法:各种常用的算法,如sort、find、copy、for_each等。
3、迭代器:扮演了容器和算法之间的胶合剂。其是由容器设计者实现的接口,用来遍历自己容器内部的元素,从而使得不同的容器对外表现相似。
4、仿函数:行为类似于函数,可作为算法的某种策略。
5、适配器:一种用来修饰容器或者仿函数或迭代器接口的东西。
6、空间配置器:负责空间的配置与管理。
容器:分为序列式容器和关联式容器两种。序列式容器:强调值的排序,序列式容器中每个元素均有固定的位置。关联式容器:二叉树结构,各元素之间没有严格的物理上的顺序关系。
容器类型 | 特点 |
---|---|
vector | 可从后端直接访问元素、实现快速插入和删除 |
deque | 可从前端或后端直接访问元素,实现快速插入和删除 |
list | 可从在任何地方实现快速插入和删除,但随机访问速度较慢 |
set | 快速查找,不允许重复值 |
multiset | 快速查找,允许重复值 |
map | 一对多映射,基于关键字快速查找,不允许重复值 |
multimap | 一对多映射,基于关键字快速查找,允许重复值 |
stack | 后进先出 |
queue | 先进先出 |
priority_queue | 最高优先级元素总是第一个出列 |
算法:有限的步骤,解决逻辑或数学上的问题。算法分为质变算法和非质变算法。质变算法:指运算过程中会更改区间内的元素的内容,例如拷贝、替换、删除等等。非质变算法:指运算过程中不会更改区间内的元素的内容,例如查找、遍历等等。
迭代器:提供一种方法,使之能够依序寻访某个容器所含的各个元素,而又无需暴露该容器的内部表示方式。每个容器都有自己专属的迭代器。
迭代器的分类:
输入迭代器:可用来从序列中读取数据,如输入流迭代器。
输出迭代器:可用来向序列中写入数据,如输出流迭代器。
前向迭代器:既是输入迭代器又是输出迭代器,并且可以对序列进行单向的遍历。
双向迭代器:与前向迭代器相似,既是输入迭代器又是输出迭代器,但是其可在两个方向上对数据进行遍历。
随机访问迭代器:也是双向迭代器,功能和双向迭代器相似,但能够在序列中的任意两个位置之间进行跳转,如指针、使用vector的begin()、end()函数得到的迭代器。
迭代器常用辅助函数:
advance(p,n):对p进行n次自增操作。
distance(first,last):可计算出两个迭代器之间的距离。
2. vector
容器:vector
算法:for_each
迭代器:vector<int>::iterator
2.1 vector存放自定义数据类型
//vector容器中存放自定义数据类型
class Person
{
public:
Person(string name,int age)
{
this->m_name=name;
this->m_age=age;
}
string m_name; //姓名
int m_age; //年龄
}
void test1()
{
vector<Person>v;
Person p1("Tony",19);
Person p2("Tom",29);
Person p3("Timi",39);
Person p4("Jerry",49);
//向容器中添加数据
v.push_back(p1);
v.push_back(p2);
v.push_back(p3);
v.push_back(p4);
//遍历容器中的数据
for(vector<Person>::iterator it=v.begin();it!=v.end();it++)
{
cout<<"name:"<<(*it).m_name<<endl; //方式一
cout<<"age:"<<it->m_age<<endl; //方式二
}
}
//存放自定义数据类型----指针
void test2()
{
vector<Person*>v;
Person p1("Tony",19);//此处为其地址
Person p2("Tom",29);
Person p3("Timi",39);
Person p4("Jerry",49);
//向容器中添加数据
v.push_back(&p1); //尾插法
v.push_back(&p2);
v.push_back(&p3);
v.push_back(&p4);
//遍历容器
for(vector<Person*>::iterator it=v.begin();it<v.end();it++)
{
cout<<"name:"<<(*it)->m_name<<endl;
cout<<"age:"<<(*it)->m_age<<endl;
}
}
2.2 vector容器嵌套容器
相当于数字里嵌套数组,即二维数组。
//容器嵌套容器
void test1()
{
vector<vector<int>>v;
//创建内部小容器
vector<int>v1;
vector<int>v2;
vector<int>v3;
vector<int>v4;
//向小容器中添加数据
for(int i=0;i<4;i++)
{
v1.push_back(i+1);
v2.push_back(i+2);
v3.push_back(i+3);
v4.push_back(i+4);
}
//将小容器中的数据插入到大的容器中
v.push_back(v1);
v.push_back(v2);
v.push_back(v3);
v.push_back(v4);
//通过大容器把所有的数据都遍历一遍
for(vector<vector<int>>::iterator it=v.begin();it!=v.end();it++)
{
//(*it)为vector<int>,故需再遍历
for(vector<int>::iterator vit=(*it).begin();vit!=vit.end();vit++)
{
cout<<(*vit)<<" "
}
cout<<endl;
}
}
3. string容器
3.1 string的基本概念
本质:string是C++风格的字符串,而string本质上是一个类。
string和char*的区别:
1. char*是一个指针
2.string是一个类,类内部封装了char*来管理这个字符串,即是一个char*容器。
string类内封装了很多成员方法,例如:查找find,拷贝copy,删除delete,替换replace,插入insert。
string管理char*所分配的内存,不用担心复制越界和取值越界等,由类内部经行负责。
3.2 string构造函数
构造函数原型:
1. string(); //创建一个空的字符串
string(const char* s); //使用字符串s初始化
2. string(const string& str); //使用一个string对象初始化另一个string对象。
3. string(int n, char c); //使用n个字符c初始化
3.3 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& assign(const char *s, int n); //把字符串s的前n个字符赋给当前的字符串
- string& assign(const string &s); //把字符串s赋给当前字符串
- string& assign(int n, char c); //用n个字符c赋给当前字符串
3.4 string字符串的拼接
函数原理:
- string& operator+=(const 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个字符连接到字符串结尾
//string字符串
void test1()
{
//string& operator+=(const char* str); //重载+=操作符
string str1 = "吃饭";
str1 += "了吗";
cout << "str1=" << str1 << endl;
//string& operator+=(const char c); //重载+=操作符
str1 += "?";
cout << "str1=" << str1 << endl;
//string& append(const char *s); //把字符串s连接到当前字符串结尾
string str2 = "没吃一起去西苑吃呀!";
str1 += str2;
cout << "str1=" << str1 << endl;
//string& append(const char *s); //把字符串s连接到当前字符串结尾
string str3 = "I'm so ";
str3.append("happy!");
cout << "str3=" << str3 << endl;
//string& append(const char*s, int n); //把字符串s的前n个字符连接到当前字符串结尾
str3.append("today what about you", 5);
cout << "str3=" << str3 << endl;
//string& append(const string &s); //同operator+=(const string& str)
str3.append("hhhhh");
cout << "str3=" << str3 << endl;
//string& append(const string &s, int pos, int n); //字符串s中从pos开始的n个字符连接到字符串结尾*/
str3.append("the weather is great", 4, 7);
cout << "str3=" << str3 << endl;
}
3.5 string查找和替换
查找:查找指定字符串是否存在。
替换:在指定位置替换字符串。
函数原理;
int find(const string& str,int pos = 0) const; //查找str第一次出现的位置,从pos开始查找
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第一次出现的位置
4. 应用:结合容器和迭代器实现序列变换及像素变换
4.1 结合容器和迭代器实现序列变换
4.2 结合容器和迭代器实现像素变换
5. 应用:用set存储学生信息,并进行增删改查操作
5.1 构造学生类Student
// 学生类
class Student{
public:
string m_num; //学号
string m_Name; //姓名
Student(string num, string Name){ //构造函数
m_num = num;
m_Name = Name;
}
// <<运算符重载
friend ostream& operator<<(ostream& os, const Student& info){
os << info.m_num << info.m_Name;
return os;
}
// 比较运算符重载
friend bool operator<(const Student& info1, const Student& info2){
return info1.m_num<info2.m_num;
}
};
5.2 使用set容器存储学生信息
// 存储学生信息
void saveStudent(){
vector<Student> s;
//创建vector容器来存储刚输入时按照输入顺序存储的学生信息
s.push_back(Student("1", "Tony")); //添加学生信息
s.push_back(Student("20", "YangHaoming"));
s.push_back(Student("4", "SunYihang"));
s.push_back(Student("7", "DuanXingxing"));
s.push_back(Student("15", "LiangSeng"));
// 创建set容器来存储学生信息可去掉重复的信息且使其有序
set<Student> StudentSet(s.begin(), s.end());
}
5.3 对存储的学生信息进行增删改查
5.3.1 向容器添加学生信息
StudentSet.insert(Student("32","WeiHongyu")); //添加
5.3.2 删除容器内的学生信息
StudentSet.erase(Student("7","DuanXingxing")); //删除
5.3.3 修改容器内的学生信息
//修改学生姓名
bool updateName(set<Student>& StudentSet, string OldName, string NewName){
string newName; //用于保存,需要修改姓名的学生的学号
bool result = false; //返回是修改成功
for(auto it = StudentSet.begin(); it != StudentSet.end(); it++){
if((*it).m_Name == OldName)
{
num = (*it).m_num; //保存原来学号
StudentSet.erase(*it); //先删除旧的学生信息
StudentSet.insert(Student(num,NewName));//重新添加新的学生信息
result = true;
break;
}
}
return result;
}
5.3.4 查找容器中是否有某学生信息
// 查找学生信息
if(StudentSet.find(Student("1", "Tony")) != StudentSet.end())
{
cout << "Find The Student! "<< endl;
}
else
{
cout << "Not Find The Student! "<< endl;
}
6. 应用: 输入一个字符串,用map统计每个字符出现的次数并输出字符及对应的次数
7. 总结
实验总结: