C++的面向对象和泛型编程思想,目的就是提高代码的复用性,为建立数据结构和算法的一套标准,诞生了STL。
STL(Standard Template Library)标准模板库。
STL六大组件:容器、算法、迭代器、仿函数、适配器(配接器)、空间配置器。
容器:存放数据。
常用的数据结构:数组、链表、树、栈、队列、集合等。
这些容器又可分为序列式容器
和关联式容器
两种:
序列式容器:强调值的排序,序列式容器中的每个元素均有固定的位置。
关联式容器:二叉树结构,各元素之间没有严格的物理上的顺序关系。
算法:分为质变算法
和非质变算法
。有限的步骤,解决逻辑或数学上的问题,这一门学科称之为算法。
质变算法:运算过程中会改变区间内元素的值,如拷贝、替换、删除。
非质变算法:运算过程中不会改变区间内的元素内容,例如查找、计数、遍历、寻找极值。
迭代器:提高一种方法,使之能够依次寻访某个容器所含的各个元素,而又无需暴漏该容器的内部表示方式。
每个容器都有自己专属的迭代器,迭代器的使用非常类似于指针。
迭代器种类:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-o546zOzF-1685616730341)(images/4.png)]
常用的容器中迭代器种类为双向迭代器,和随机访问迭代器。
STL中最常用的容器为Vector
,可以理解为数组。
STL中每个容器在使用前都需要包含头文件。
vector
存放内置数据类型:
#include
#include
#include // STL标准算法头文件,使用for_each时需要
using namespace std;
void myPrint(int val)
{
cout << val << endl;
}
void test()
{
vector<int> v; // 创建一个容器
// 向容器中插入数据(尾插)
v.push_back(1);
v.push_back(2);
v.push_back(3);
// 通过迭代器访问容器中的数据
// vector::iterator itBegin = v.begin(); // 起始迭代器,指向容器中第一个元素的位置
// vector::iterator itEnd = v.end(); // 结束迭代器,指向容器中最后一个元素的下一个位置
// // 遍历方式1
// while (itBegin != itEnd)
// {
// cout << *itBegin << endl;
// itBegin++;
// }
// 遍历方式2:更常用
for (vector<int>::iterator it = v.begin(); it != v.end(); it++)
{
cout << *it << endl;
}
// 遍历方式3:利用STL提供的遍历算法
// for_each(v.begin(), v.end(), myPrint); // 需要定义一个打印输出的函数,传入函数名
}
int main()
{
test();
return 0;
}
#include
#include
#include
using namespace std;
// vector容器中存放自定义数据类型
class Person
{
public:
string m_name;
int m_age;
Person(string name, int age)
{
this->m_name = name;
this->m_age = age;
}
};
void test1()
{
vector<Person> v; // 创建一个存放自定义数据类型class的容器
Person p1("张三", 1);
Person p2("李四", 2);
// 向容器中添加数据
v.push_back(p1);
v.push_back(p2);
// 遍历容器中的数据
for (vector<Person>::iterator it = v.begin(); it != v.end(); it++)
{
// (*it)的数据类型为Person
cout << "name:" << (*it).m_name << ",age:" << (*it).m_age << endl;
}
}
// 存放自定义数据类型:指针
void test2()
{
vector<Person *> v;
Person p1("张三", 1);
Person p2("李四", 2);
v.push_back(&p1);
v.push_back(&p2);
// 遍历容器
for (vector<Person *>::iterator it = v.begin(); it != v.end(); it++)
{
cout << "name:" << (*it)->m_name << endl;
}
}
int main()
{
test1();
test2();
return 0;
}
学习目标:容器中嵌套容器,将所有数据进行遍历输出。
容器嵌套相当于一个二维数组。
#include
#include
using namespace std;
// 容器嵌套输出
void test1()
{
vector<vector<int>> v;
// 创建小容器
vector<int> v1;
vector<int> v2;
vector<int> v3;
// 向小容器中添加数据
for (int i = 0; i < 3; i++)
{
v1.push_back(i + 1);
v2.push_back(i + 2);
v3.push_back(i + 3);
}
// 将小容器插入到大容器中
v.push_back(v1);
v.push_back(v2);
v.push_back(v3);
// 通过大容器,把所有数据遍历一遍,与二维数组的遍历方式一样
for (vector<vector<int>>::iterator it = v.begin(); it != v.end(); it++)
{
// (*it) = vector; 技巧:(*it)等于尖括号里的内容
// 遍历小容器
for (vector<int>::iterator vit = (*it).begin(); vit != (*it).end(); vit++)
{
cout << *vit << " "; // 输出小容器中的数据
}
cout << endl;
}
}
int main()
{
test1();
return 0;
}
char *
的区别:char *
是一个指针string
是一个类,类内部封装了char *
,是一个char *
容器find
查找,delete
删除、replace
删除、insert
插入char *
所分配的内存,不用担心复制越界和取值越界的问题,由类内部进行负责。构造函数原型:
string();
创建一个空的字符串,例如string str1;
string(const char *s);
使用字符串s初始化string(const string& str);
使用一个string对象初始化另一个string对象string(int n, char c)
使用n个字符c初始化#include
#include
using namespace std;
void test1()
{
string s1; // 默认构造
const char *str = "hello,world";
string s2(str);
cout << s2 << endl; // 输出hello,world
}
int main()
{
test1();
return 0;
}
#include
#include
using namespace std;
void test1()
{
string str1 = "hello,world";
string str2;
str2.assign("hello,c++"); // 使用string类的成员函数进行赋值
string str3;
str3.assign("hello,c++", 5); // 把字符串中的前5个字符赋值给str3
cout << str3 << endl; // 输出hello
string str4;
str4.assign(str3); // 拷贝赋值,利用另外一个字符串,给str3赋值
string str5;
str5.assign(10, 'w'); // 输出10个w
cout << str5 << endl;
}
int main()
{
test1();
return 0;
}
功能描述:实现在字符串末尾拼接字符串
#include
#include
using namespace std;
void test1()
{
string str1 = "hello";
str1 += ",world"; // 追加一个字符串
str1 += '.'; // 追加一个字符
cout << str1 << endl;
string str2 = "test";
str2 += str1;
cout << str2 << endl;
// 追加方式2:采用string类的成员函数
string str3 = "test2";
str3.append(" ,"); // 追加字符串或字符
str3.append("hello,world", 4); // 追加字符串hello,world的前4个字符
cout << str3 << endl;
// 参数2:从哪个位置开始截取,参数3:截取字符个数
str3.append(str2, 0, 3); // 从字符串str2的第0个位置(起始位置)截取3个字符,追加到str3
cout << str3 << endl;
}
int main()
{
test1();
return 0;
}
功能描述:
find()
和rfind()
find
查找是从左往右,rfind
是从右往左find
找到字符串后返回查找到的第一个字符位置(起始位置为0),找不到返回-1
replace
在替换时,要指定从那个位置起,多少个连续的字符,替换为str#include
#include
using namespace std;
// 字符串查找
void test1()
{
string str1 = "abcdef";
int pos = str1.find("de"); // 默认从0号位置查找 字符串第一次出现的位置
if (pos == -1)
{
cout << "未找到字符串" << endl;
}
cout << pos << endl; // 输出结果:3(起始位置为0)。如果没有找到,输出:-1
// rfind 和 find的区别
// rfind 从右往左开始查找。find从左往右开始查找
pos = str1.rfind("a");
cout << pos << endl; // 输出结果0
}
int main()
{
test1();
return 0;
}
示例2:字符串替换replace()
#include
#include
using namespace std;
// 字符串查找
void test1()
{
string str1 = "abcdef";
// 参数1:起始位置,参数2:从pos起始位置开始把连续的3个字符,替换为字符串str
str1.replace(1, 3, "1");
cout << str1 << endl; // 输出结果:a1ef 。把bcd这三个字符,替换成了字符串str
}
int main()
{
test1();
return 0;
}
=
,输出0>
,输出1<
,输出-1#include
#include
using namespace std;
void test1()
{
string str1 = "bcd";
string str2 = "abcde";
int result = str1.compare(str2);
cout << result << endl; // 输出1
}
int main()
{
test1();
return 0;
}
功能描述:存取单个字符
#include
#include
using namespace std;
void test1()
{
string str1 = "abcd";
cout << str1.size() << endl; // 输出4,不包括字符串的结束符
// 访问方式1:通过[]访问单个字符
for (int i = 0; i < str1.size(); i++)
{
cout << str1[i] << " ";
}
cout << endl;
// 访问方式2:通过at访问
for (int i = 0; i < str1.size(); i++)
{
cout << str1.at(i) << " ";
}
cout << endl;
// 修改单个字符
str1[0] = 'x'; // str1.at(0) = 'x';
cout << str1 << endl;
}
int main()
{
test1();
return 0;
}
insert()
插入字符串erase()
删除从pos开始的m个字符#include
#include
using namespace std;
void test1()
{
// 插入
string str1 = "abcd";
str1.insert(1, "123"); // 在第一个字符之后,插入字符串
cout << str1 << endl; // 输出:a123bcd
// 删除
str1.erase(1, 3); // 从第一个位置开始,删除3个字符
cout << str1 << endl; // 输出:abcd
}
int main()
{
test1();
return 0;
}
总结:插入和删除的起始下标都是从0开始。
#include
#include
using namespace std;
void test1()
{
string str1 = "abcdefg";
string subStr = str1.substr(1, 3); // 从1号位置,截取3个连续的字符
cout << subStr << endl; // 输出:bcd
}
// 实用操作
void test2()
{
string email = "[email protected]";
// 从邮件地址中获取用户信息
int pos = email.find("@");
cout << pos << endl;
string username = email.substr(0, pos); // 输出:hello
cout << username << endl;
}
int main()
{
test1();
test2();
return 0;
}
vector
数据结构和数组非常相似,也称为单端数据vector
与普通数组区别:数组是静态空间,而vector
可以动态扩展。
vector
容器的迭代器是支持随机访问的迭代器功能描述:创建vector容器。
#include
#include
using namespace std;
// 打印输出容器中的内容
void printVector(vector<int> &v)
{
for (vector<int>::iterator it = v.begin(); it != v.end(); it++)
{
cout << *it << " ";
}
cout << endl;
}
void test1()
{
vector<int> v1; // 默认构造,无参构造
for (int i = 0; i < 10; i++)
{
v1.push_back(i);
}
printVector(v1);
// 通过区间方式进行构造
vector<int> v2(v1.begin(), v1.end());
printVector(v2);
// n个元素方式构造
// 参数1:个数,参数2:值
vector<int> v3(10, 100); // 容器中有10个元素,初始值为100
printVector(v3);
// 拷贝构造
vector<int> v4(v3);
printVector(v4);
}
int main()
{
test1();
return 0;
}
#include
#include
using namespace std;
// 打印输出容器中的内容
void printVector(vector<int> &v)
{
for (vector<int>::iterator it = v.begin(); it != v.end(); it++)
{
cout << *it << " ";
}
cout << endl;
}
void test1()
{
vector<int> v1;
for (int i = 0; i < 10; i++)
{
v1.push_back(i);
}
printVector(v1);
// 赋值方式1
vector<int> v2;
v2 = v1;
printVector(v2);
// 赋值方式2
vector<int> v3;
v3.assign(v1.begin(), v1.end());
printVector(v3);
// 赋值方式3
vector<int> v4;
v4.assign(10, 100);
printVector(v4);
}
int main()
{
test1();
return 0;
}
empty()
判断容器是否为空capacity()
容器的容量size()
返回容器中元素的个数resize(int num)
重新指定容器的长度resize(int num,elem)
重新指定容器的长度,并以elem值填充新位置#include
#include
using namespace std;
// 打印输出容器中的内容
void printVector(vector<int> &v)
{
for (vector<int>::iterator it = v.begin(); it != v.end(); it++)
{
cout << *it << " ";
}
cout << endl;
}
void test1()
{
vector<int> v1;
for (int i = 0; i < 10; i++)
{
v1.push_back(i);
}
printVector(v1);
if (v1.empty())
{
cout << "v1为空" << endl;
}
cout << "v1的容量:" << v1.capacity() << endl; // 16,容量永远大于等于size()
cout << "v1的尺寸:" << v1.size() << endl; // 10
// 重新指定大小
v1.resize(15);
printVector(v1); // 默认用0填充新位置
v1.resize(5);
printVector(v1); // 如果重新指定的比原来短了,超出部分会被删除掉
}
int main()
{
test1();
return 0;
}
push_back()
尾部插入元素pop_back()
删除最后一个元素insert
向指定位置插入元素erase
删除迭代器指向的元素clear
删除容器中所有元素#include
#include
using namespace std;
// 打印输出容器中的内容
void printVector(vector<int> &v)
{
for (vector<int>::iterator it = v.begin(); it != v.end(); it++)
{
cout << *it << " ";
}
cout << endl;
}
void test1()
{
vector<int> v1;
for (int i = 0; i < 10; i++)
{
v1.push_back(i);
}
printVector(v1);
// 尾部删除一个元素
v1.pop_back();
printVector(v1);
// 插入
v1.insert(v1.begin(), 100);
v1.insert(v1.begin(), 2, 100); // 在头部插入n个数据
printVector(v1);
// 删除
v1.erase(v1.begin()); // 删除头部的一个元素
v1.erase(v1.begin(), v1.end()); // 区间删除
v1.clear(); // 清空容器中的元素
}
int main()
{
test1();
return 0;
}
#include
#include
using namespace std;
// 打印输出容器中的内容
void printVector(vector<int> &v)
{
for (vector<int>::iterator it = v.begin(); it != v.end(); it++)
{
cout << *it << " ";
}
cout << endl;
}
void test1()
{
vector<int> v1;
for (int i = 0; i < 10; i++)
{
v1.push_back(i);
}
printVector(v1);
// 访问方式1
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()
{
test1();
return 0;
}
#include
#include
using namespace std;
// 打印输出容器中的内容
void printVector(vector<int> &v)
{
for (vector<int>::iterator it = v.begin(); it != v.end(); it++)
{
cout << *it << " ";
}
cout << endl;
}
void test1()
{
// 容器1
vector<int> v1;
for (int i = 0; i < 10; i++)
{
v1.push_back(i);
}
printVector(v1);
// 容器2
vector<int> v2;
for (int i = 10; i > 0; i--)
{
v2.push_back(i);
}
printVector(v2);
// 交换容器
v1.swap(v2); // v1与v2进行元素交换
printVector(v1);
printVector(v2);
}
int main()
{
test1();
return 0;
}
vector
在动态扩展容量时的扩展次数reserve(int len)
容器预留len#include
#include
using namespace std;
// vector容器,当内存空间不足时,自动开辟内存
void test1()
{
int num = 0; // 统计空间开辟次数
int *p = NULL;
// 容器1
vector<int> v1;
v1.reserve(10); // 利用reserve预留空间
for (int i = 0; i < 10; i++)
{
v1.push_back(i);
if (p != &v1[0])
{
p = &v1[0]; // 每次重新开辟空间时,从首地址0开始
num++;
}
}
cout << num << endl; // 使用v1.reserve(10)之后,输出1,不用时,输出5,也就是开辟了5次空间
}
int main()
{
test1();
return 0;
}
功能:双端队列,可以对头部进行插入删除操作
vector
只能使用push_back()
进行尾插#include
#include
using namespace std;
// 只读迭代器,防止数据被意外的修改
void printDeque(const deque<int> &d)
{
for (deque<int>::const_iterator it = d.begin(); it != d.end(); it++)
{
cout << *it << " ";
}
cout << endl;
}
void test1()
{
deque<int> d1;
for (int i = 0; i < 10; i++)
{
d1.push_back(i);
}
printDeque(d1);
// 采用区间的方式进行赋值
deque<int> d2(d1.begin(), d1.end());
printDeque(d2);
// 赋值方式3
deque<int> d3(10, 100); // 10个100
printDeque(d3);
// 拷贝构造的方式
deque<int> d4(d3); // 拷贝d3
printDeque(d4);
}
int main()
{
test1();
return 0;
}
与vector
赋值操作一样
#include
#include
using namespace std;
// 只读迭代器,防止数据被意外的修改
void printDeque(const deque<int> &d)
{
for (deque<int>::const_iterator it = d.begin(); it != d.end(); it++)
{
cout << *it << " ";
}
cout << endl;
}
void test1()
{
deque<int> d1;
for (int i = 0; i < 10; i++)
{
d1.push_back(i);
}
printDeque(d1);
// 等号赋值
deque<int> d2;
d2 = d1;
printDeque(d2);
// assign赋值
deque<int> d3;
d3.assign(d1.begin(), d1.end());
printDeque(d3);
deque<int> d4;
d4.assign(10, 100);
printDeque(d4);
}
int main()
{
test1();
return 0;
}
deque
相比于vector
容器,没有容量的概念。
#include
#include
using namespace std;
// 只读迭代器,防止数据被意外的修改
void printDeque(const deque<int> &d)
{
for (deque<int>::const_iterator it = d.begin(); it != d.end(); it++)
{
cout << *it << " ";
}
cout << endl;
}
void test1()
{
deque<int> d1;
for (int i = 0; i < 10; i++)
{
d1.push_back(i);
}
printDeque(d1);
if (d1.empty())
{
cout << "容器为空" << endl;
}
// 元素个数
cout << "d1的大小:" << d1.size() << endl; // 输出10
// 重新指定大小
d1.resize(15); // 多出的部分用0进行填充
d1.resize(15, 1); // 多出的部分用1进行填充
d1.resize(3); // 超出的部分被删除
}
int main()
{
test1();
return 0;
}
功能描述:向deque
容器中插入和删除数据。
#include
#include
using namespace std;
// 只读迭代器,防止数据被意外的修改
void printDeque(const deque<int> &d)
{
for (deque<int>::const_iterator it = d.begin(); it != d.end(); it++)
{
cout << *it << " ";
}
cout << endl;
}
// 两端插入和删除操作
void test1()
{
deque<int> d1;
d1.push_back(1); // 尾插
d1.push_back(2);
d1.push_front(3); // 头插
d1.push_front(4);
printDeque(d1); // 输出4 3 1 2
d1.pop_back(); // 尾删一个元素
d1.pop_front(); // 头删一个元素
printDeque(d1); // 输出 3 1
}
// 指定位置插入和删除
void test2()
{
deque<int> d1;
d1.push_back(1); // 尾插
d1.push_back(2);
d1.push_front(3); // 头插
d1.push_front(4);
printDeque(d1); // 输出4 3 1 2
// insert插入
d1.insert(d1.begin(), 10); // 在头部插入一个元素
d1.insert(d1.begin(), 2, 10); // 在头部插入2个元素
// 按照区间进行插入
deque<int> d2;
for (int i = 0; i < 3; i++)
{
d2.push_back(i);
}
printDeque(d2);
d1.insert(d1.begin(), d2.begin(), d2.end()); // 在d1的头部插入d2的区间元素
printDeque(d1);
// 删除操作
deque<int>::iterator it = d1.begin(); // 创建一个迭代器
it++;
d1.erase(it); // 删除第二个元素
// 按区间方式进行删除
d1.erase(d1.begin(),d1.end());
d1.clear(); // 效果等同于上面的语句
}
int main()
{
// test1();
test2();
return 0;
}
功能描述:对deque
中的数据进行存取操作。
#include
#include
using namespace std;
void test1()
{
deque<int> d1;
for (int i = 0; i < 10; i++)
{
d1.push_back(i);
}
// 通过[]访问
for (int i = 0; i < d1.size(); i++)
{
cout << d1[i] << " ";
}
cout << endl;
// 通过at方式访问元素
for (int i = 0; i < d1.size(); i++)
{
cout << d1.at(i) << " ";
}
cout << endl;
// 访问头尾元素
cout << "第一个元素:" << d1.front() << endl;
cout << "最后一个元素:" << d1.back() << endl;
}
int main()
{
test1();
return 0;
}
功能描述:利用算法sort
实现对deque
容器进行排序。
#include
vector
容器#include
#include
#include // 标准算法头文件
using namespace std;
// 只读迭代器,防止数据被意外的修改
void printDeque(const deque<int> &d)
{
for (deque<int>::const_iterator it = d.begin(); it != d.end(); it++)
{
cout << *it << " ";
}
cout << endl;
}
void test1()
{
deque<int> d1;
d1.push_back(10);
d1.push_back(8);
d1.push_front(0);
d1.push_front(1);
printDeque(d1); // 输出1 0 10 8
// 排序:默认规则为从小到大排序
sort(d1.begin(), d1.end());
printDeque(d1); // 升序
}
int main()
{
test1();
return 0;
}
stack是一种先进后出(后进先出)(First In Last Out,FILO)的数据结构,只有一个出口。
push
,出栈pop
,生活中的栈实例:弹夹#include
#include
using namespace std;
void test1()
{
stack<int> s;
// 入栈
for (int i = 0; i < 4; i++)
{
s.push(i);
}
cout << "栈的大小:" << s.size() << endl; // 输出:4
// 只要栈不为空,查看栈顶,并且执行出栈操作
while (!s.empty())
{
cout << "栈顶元素为:" << s.top() << endl;
s.pop(); // 出栈,才能访问下一个元素
}
cout << "栈的大小:" << s.size() << endl; // 数据元素全部出栈后,栈的大小为0
}
int main()
{
test1();
return 0;
}
queue
是一种先进先出(First In First Out,FIFO)的数据结构,它有两个出口。#include
#include
using namespace std;
void test1()
{
queue<int> q; // 创建一个队列容器
q.push(10); // 先进先出
q.push(1);
q.push(2);
cout << "队列大小:" << q.size() << endl; // 输出3
while (!q.empty())
{
// 查看队头
cout << "对头:" << q.front() << endl;
cout << "队尾:" << q.back() << endl;
q.pop(); // 出队,要不是一个死循环
}
cout << "队列大小:" << q.size() << endl; // 输出0
}
int main()
{
test1();
return 0;
}
功能:将数据进行链式存储
链表的优点:可以对任意位置进行快速插入或删除元素。
缺点:容器的遍历速度没有数组快,占用的空间比数组大(有指针域的存在)
链表(list)是一种物理存储单元上非连续的存储结构,数据元素的逻辑顺序是通过链表中的指针链接实现的
链表的组成:链表由一系列结点组成
结点的组成:一个是存储数据元素的数据域,另一个是存储下一个结点地址的指针域。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-TBlPmX2P-1685616790228)(images/10.png)]
STL中的链表是一个双向循环链表
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-CetDVMh5-1685616790229)(images/11.png)]
由于链表的存储方式并不是连续的内存空间,因此链表list中的迭代器只支持前移和后移,属于双向迭代器。
list的优点:
list的缺点:
list
有一个重要的性质,插入和删除操作都不会造成原有list
迭代器的失效,这在vector
是不成立的。#include
#include
using namespace std;
void printList(const list<int> &L)
{
for (list<int>::const_iterator it = L.begin(); it != L.end(); it++)
{
cout << *it << " ";
}
cout << endl;
}
void test1()
{
list<int> L1;
L1.push_back(1);
L1.push_back(2);
L1.push_back(3);
printList(L1); // 输出1 2 3
list<int> L2(L1.begin(), L1.end()); // 区间方式构造
printList(L2);
list<int> L3(L2); // 拷贝构造
printList(L3);
list<int> L4(10, 100); // 赋值10个100
printList(L4);
}
int main()
{
test1();
return 0;
}
#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 test1()
{
list L1;
L1.push_back(1);
L1.push_back(2);
L1.push_back(3);
printList(L1); // 输出1 2 3
list L2 = L1; // 直接赋值
printList(L2);
list L3;
L3.assign(L2.begin(), L2.end()); // assign赋值
printList(L3);
list L4;
L4.assign(10, 100);
printList(L4);
}
// 交换
void test2()
{
list L1;
L1.push_back(1);
L1.push_back(2);
L1.push_back(3);
list L2;
L2.assign(10, 100);
cout << "交换前:" << endl;
printList(L1);
printList(L2);
cout << "交换后:" << endl;
L1.swap(L2);
printList(L1);
printList(L2);
}
int main()
{
// test1();
test2();
return 0;
}
#include
#include
using namespace std;
void printList(const list<int> &L)
{
for (list<int>::const_iterator it = L.begin(); it != L.end(); it++)
{
cout << *it << " ";
}
cout << endl;
}
void test1()
{
list<int> L1;
L1.push_back(1);
L1.push_back(2);
L1.push_back(3);
printList(L1); // 输出1 2 3
if (!L1.empty()) // 判断容器是否为空
{
cout << "L1元素个数:" << L1.size() << endl;
}
// 重新指定容器大小
L1.resize(10);
printList(L1);
}
int main()
{
test1();
return 0;
}
#include
#include
using namespace std;
void printList(const list<int> &L)
{
for (list<int>::const_iterator it = L.begin(); it != L.end(); it++)
{
cout << *it << " ";
}
cout << endl;
}
void test1()
{
list<int> L1;
L1.push_back(1); // 尾插
L1.push_back(2);
L1.push_front(3); // 头插
L1.push_front(4);
printList(L1); // 输出4 3 1 2
L1.pop_back(); // 尾部删除一个元素
L1.pop_front(); // 头部删除一个元素
// insert
L1.insert(L1.begin(), 1000);
list<int>::iterator it = L1.begin();
L1.insert(++it, 10); // 创建一个迭代器,在其他位置插入元素
// 删除
L1.erase(L1.begin()); // 移除头部的一个元素
// 移除
L1.remove(100); // 删除容器中所有与元素值匹配的元素
L1.clear(); // 清空
}
int main()
{
test1();
return 0;
}
[]
和at()
的方式访问元素 list<int>::iterator it = L1.begin();
it++; // 支持,可以通过多加几次,访问其他元素
it--; // 支持
it = it + 1; // 不支持
it = it + 2; // 不支持
front()
返回第一个元素back()
返回最后一个元素功能描述:将容器中的元素反转,以及将容器中的数据进行排序。
reverse()
反转链表sort()
链表排序,所有不支持随机访问迭代器的容器,不可以使用标准算法。不支持随机访问迭代器的容器,内部会提供对应的一些算法#include
#include
using namespace std;
void printList(const list<int> &L)
{
for (list<int>::const_iterator it = L.begin(); it != L.end(); it++)
{
cout << *it << " ";
}
cout << endl;
}
bool myCompare(int v1, int v2)
{
// 降序:让第一个数>第二个数
return v1 > v2;
}
void test1()
{
list<int> L1;
L1.push_back(1); // 尾插
L1.push_back(2);
L1.push_front(3); // 头插
L1.push_front(4);
cout << "反转前:";
printList(L1); // 输出4 3 1 2
cout << "反转后:";
L1.reverse(); // 反转
printList(L1);
// 排序
cout << "排序前:";
printList(L1);
cout << "排序后(升序):";
L1.sort(); // 默认排序规则:从小到大升序
printList(L1);
// 通过仿函数实现降序排序
cout << "排序后(降序):";
L1.sort(myCompare); // 传入自定义的仿函数名
printList(L1);
}
int main()
{
test1();
return 0;
}
set/multiset
属于关联式容器,底层结构是用二叉树实现的。#include
#include
using namespace std;
void printSet(set<int> &s)
{
for (set<int>::iterator it = s.begin(); it != s.end(); it++)
{
cout << *it << " ";
}
cout << endl;
}
// set容器构造和赋值
void test1()
{
set<int> s1;
s1.insert(1); // 插入数据只有insert方式
s1.insert(0); // set容器不允许插入重复值
s1.insert(3);
printSet(s1); // 遍历容器,自动输出排序后(升序)的值
set<int> s2(s1); // 拷贝构造
// 赋值方式
set<int> s3;
s3 = s2;
}
int main()
{
test1();
return 0;
}
#include
#include
using namespace std;
void printSet(set<int> &s)
{
for (set<int>::iterator it = s.begin(); it != s.end(); it++)
{
cout << *it << " ";
}
cout << endl;
}
void test1()
{
set<int> s1;
s1.insert(1); // 插入数据只有insert方式
s1.insert(0); // set容器不允许插入重复值
s1.insert(3);
if (!s1.empty())
{
cout << "元素的个数:" << s1.size() << endl;
}
set<int> s2;
s2.insert(2);
s2.insert(1);
cout << "交换前:" << endl;
printSet(s1);
printSet(s2);
cout << "交换后:" << endl;
s1.swap(s2);
printSet(s1);
printSet(s2);
}
int main()
{
test1();
return 0;
}
#include
#include
using namespace std;
void printSet(set<int> &s)
{
for (set<int>::iterator it = s.begin(); it != s.end(); it++)
{
cout << *it << " ";
}
cout << endl;
}
void test1()
{
set<int> s1;
s1.insert(1); // 插入数据只有insert方式
s1.insert(0); // set容器不允许插入重复值
s1.insert(3);
s1.erase(s1.begin()); // 删除头部元素(自动排序后的头部元素)
printSet(s1);
s1.erase(3); // 删除指定元素
s1.erase(s1.begin(), s1.end()); // 清空
s1.clear(); // 同上
}
int main()
{
test1();
return 0;
}
find(key)
查找key是否存在,若存在,返回该元素的迭代器。若不存在,返回set.end()
count(key)
统计key的元素个数,对于set
容器而言,返回值为0或1#include
#include
using namespace std;
void test1()
{
set<int> s1;
s1.insert(1);
s1.insert(0);
s1.insert(3);
set<int>::iterator pos = s1.find(3);
if (pos != s1.end())
{
cout << "找到元素:" << *pos << endl;
}
else
{
cout << "未找到" << endl;
}
int num = s1.count(0); // 统计元素0的个数
cout << num << endl;
}
int main()
{
test1();
return 0;
}
#include
#include
using namespace std;
void printMultiset(multiset<int> &ms)
{
for (multiset<int>::iterator it = ms.begin(); it != ms.end(); it++)
{
cout << *it << " ";
}
cout << endl;
}
void test1()
{
set<int> s1;
s1.insert(1);
s1.insert(0);
s1.insert(3);
pair<set<int>::iterator, bool> ret = s1.insert(10);
if (ret.second)
{
cout << "第一次插入成功" << endl;
}
else
{
cout << "第一次插入失败" << endl;
}
ret = s1.insert(10); // 插入重复值,会失败
if (ret.second)
{
cout << "第二次插入成功" << endl;
}
else
{
cout << "第二次插入失败" << endl;
}
// multiset允许插入重复值
multiset<int> ms;
ms.insert(10);
ms.insert(10);
printMultiset(ms); // 输出:10 10
}
int main()
{
test1();
return 0;
}
功能描述:成对出现的数据,利用对组可以返回两个数据
#include
#include
using namespace std;
void test1()
{
// 第一种创建方式
pair<string, int> p1("Tom", 20); // 数据类型,数据值
cout << "姓名:" << p1.first << "年龄:" << p1.second << endl;
// 第二种创建方式
pair<string, int> p2 = make_pair("小明", 18);
cout << "姓名:" << p2.first << "年龄:" << p2.second << endl;
}
int main()
{
test1();
return 0;
}
学习目标:set容器默认排序规则为从小到大,掌握如何改变排序规则。
主要技术点:利用仿函数,可以改变排序规则。
示例1:set存放内置数据类型
#include
#include
using namespace std;
void printSet(set<int> &s)
{
for (set<int>::iterator it = s.begin(); it != s.end(); it++)
{
cout << *it << " ";
}
cout << endl;
}
class MyCompare
{
public:
bool operator()(int v1, int v2)
{
return v1 > v2;
}
};
void printSet2(set<int, MyCompare> &s)
{
for (set<int, MyCompare>::iterator it = s.begin(); it != s.end(); it++)
{
cout << *it << " ";
}
cout << endl;
}
void test1()
{
set<int> s1;
s1.insert(10);
s1.insert(6);
s1.insert(7);
printSet(s1); // 输出 6 7 10
// 指定排序规则为从大到小
set<int, MyCompare> s2; // 仿函数本质上是一个数据类型
s2.insert(10);
s2.insert(6);
s2.insert(7);
printSet2(s2); // 输出 10 7 6
}
int main()
{
test1();
return 0;
}
#include
#include
#include
using namespace std;
// 创建自定义数据类型
class Person
{
public:
string m_name;
int m_age;
Person(string name, int age)
{
this->m_name = name;
this->m_age = age;
}
};
// 指定排序规则
class MyCompare
{
public:
bool operator()(const Person &p1, const Person &p2)
{
// 按照年龄降序
return p1.m_age > p2.m_age;
}
};
void printSet(set<Person, MyCompare> &s)
{
for (set<Person, MyCompare>::iterator it = s.begin(); it != s.end(); it++)
{
cout << "姓名:" << it->m_name << ",年龄:" << it->m_age << endl;
}
}
void test1()
{
set<Person, MyCompare> s;
Person p1("刘备", 1);
Person p2("关羽", 3);
Person p3("张飞", 2);
s.insert(p1);
s.insert(p2);
s.insert(p3);
printSet(s);
}
int main()
{
test1();
return 0;
}