容器、算法、迭代器、仿函数、适配器(配接器)、空间配置器
容器:STL容器就是将运用最广泛的一些数据结构实现出来
常用的数据结构:数组,链表,树,栈,队列,集合,映射表等
这些容器分为 序列式容器和关联式容器 两种:
算法:
有限的步骤,解决逻辑上或数学上的问题,算法可以分为质变算法和非质变算法
质变算法:是指运算过程中会更改区间内的元素的内容,例如拷贝、替换、删除等
非质变算法:是指运算过程中不会更改区间内的元素内容,例如查找、计数、遍历、寻找极值等
迭代器:算法和容器之间的桥梁
提供一种方法,使之能够依序访问某个容器中所含的各个元素,而又无需暴漏该容器的内部表示方式
每个容器都有自己专属的迭代器
迭代器使用非常类似于指针,初始阶段可以理解为指针
迭代器种类:
种类 | 功能 | 支持运算 |
---|---|---|
输入迭代器 | 对数据的只读访问 | 只读,支持 ++,==,!= |
输出迭代器 | 对数据的只写访问 | 只写,支持 ++ |
前向迭代器 | 读写操作,并能向前推进迭代器 | 读写,支持 ++,==,!= |
双向迭代器 | 读写操作,并能向前和向后操作 | 读写,支持++,– |
随机访问迭代器 | 读写操作,可以以跳跃的方式访问任意数据,功能最强的迭代器 | 读写,支持++,–,[n],-n.<,>,>=,<= |
常用的迭代器种类为双向迭代器和随机访问迭代器
STL中最常用的容器是vector,可以理解为数组
容器 | 算法 | 迭代器 |
---|---|---|
vector | for_each | vector::iterator |
示例:
#include
#include //标准算法头文件
void myPrint(int val)
{
cout << val << endl;
}
void test01()
{
//创建了一个vector容器---数组
vector<int> v;
//容器中插入数据 vector内置 .push_back()尾插法
v.push_back(10);
v.push_back(20);
v.push_back(30);
v.push_back(40);
//通过迭代器访问容器中的数据
vector<int>::iterator itBegin = v.begin(); //起始迭代器,指向容器中第一个元素
vector<int>::iterator itEnd = v.end(); //结束迭代器,指向容器中最后一个元素的下一个位置
//第一种遍历方式
while (itBegin != itEnd)
{
//对指针解引用
cout << *itBegin << endl;
itBegin++;
}
//第二种遍历方式
for (vector<int>::iterator it = v.begin(); it != v.end(); it++)
{
cout << *it << endl;
}
//第三种遍历方式 利用STL中提供的遍历算法for_each 需要导入标准算法头文件
for_each(v.begin(), v.end(), myPrint);
}
int main()
{
test01();
system("pause");
return 0;
}
示例:
#include
class Person
{
public:
Person(string name, int age)
{
this->m_name = name;
this->m_age = age;
}
string m_name;
int m_age;
};
//存放自定义数据类型
void test01()
{
vector<Person> v;
Person p1("hututu", 23);
Person p2("lututu", 23);
Person p3("eututu", 23);
Person p4("mututu", 23);
Person p5("pututu", 23);
//向容器中尾插数据
v.push_back(p1);
v.push_back(p2);
v.push_back(p3);
v.push_back(p4);
v.push_back(p5);
//遍历容器中数据
//it是Person*,解引用后是Person
for (vector<Person>::iterator it = v.begin(); it != v.end(); it++)
{
/*cout << "姓名:" << (*it).m_name << " "
<< "年龄:" << (*it).m_age << endl;*/
//it可以看作指针
cout << "姓名:" << it->m_name << " "
<< "年龄:" << it->m_age << endl;
}
}
//存放自定义数据类型指针
void test02()
{
//容器中存放的是地址
vector<Person*> v;
Person p1("hututu", 23);
Person p2("lututu", 23);
Person p3("eututu", 23);
Person p4("mututu", 23);
Person p5("pututu", 23);
//向容器中尾插数据
v.push_back(&p1);
v.push_back(&p2);
v.push_back(&p3);
v.push_back(&p4);
v.push_back(&p5);
//遍历容器
//it是Person**,解引用的(*it)是Person*
for (vector<Person*>::iterator it = v.begin(); it != v.end(); it++)
{
cout << "姓名:" << (*it)->m_name << "\t" << "年龄:"
<< (*it)->m_age << endl;
}
}
int main()
{
test02();
system("pause");
return 0;
}
注意:
- vector<Person>::iterator it,it是Person*,解引用的(*it)是Person
- vector<Person*>::iterator it,it是Person**,解引用的(*it)是Person*
学习容器嵌套容器,将所有数据进行遍历输出
示例:
#include
void test01()
{
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类型的数据容器
for (vector<int>::iterator vit = (*it).begin(); vit != (*it).end(); vit++)
{
//*vit 是int类型的
cout << *vit << " ";
}
cout << endl;
}
}
int main()
{
test01();
system("pause");
return 0;
}
--------------------------------------------------------------------------------------
1 2 3 4
2 3 4 5
3 4 5 6
4 5 6 7
请按任意键继续. . .
本质:
string和char 区别*:
特点:
构造函数原型
string(); //构建一个空的字符串
string(const char* s); //使用字符串s进行初始化
string(const string& str); //使用一个string对象初始化另一个string对象
string(int n,char c); //使用n个字符初始化
void test01()
{
string s1; //默认构造
//把c_string转化成了string
const char* str = "nibukunwokun";
string s2(str);
cout << "s2=" << s2 << endl;
//调用拷贝构造函数
string s3(s2);
cout << "s3=" << s3 << endl;
string s4(6, 'a');
cout << "s4=" << s4 << endl;
}
int main()
{
test01();
system("pause");
return 0;
}
-----------------------------------------------------------
s2=nibukunwokun
s3=nibukunwokun
s4=aaaaaa
请按任意键继续. . .
功能描述:给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赋值给当前的字符串 |
示例:
#include
void test01()
{
//string & operator=(const char* s);
string str1;
str1 = "hello world";
cout << "str1= " << str1 << endl;
//string & operator=(const string s);
string str2;
str2 = str1;
cout << "str2= " << str2 << endl;
//string & operator=(char c);
string str3;
str3 = 'a';
cout << "str3= " << str3 << endl;
//string & assign(const char * s);
string str4;
str4.assign("hututu");
cout << "str4= " << str4 << endl;
string str5;
str5.assign("hututu", 3);
cout << "str5= " << str5 << endl;
string str6;
str6.assign(str5);
cout << "str6= " << str6 << endl;
string str7;
str7.assign(10, 'a');
cout << "str7= " << str7 << endl;
}
int main()
{
test01();
system("pause");
return 0;
}
------------------------------------------
str1= hello world
str2= hello world
str3= a
str4= hututu
str5= hut
str6= hut
str7= aaaaaaaaaa
请按任意键继续. . .
功能描述:实现字符串末尾拼接字符串
函数原型
函数 | 注释 |
---|---|
string & opertor+=(const char* str); | 重载+=操作符 |
string & opertor+=(const char c); | 重载+=操作符 |
string & opertor+=(const string & str); | 重载+=操作符 |
string & append(const char* s); | 把字符串s拼接到当前字符串结尾 |
string & append(const char* s, int n); | 把字符串s的前n个字符连接到当前字符串结尾 |
string & append(const string &s); | 同string & opertor+=(const char* str); |
string & append(const string &s, int pos, int n); | 字符串s中从pos开始的n个字符连接到字符串结尾 |
示例:
void test01()
{
//重载+=运算符
string str1 = "你";
str1 += "不困";
cout << str1 << endl;
str1 += ',';
cout << str1 << endl;
string str2 = "我困";
str1 += str2;
cout << "str1=" << str1 << endl;
//append函数
string str3 = "hututu";
str3.append(" and");
cout << "str3=" << str3 << endl;
str3.append(" xiaomei abdjs", 8);
cout << "str3=" << str3 << endl;
//str3.append(str2);
//cout << "str3=" << str3 << endl;
string str4 = "abcdefg";
//从pos位置开始,截取n个元素
str3.append(str4, 0, 3);
cout << "str3=" << str3 << endl;
}
int main()
{
test01();
system("pause");
return 0;
}
功能描述:
函数原型:
函数 | 注释 |
---|---|
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第一次出现位置 |
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 c, int pos=0)const; | 查找字符c最后一次出现位置 |
int rfind(const char *s,int pos,int n)const; | 从pos查找s的前n个字符最后一次位置 |
string & replace(int pos, int n, const string & str); | 替换从pos开始n个字符为字符串str |
string & replace(int pos,int n,const char *s); | 替换从pos开始的n字符为字符串s |
示例:
#include
void test01()
{
string str1 = "hututugaagag";
int pos1 = str1.find("hu");
if (pos1 == -1)
cout << "未找到字符串" << endl;
else
cout << "字符串第一次出现的位置是:" << pos1 << endl;
//cout << "pos1=" << pos1 << endl; //2
//rfind
//rfind是从右往左查找,find是左往右查找
int pos2 = str1.rfind("hu");
cout << "pos2=" << pos2 << endl;
}
//替换
void test02()
{
string str1 = "abcdefg";
//从1号位置起,3个字符替换为1111
str1.replace(1, 3, "1111");
cout << str1 << endl; //a1111efg
}
总结:
功能描述:字符串之间的比较
比较方式:字符串比较是按照字符的ASCII码进行对比
= 返回0
> 返回1
< 返回-1
函数原型:
函数 | 注释 |
---|---|
int compare(const string &s)const; | 与字符串s比较 |
int compare(const char *s)const; | 与字符串s比较 |
示例:
#include
void test01()
{
string str1 = "hello";
string str2 = "hello";
if (str1.compare(str2) == 0)
cout << "str1==str2" << endl;
else if (str1.compare(str2) == 1)
cout << "str1>str2" << endl;
else
cout << "str1 << endl;
}
string中单个字符串存取方式有两种
函数 | 注释 |
---|---|
char& operator[](int n); | 通过[]方式取字符 |
char& art(int n); | 通过at方式获取字符 |
示例:
#include
void test01()
{
string str1 = "hello";
//cout << "str1=" << str1 << endl;
//依次输出字符串中字符
//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] = 'a';
cout << "str1=" << str1 << endl; //str1=aello
str1.at(1) = 'a';
cout << "str1=" << str1 << endl; //str1=aallo
}
功能描述:对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
void test01()
{
string str = "hello";
//插入
str.insert(1, "111");
cout << "str=" << str << endl; //str=h111ello
//删除
str.erase(1, 3);
cout << "str=" << str << endl; //str=hello
}
功能描述:从字符串中获取想要的子串
函数原型:
string substr(int pos = 0, int n = npos) const;` //返回由pos开始的n个字符组成的字符串
示例:
#include
void test()
{
string str = "abcdefg";
string subStr = str.substr(1, 3);
cout << subStr << endl; //bcd
}
void test02()
{
string email = "[email protected]";
//从邮件地址中获取用户信息
int pos = email.find("@"); //返回@的下标地址
string userName = email.substr(0, pos);
cout << userName << endl; //nibukunwokun
}
功能:
vector与普通数组的区别:
动态扩展:
并不是在原空间之后续接新空间,而是找更大的内存空间,然后将原数据拷贝到新空间,释放原空间
vector容器的迭代器是支持随机访问的迭代器
功能描述:
函数原型:
函数原型 | 注释 |
---|---|
vector v; | 采用模板实现类实现,默认构造函数 |
vector v(v.begin(), v.end()) ; | 将v [begin(),end()) 区间(前闭后开)中的元素拷贝到自身 |
vector v(n, elem); | 构造函数将n个elem拷贝给本身 |
vector v(const vector &vec); | 拷贝构造函数 |
示例:
#include
void printVector(vector<int> &v)
{
for (vector<int>::iterator it = v.begin(); it != v.end(); it++)
cout << *it << " ";
cout << endl;
}
void test01()
{
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个elem方式构造
vector<int>v3(10, 88);
printVector(v3);
//拷贝构造
vector<int>v4(v3);
printVector(v4);
}
-----------------------------------------------------
0 1 2 3 4 5 6 7 8 9
0 1 2 3 4 5 6 7 8 9
88 88 88 88 88 88 88 88 88 88
88 88 88 88 88 88 88 88 88 88
请按任意键继续. . .
功能描述:
函数原型:
函数原型 | 注释 |
---|---|
vector& operator=(const vector &vec); | 重载等号操作符 |
assign(beg, end); | 将[beg,end]区间中的数据拷贝赋值给本身 |
assign(n, elem); | 将n个elem拷贝赋值给本身 |
示例:
#include
void test01()
{
vector<int> v1;
for (int i = 0; i < 10; i++)
v1.push_back(i);
printVector(v1);
//赋值 重载=
vector<int> v2;
v2 = v1;
printVector(v2);
//assign
vector<int>v3;
v3.assign(v1.begin(), v1.end());
printVector(v3);
vector<int>v4;
v4.assign(10, 88);
printVector(v4);
}
-----------------------------------------------
0 1 2 3 4 5 6 7 8 9
0 1 2 3 4 5 6 7 8 9
0 1 2 3 4 5 6 7 8 9
88 88 88 88 88 88 88 88 88 88
请按任意键继续. . .
功能描述:
函数原型:
函数 | 注释 |
---|---|
empty(); | 判断容器是否为空 |
capacity(); | 容器的容量 |
size(); | 返回容器中元素的个数 |
resize(int num); | 重新指定容器的长度为num,若容器变长,则以默认值填充新位置;若容器变短,则末尾超出容器长度的元素被删除 |
resize(int num, elem); | 重新指定容器的长度为num,若容器变长,则以elem值填充新位置 ;若容器变短,则 末尾超出容器长度的元素被删除 |
示例:
void test01()
{
vector<int>v1;
for (int i = 0; i < 10; i++)
v1.push_back(i);
printVector(v1);
//.empty()为true,则代表容器为空
if (v1.empty())
cout << "v1为空" << endl;
else
{
cout << "v1不为空" << endl;
cout << "v1的容量是:" << v1.capacity() << endl;
cout << "v1的大小是:" << v1.size() << endl; //此时容器中元素个数
}
//重新指定大小
v1.resize(15);
printVector(v1);
v1.resize(5);
printVector(v1);
}
-----------------------------------------------
0 1 2 3 4 5 6 7 8 9
v1不为空
v1的容量是:13
v1的大小是:10
0 1 2 3 4 5 6 7 8 9 0 0 0 0 0
0 1 2 3 4
请按任意键继续. . .
功能描述:
函数原型:
函数 | 注释 |
---|---|
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(); | 删除容器中所有元素 |
示例:
void test01()
{
vector<int>v1;
//尾插法
v1.push_back(10);
v1.push_back(20);
v1.push_back(30);
v1.push_back(40);
v1.push_back(50);
printVector(v1);
//尾删
v1.pop_back();
printVector(v1);
//插入 第一个参数是迭代器
v1.insert(v1.begin(), 88);
printVector(v1);
v1.insert(v1.begin(), 2, 99);
printVector(v1);
//删除 参数也是迭代器
v1.erase(v1.begin());
printVector(v1);
v1.erase(v1.begin(), v1.end()); //类似于 .clear()
printVector(v1);
}
-----------------------------------
10 20 30 40 50
10 20 30 40
88 10 20 30 40
99 99 88 10 20 30 40
99 88 10 20 30 40
请按任意键继续. . .
功能描述:
函数原型:
函数 | 注释 |
---|---|
at(int idx); | 返回索引idx所指的数据 |
operator[]; | 返回索引idx所指的数据 |
front(); | 返回容器中第一个数据元素 |
back(); | 返回容器中最后一个数据元素 |
示例:
void test01()
{
vector<int> v1;
for (int i = 0; i < 10; i++)
v1.push_back(i);
//利用重载[]来访问vector中元素
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;
}
-------------------------------------------
0 1 2 3 4 5 6 7 8 9
0 1 2 3 4 5 6 7 8 9
第一个元素为:0
最后一个元素为:9
请按任意键继续. . .
功能描述:
函数原型:
函数 | 注释 |
---|---|
swap(vec); | 将vec与本身的元素互换 |
示例:
#include
void printVector(vector<int>&v)
{
for (vector<int>::iterator it = v.begin(); it != v.end(); it++)
cout << *it << " ";
cout << endl;
}
//基本使用
void test01()
{
vector<int> v1;
for (int i = 0; i < 10; i++)
v1.push_back(i);
vector<int>v2;
for (int i = 10; i > 0; i--)
v2.push_back(i);
cout << "交换前:" << endl;
printVector(v1);
printVector(v2);
cout << "交换后:" << endl;
v1.swap(v2);
printVector(v1);
printVector(v2);
}
//实际用途:巧用swap可以收缩内存空间
void test02()
{
vector<int>v;
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) 匿名对象,按照v对其进行初始化
.swap(v) 类似于指针的交换,相当于将匿名对象容器和v进行交换
因为匿名对象由编译器自动回收,所以不用担心大量空间被占用
*/
vector<int>(v).swap(v);
cout << "v的容量:" << v.capacity() << endl;
cout << "v的大小:" << v.size() << endl;
}
----------------------------------------------
v的容量:138255
v的大小:100000
v的容量:138255
v的大小:3
v的容量:3
v的大小:3
请按任意键继续. . .
功能介绍:减少vector在动态扩展容量时的扩展次数
函数原型:
reserve(int len);//容器预留len个元素长度,预留位置不初始化,元素不可访问
示例:
#include
void test01()
{
vector<int> v;
//利用reserve来预留空间
//当数据量很大时,最开始就进行预留空间就可以避免后期不断开辟新空间
v.reserve(10000);
int num = 0;
int *p = NULL;
for (int i = 0; i < 10000; i++)
{
v.push_back(i);
//每次开辟内存时,首地址都会发生改变,用num记录动态扩展的次数
if (p != &v[0])
{
p = &v[0];
num++;
}
}
cout << "num=" << num << endl;
}
功能:双端数组,可以对头端进行插入删除操作
deque与vector的区别:
deque内部工作原理:
deque内部有个中控器,维护每段缓冲区中的内容,缓冲区中存放真实数据
中控器中维护的是每个缓冲区的地址,使得使用deque时像是一片连续的内存空间
功能描述:deque容器构造
函数原型:
函数原型 | 注释 |
---|---|
deque deque T; | 默认构造形式 |
deque(beg,end); | 构造函数将【beg,end)区间中的元素拷贝给本身 |
deque(n, elem); | 构造函数将n个elem拷贝给本身 |
deque(cosnt deque &deq); | 拷贝构造函数 |
示例:
#include
//输入参数 const限定只读
void printDeque(const deque<int> &d)
{
//获取迭代器deque::const_iterator类型同样也是限定只读
for (deque<int>::const_iterator it = d.begin(); it != d.end(); it++)
{
cout << *it << " ";
}
cout << endl;
}
void test01()
{
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);
deque<int>d3(10, 100);
printDeque(d3);
deque<int>d4(d3);
printDeque(d4);
}
总结:deque容器和vector容器的构造方式几乎一致
功能描述:给deque容器进行赋值
函数原型:
函数原型 | 注释 |
---|---|
deque& operator =(const deque &deq); | 重载等号操作符 |
assign(beg,end); | 将【beg, end)区间中的数据拷贝赋值给本身 |
assign(n, elem); | 将n个elem拷贝赋值给本身 |
示例:
#include
void printDeque(const deque<int> &d);
void test01()
{
deque<int> d1;
for (int i = 0; i < 10; i++)
d1.push_back(i);
printDeque(d1);
//重载 =
deque<int>d2;
d2 = d1;
printDeque(d2);
deque<int>d3;
d3.assign(d1.begin(), d1.end());
printDeque(d3);
deque<int>d4;
d4.assign(10, 8);
printDeque(d4);
}
--------------------------------
0 1 2 3 4 5 6 7 8 9
0 1 2 3 4 5 6 7 8 9
0 1 2 3 4 5 6 7 8 9
8 8 8 8 8 8 8 8 8 8
功能描述:对deque容器的大小进行操作
函数原型:
函数原型 | 注释 |
---|---|
deque.empty(); | 判断容器是否为空 |
deque.size(); | 返回容器中元素的个数 |
deque.resize(num); | 重新指定容器的长度为num,若容器变长,则以默认值填充新位置;若容器变短,则末尾超出容器长度的元素被删除。 |
deque.resize(num, elem); | 重新指定容器的长度为num,若容器变长,则以elem重新填充新位置;若容器变短,则末尾超过容器长度的元素被删除。 |
示例:
void test01()
{
deque<int> d1;
for (int i = 0; i < 10; i++)
d1.push_back(i);
printDeque(d1);
if (d1.empty())
cout << "d1为空" << endl;
else
{
cout << "d1不为空" << endl;
//deque没有容量的概念,因为可以无限放数据
cout << "d1大小为:" << d1.size() << endl;
}
//重新指定大小
d1.resize(15, 88);
printDeque(d1);
d1.resize(5);
printDeque(d1);
}
-----------------------------------------
0 1 2 3 4 5 6 7 8 9
d1不为空
d1大小为:10
0 1 2 3 4 5 6 7 8 9 88 88 88 88 88
0 1 2 3 4
请按任意键继续. . .
总结:
功能描述:向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)区间的数据,无返回值 |
clear(); | 清空容器的所有数据 |
erase(beg, end); | 删除【beg, end)区间的数据,返回下一个数据的位置 |
erase(pos); | 删除pos位置的数据,返回下一个数据的位置 |
示例:
void test01()
{
deque<int>d1;
//尾插
d1.push_back(10);
d1.push_back(20);
//头插
d1.push_front(100);
d1.push_front(200);
printDeque(d1);
//尾删
d1.pop_back();
printDeque(d1);
//头删
d1.pop_front();
printDeque(d1);
}
----------------------
200 100 10 20
200 100 10
100 10
请按任意键继续. . .
void test02()
{
deque<int>d1;
d1.push_back(10);
d1.push_back(20);
d1.push_front(100);
d1.push_front(200);
printDeque(d1);
//insert插入
d1.insert(d1.begin(), 88);
printDeque(d1);
d1.insert(d1.begin(), 2, 88);
printDeque(d1);
//按照区间进行插入
deque<int>d2;
d2.push_back(1);
d2.push_back(2);
d2.push_back(3);
d1.insert(d1.begin(), d2.begin(), d2.end());
printDeque(d1); //1 2 3 88 88 88 200 100 10 20
}
-----------------------
200 100 10 20
88 200 100 10 20
88 88 88 200 100 10 20
1 2 3 88 88 88 200 100 10 20
请按任意键继续. . .
void test03()
{
deque<int>d1;
d1.push_back(10);
d1.push_back(20);
d1.push_front(100);
d1.push_front(200);
printDeque(d1);
//删除
//d1.erase(d1.begin());
deque<int>::iterator it = d1.begin();
it++; //迭代器向后偏移一位,完成删除第二个元素的作用
d1.erase(it);
printDeque(d1);
//按照区间删除
d1.erase(d1.begin(), d1.end()); //相当于d1.clear()
printDeque(d1);
}
---------------------------
200 100 10 20
200 10 20
请按任意键继续. . .
功能描述:对deque中的数据的存取操作
函数原型:
函数原型 | 注释 |
---|---|
at(int idx); | 返回索引idx所指的数据 |
operator[]; | 返回索引idx所指的数据 |
front(); | 返回容器中第一个数据元素 |
back(); | 返回容器中最后一个数据元素 |
示例:
void test01()
{
deque<int>d;
d.push_back(10);
d.push_back(20);
d.push_back(30);
d.push_front(8);
d.push_front(88);
d.push_front(888);
//通过[]方式访问元素
for (int i = 0; i < d.size(); i++)
{
cout << d[i] << " ";
}
cout << endl; //888 88 8 10 20 30
//通过at方式访问元素
for (int i = 0; i < d.size(); i++)
{
cout << d.at(i) << " ";
}
cout << endl; //888 88 8 10 20 30
cout << "第一个元素为:" << d.front() << endl;
cout << "最后一个元素为:" << d.back() << endl;
}
功能描述:利用算法实现对deque容器进行排序
算法:
sort(iterator beg,iterator end); //对beg和end区间元素进行排序
示例:
#include //标准算法头文件
void printDeque(const deque<int>&d)
{
for (deque<int>::const_iterator it = d.begin(); it != d.end(); it++)
cout << *it << " ";
cout << endl;
}
void test01()
{
deque<int>d;
d.push_back(10);
d.push_back(20);
d.push_back(30);
d.push_front(100);
d.push_front(200);
d.push_front(300);
//打印
printDeque(d);
sort(d.begin(),d.end());
cout << "排序后结果:" << endl;
printDeque(d);
}
------------------------
300 200 100 10 20 30
排序后结果:
10 20 30 100 200 300
请按任意键继续. . .
总结:对于支持随机访问的迭代器的容器,都可以利用sort算法直接对其排序,eg:vector
stack是一种先进后出(FILO)的数据结构,它只有一个出口
栈中只有顶端的元素才可以被外界使用,因此栈不允许有遍历行为
入栈:栈中进入数据push
出栈:弹出数据pop
功能描述:栈容器常用的对外接口
构造函数:
函数 | 注释 |
---|---|
stack stk; | stack采用模板类实现,stack对象的默认构造形式 |
stack(const stack &stk); | 拷贝构造函数 |
赋值操作:
函数 | 注释 |
---|---|
stack& operator = (const stack &stk); | 重载等号操作符 |
数据存取:
函数 | 注释 |
---|---|
push(elem); | 向栈顶添加元素 |
pop(); | 从栈顶移除第一个元素 |
top(); | 返回栈顶元素 |
大小操作:
函数 | 注释 |
---|---|
empty(); | 判断栈顶是否为空 |
size(); | 返回栈的大小 |
示例:
using namespace std;
void test01()
{
stack<int>s;
//入栈
s.push(10);
s.push(20);
s.push(30);
s.push(40);
cout << "栈的大小为:" << s.size() << endl;
//只要栈不为空,查看栈顶并且执行出栈操作
while (!s.empty())
{
cout << "栈顶元素为:" << s.top() << endl;
//出栈
s.pop();
}
cout << "栈的大小为:" << s.size() << endl;
}
-------------------
栈的大小为:4
栈顶元素为:40
栈顶元素为:30
栈顶元素为:20
栈顶元素为:10
栈的大小为:0
请按任意键继续. . .
queue是 一种先进先出(FIFO)的数据结构,它有两个出口
队列容器允许从一端新增元素,从另一端移除元素
队列中只有队头和队尾才可以被外界使用,因此队列不允许遍历行为
入队:队列中进数据push
出队:队列中出数据pop
功能描述:队列容器常用的对外接口
构造函数:
函数 | 注释 |
---|---|
queue que; | queue采用模板类实现,queue对象的默认构造形式 |
queue(const queue &que); | 拷贝构造函数 |
赋值操作:
函数 | 注释 |
---|---|
queue& operator = (const queue &que); | 重载等号操作符 |
数据存取:
函数 | 注释 |
---|---|
push(elem); | 往队尾添加元素 |
pop(); | 从队头移除第一个元素 |
back(); | 返回最后一个元素 |
front(); | 返回第一个元素 |
大小操作:
函数 | 注释 |
---|---|
empty(); | 判断栈是否为空 |
size(); | 返回栈的大小 |
示例:
using namespace std;
class Person
{
public:
Person(string name, int age)
{
this->m_name = name;
this->age = age;
}
string m_name;
int age;
};
void test01()
{
//创建队列容器
queue<Person>q;
Person p1("楚子航", 23);
Person p2("夏弥", 21);
Person p3("凯撒", 25);
Person p4("诺诺", 22);
//入队
q.push(p1);
q.push(p2);
q.push(p3);
q.push(p4);
//判断只要队列不为空,查看队头,查看队尾,出队
while (!q.empty())
{
cout << "队头姓名:" << q.front().m_name << "年龄:" << q.front().age << endl;
cout << "队尾姓名:" << q.back().m_name << "年龄:" << q.back().age << endl;
//出队
q.pop();
}
cout << "队列的大小:" << q.size() << endl;
}
---------------------------
队头姓名:楚子航 年龄:23
队尾姓名:诺诺 年龄:22
队头姓名:夏弥 年龄:21
队尾姓名:诺诺 年龄:22
队头姓名:凯撒 年龄:25
队尾姓名:诺诺 年龄:22
队头姓名:诺诺 年龄:22
队尾姓名:诺诺 年龄:22
队列的大小:0
请按任意键继续. . .
功能:将数据进行链式存储
链表是一种物理存储单元上非连续的存储结构,数据元素的逻辑顺序是通过链表中的指针链接实现的
链表的组成:链表是由一系列结点组成
结点的组成:一个是存储数据元素的数据域,另一个是存储下一个结点地址的指针域
STL中的链表是一个双向循环链表
由于链表的存储方式并不是连续的内存空间,因此list的迭代器只支持前移和后移,属于双向迭代器
list还有个重要的性质,插入和删除操作并不会造成原有list迭代器的失效,这在vector是不成立的
list优缺点:
优点:
缺点:
功能描述:创建list容器
函数原型 | 注释 |
---|---|
list lst; | list采用模板类实现对象的默认构造形式 |
list |
构造函数将【beg, end) 区间中的元素拷贝给本身 |
list(n,elem); | 构造函数将n个elem拷贝给本身 |
list(const list &lst); | 拷贝构造函数 |
示例:
void printList(const list<int> &L)
{
for (list<int>::const_iterator it = L.begin(); it != L.end(); it++)
{
cout << *it << " ";
}
cout << endl;
}
void test01()
{
list<int>L1;
L1.push_back(10);
L1.push_back(20);
L1.push_back(30);
L1.push_back(40);
//遍历容器
printList(L1);
//区间方式构造
list<int>L2(L1.begin(), L1.end());
printList(L2);
//拷贝构造
list<int>L3(L1);
printList(L3);
list<int>L4(8, 88);
printList(L4);
}
----------------------------
10 20 30 40
10 20 30 40
10 20 30 40
88 88 88 88 88 88 88 88
请按任意键继续. . .
功能描述:给list容器进行赋值,以及交换list容器
函数原型:
函数原型 | 注释 |
---|---|
assign(beg, end); | 将[beg,end)区间中的数据拷贝赋值给本身 |
assign(n, elem); | 将n个elem拷贝赋值给本身 |
list & operator = (const list &lst); | 重载等号操作符 |
swap(lst); | 将list与本身的元素互换 |
示例:
void test01()
{
list<int>L1;
L1.push_back(10);
L1.push_back(20);
L1.push_back(30);
L1.push_back(40);
printList(L1);
list<int>L2;
L2 = L1;
printList(L2);
list<int>L3;
L3.assign(L2.begin(), L2.end());
printList(L3);
list<int>L4;
L4.assign(8, 88);
printList(L4);
}
//交换
void test02()
{
list<int>L1;
L1.push_back(10);
L1.push_back(20);
L1.push_back(30);
L1.push_back(40);
list<int>L2;
L2.assign(8, 88);
cout << "交换前:" << endl;
printList(L1);
printList(L2);
L1.swap(L2);
cout << "交换后:" << endl;
printList(L1);
printList(L2);
}
-----------------
交换前:
10 20 30 40
88 88 88 88 88 88 88 88
交换后:
88 88 88 88 88 88 88 88
10 20 30 40
请按任意键继续. . .
功能描述:对list容器的大小进行操作
函数原型:
函数原型 | 注释 |
---|---|
size(); | 返回容器中元素的个数 |
empty(); | 判断容器是否为空 |
resize(num); | 重新指定容器的长度为num,若容器变长,则以默认值重新填充新位置,如果容器变短,则末尾超出容器长度的元素被删除 |
resize(num, elem); | 重新指定容器的长度为num,若容器变长,则以elem值填充新位置,若容器变短,则末尾超出容器长度的元素被删除 |
示例:
void test01()
{
list<int>l1;
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);
printList(l1);
l1.resize(2);
printList(l1);
}
---------
10 20 30 40
l1不为空
l1中元素个数为:4
10 20 30 40 0 0 0 0 0 0
10 20
请按任意键继续. . .
功能描述:对list容器进行数据的插入和删除
函数原型:
函数原型 | 注释 |
---|---|
push_back(elem); | 在容器尾部加入一个元素 |
push_back( ); | 删除容器中最后一个元素 |
push_front(elem); | 在容器开头插入一个元素 |
push_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值匹配的元素 |
示例:
void test01()
{
list<int>L;
//尾插
L.push_back(10);
L.push_back(20);
L.push_back(30);
//头插
L.push_front(100);
L.push_front(200);
L.push_front(300);
printList(L);
//尾删
L.pop_back();
printList(L); //300 200 100 10 20
//头删
L.pop_front();
printList(L); //200 100 10 20
//insert插入
L.insert(L.begin(), 88);
printList(L); //88 200 100 10 20
list<int>::iterator it = L.begin();
L.insert(++it, 8888);
printList(L); //88 8888 200 100 10 20
//删除
it = L.begin();
L.erase(it);
printList(L); //8888 200 100 10 20
//移除
L.push_back(10000);
L.push_back(10000);
L.push_back(10000);
printList(L); //8888 200 100 10 20 10000 10000 10000
L.remove(10000);
printList(L); //8888 200 100 10 20
L.clear();
printList(L);
}
功能描述:对list容器数据进行存取
函数原型:
函数原型 | 注释 |
---|---|
front(); | 返回第一个元素 |
back(); | 返回最后一个元素 |
示例:
void test01()
{
listL1;
L1.push_back(10);
L1.push_back(20);
L1.push_back(30);
L1.push_back(40);
//不可以用中括号和at()方式访问list容器中的元素、
//原因是因为list本质是链表,不是用连续性空间存储数据,迭代器也不支持随机访问
cout << "第一个元素是:" << L1.front() << endl;
cout << "最后一个元素是:" << L1.back() << endl;
}
功能描述:将容器中的元素反转,以及将容器中的数据进行排序
函数原型:
函数原型 | 注释 |
---|---|
reverse(); | 反转排序 |
sort(); | 链表排序 |
示例:
void printList(const list<int>&L)
{
for (list<int>::const_iterator it = L.begin(); it != L.end(); it++)
{
cout << *it << " ";
}
cout << endl;
}
//提供sort重载函数
bool myCompare(int v1,int v2)
{
//降序:就让第一个数>第二个数
return v1 > v2;
}
void test01()
{
list<int>L1;
L1.push_back(20);
L1.push_back(50);
L1.push_back(40);
L1.push_back(30);
L1.push_back(220);
L1.push_back(1);
cout << "反转前:";
printList(L1);
//反转后
cout << "反转后:";
L1.reverse();
printList(L1);
//排序
//不支持随机访问迭代器的容器,内部会支持对应的一些算法
cout << "排序后:";
L1.sort(); //默认升序
printList(L1);
cout << "降序:";
L1.sort(myCompare);
printList(L1);
}
----------------------
反转前:20 50 40 30 220 1
反转后:1 220 30 40 50 20
排序后:1 20 30 40 50 220
降序:220 50 40 30 20 1
请按任意键继续. . .
案例描述:将Person自定义数据类型进行排序,Person属性中有姓名,年龄,身高
排序规则:按照年龄进行升序,如果年龄相同则按照身高排序
示例:
class Person
{
public:
Person(string name, int age, int height)
{
this->m_name = name;
this->m_age = age;
this->m_height = height;
}
string m_name;
int m_age;
int m_height;
};
//指定排序规则
bool myCompare(Person &p1,Person &p2)
{
//年龄相同,按照身高进行降序
if (p1.m_age == p2.m_age)
{
return p1.m_height > p2.m_height;
}
else
{
//按照年龄升序
return p1.m_age < p2.m_age;
}
}
void test01()
{
list<Person> L;
Person p1("楚子航", 22, 188);
Person p2("夏弥", 21, 168);
Person p3("凯撒", 24, 192);
Person p4("诺诺", 23, 171);
Person p5("绘梨衣", 19, 165);
Person p6("路明非", 22, 183);
//向容器中插入数据
L.push_back(p1);
L.push_back(p2);
L.push_back(p3);
L.push_back(p4);
L.push_back(p5);
L.push_back(p6);
cout << "排序前:" << endl;
for (list<Person>::iterator it = L.begin(); it != L.end(); it++)
{
cout << "姓名:" << (*it).m_name << " "
<< "\t年龄:" << (*it).m_age << " "
<< "\t身高:" << (*it).m_height << endl;
}
cout << "排序后:" << endl;
L.sort(myCompare);
for (list<Person>::iterator it = L.begin(); it != L.end(); it++)
{
cout << "姓名:" << (*it).m_name << " "
<< "\t年龄:" << (*it).m_age << " "
<< "\t身高:" << (*it).m_height << endl;
}
}
-----------------------
排序前:
姓名:楚子航 年龄:22 身高:188
姓名:夏弥 年龄:21 身高:168
姓名:凯撒 年龄:24 身高:192
姓名:诺诺 年龄:23 身高:171
姓名:绘梨衣 年龄:19 身高:165
姓名:路明非 年龄:22 身高:183
排序后:
姓名:绘梨衣 年龄:19 身高:165
姓名:夏弥 年龄:21 身高:168
姓名:楚子航 年龄:22 身高:188
姓名:路明非 年龄:22 身高:183
姓名:诺诺 年龄:23 身高:171
姓名:凯撒 年龄:24 身高:192
请按任意键继续. . .